Como você encontra as principais correlações em uma matriz de correlação com Pandas? Há muitas respostas sobre como fazer isso com R ( Mostrar correlações como uma lista ordenada, não como uma grande matriz ou maneira eficiente de obter pares altamente correlacionados de grandes conjuntos de dados em Python ou R ), mas estou me perguntando como fazer isso com pandas? No meu caso, a matriz é 4460x4460, então não posso fazer isso visualmente.
python
pandas
correlation
Kyle Brandt
fonte
fonte
A resposta de @HYRY é perfeita. Apenas desenvolvendo essa resposta adicionando um pouco mais de lógica para evitar duplicatas e autocorrelações e classificação adequada:
import pandas as pd d = {'x1': [1, 4, 4, 5, 6], 'x2': [0, 0, 8, 2, 4], 'x3': [2, 8, 8, 10, 12], 'x4': [-1, -4, -4, -4, -5]} df = pd.DataFrame(data = d) print("Data Frame") print(df) print() print("Correlation Matrix") print(df.corr()) print() def get_redundant_pairs(df): '''Get diagonal and lower triangular pairs of correlation matrix''' pairs_to_drop = set() cols = df.columns for i in range(0, df.shape[1]): for j in range(0, i+1): pairs_to_drop.add((cols[i], cols[j])) return pairs_to_drop def get_top_abs_correlations(df, n=5): au_corr = df.corr().abs().unstack() labels_to_drop = get_redundant_pairs(df) au_corr = au_corr.drop(labels=labels_to_drop).sort_values(ascending=False) return au_corr[0:n] print("Top Absolute Correlations") print(get_top_abs_correlations(df, 3))
Isso dá a seguinte saída:
Data Frame x1 x2 x3 x4 0 1 0 2 -1 1 4 0 8 -4 2 4 8 8 -4 3 5 2 10 -4 4 6 4 12 -5 Correlation Matrix x1 x2 x3 x4 x1 1.000000 0.399298 1.000000 -0.969248 x2 0.399298 1.000000 0.399298 -0.472866 x3 1.000000 0.399298 1.000000 -0.969248 x4 -0.969248 -0.472866 -0.969248 1.000000 Top Absolute Correlations x1 x3 1.000000 x3 x4 0.969248 x1 x4 0.969248 dtype: float64
fonte
au_corr = au_corr.drop(labels=labels_to_drop).sort_values(ascending=False)
:# -- partial selection or non-unique index
Solução de poucas linhas sem pares redundantes de variáveis:
corr_matrix = df.corr().abs() #the matrix is symmetric so we need to extract upper triangle matrix without diagonal (k = 1) sol = (corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k=1).astype(np.bool)) .stack() .sort_values(ascending=False)) #first element of sol series is the pair with the biggest correlation
Em seguida, você pode iterar por meio de nomes de pares de variáveis (que são pandas.Series multi-indexes) e seus valores como este:
for index, value in sol.items(): # do some staff
fonte
os
como um nome de variável porque mascara oos
deimport os
se disponível no códigoCombinando alguns recursos das respostas de @HYRY e @arun, você pode imprimir as principais correlações para dataframe
df
em uma única linha usando:Nota: a única desvantagem é se você tiver 1.0 correlações que não são uma variável para si mesmo, a
drop_duplicates()
adição as removeriafonte
drop_duplicates
descartaria todas as correlações que são iguais?v1
parav2
ev3
parav4
) não seria exatamente a mesmaUse o código abaixo para visualizar as correlações em ordem decrescente.
# See the correlations in descending order corr = df.corr() # df is the pandas dataframe c1 = corr.abs().unstack() c1.sort_values(ascending = False)
fonte
corr = df.corr()
Você pode fazer graficamente de acordo com este código simples, substituindo seus dados.
corr = df.corr() kot = corr[corr>=.9] plt.figure(figsize=(12,8)) sns.heatmap(kot, cmap="Greens")
fonte
Muitas respostas boas aqui. A maneira mais fácil que encontrei foi uma combinação de algumas das respostas acima.
corr = corr.where(np.triu(np.ones(corr.shape), k=1).astype(np.bool)) corr = corr.unstack().transpose()\ .sort_values(by='column', ascending=False)\ .dropna()
fonte
Use
itertools.combinations
para obter todas as correlações exclusivas da própria matriz de correlação do pandas.corr()
, gerar uma lista de listas e alimentá-la de volta em um DataFrame para usar '.sort_values'. Definaascending = True
para exibir as correlações mais baixas no topocorrank
leva um DataFrame como argumento porque requer.corr()
.def corrank(X: pandas.DataFrame): import itertools df = pd.DataFrame([[(i,j),X.corr().loc[i,j]] for i,j in list(itertools.combinations(X.corr(), 2))],columns=['pairs','corr']) print(df.sort_values(by='corr',ascending=False)) corrank(X) # prints a descending list of correlation pair (Max on top)
fonte
Eu não queria
unstack
complicar demais esse problema, já que só queria descartar alguns recursos altamente correlacionados como parte de uma fase de seleção de recursos.Então, acabei com a seguinte solução simplificada:
# map features to their absolute correlation values corr = features.corr().abs() # set equality (self correlation) as zero corr[corr == 1] = 0 # of each feature, find the max correlation # and sort the resulting array in ascending order corr_cols = corr.max().sort_values(ascending=False) # display the highly correlated features display(corr_cols[corr_cols > 0.8])
Nesse caso, se você quiser descartar os recursos correlacionados, poderá mapear a
corr_cols
matriz filtrada e remover os de índice ímpar (ou mesmo).fonte
corr_cols = corr.max().sort_values(ascending=False)
paracorr_cols = corr.unstack()
Eu estava tentando algumas das soluções aqui, mas na verdade descobri a minha própria. Espero que isso possa ser útil para o próximo, então eu compartilho aqui:
def sort_correlation_matrix(correlation_matrix): cor = correlation_matrix.abs() top_col = cor[cor.columns[0]][1:] top_col = top_col.sort_values(ascending=False) ordered_columns = [cor.columns[0]] + top_col.index.tolist() return correlation_matrix[ordered_columns].reindex(ordered_columns)
fonte
Este é um código de melhoria de @MiFi. Este pedido em abs, mas não excluindo os valores negativos.
def top_correlation (df,n): corr_matrix = df.corr() correlation = (corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k=1).astype(np.bool)) .stack() .sort_values(ascending=False)) correlation = pd.DataFrame(correlation).reset_index() correlation.columns=["Variable_1","Variable_2","Correlacion"] correlation = correlation.reindex(correlation.Correlacion.abs().sort_values(ascending=False).index).reset_index().drop(["index"],axis=1) return correlation.head(n) top_correlation(ANYDATA,10)
fonte
A função a seguir deve resolver o problema. Esta implementação
e também é configurável para que você possa manter as autocorrelações e também as duplicatas. Você também pode relatar quantos pares de recursos desejar.
def get_feature_correlation(df, top_n=None, corr_method='spearman', remove_duplicates=True, remove_self_correlations=True): """ Compute the feature correlation and sort feature pairs based on their correlation :param df: The dataframe with the predictor variables :type df: pandas.core.frame.DataFrame :param top_n: Top N feature pairs to be reported (if None, all of the pairs will be returned) :param corr_method: Correlation compuation method :type corr_method: str :param remove_duplicates: Indicates whether duplicate features must be removed :type remove_duplicates: bool :param remove_self_correlations: Indicates whether self correlations will be removed :type remove_self_correlations: bool :return: pandas.core.frame.DataFrame """ corr_matrix_abs = df.corr(method=corr_method).abs() corr_matrix_abs_us = corr_matrix_abs.unstack() sorted_correlated_features = corr_matrix_abs_us \ .sort_values(kind="quicksort", ascending=False) \ .reset_index() # Remove comparisons of the same feature if remove_self_correlations: sorted_correlated_features = sorted_correlated_features[ (sorted_correlated_features.level_0 != sorted_correlated_features.level_1) ] # Remove duplicates if remove_duplicates: sorted_correlated_features = sorted_correlated_features.iloc[:-2:2] # Create meaningful names for the columns sorted_correlated_features.columns = ['Feature 1', 'Feature 2', 'Correlation (abs)'] if top_n: return sorted_correlated_features[:top_n] return sorted_correlated_features
fonte
Eu gostei mais da postagem de Addison Klinke, por ser a mais simples, mas usei a sugestão de Wojciech Moszczyńsk para filtrar e mapear, mas estendeu o filtro para evitar valores absolutos, então, dada uma grande matriz de correlação, filtre, crie um gráfico e, em seguida, aplique-a:
Criado, filtrado e mapeado
dfCorr = df.corr() filteredDf = dfCorr[((dfCorr >= .5) | (dfCorr <= -.5)) & (dfCorr !=1.000)] plt.figure(figsize=(30,10)) sn.heatmap(filteredDf, annot=True, cmap="Reds") plt.show()
Função
No final, criei uma pequena função para criar a matriz de correlação, filtrá-la e depois nivelá-la. Como uma ideia, ele poderia ser facilmente estendido, por exemplo, limites superior e inferior assimétricos, etc.
def corrFilter(x: pd.DataFrame, bound: float): xCorr = x.corr() xFiltered = xCorr[((xCorr >= bound) | (xCorr <= -bound)) & (xCorr !=1.000)] xFlattened = xFiltered.unstack().sort_values().drop_duplicates() return xFlattened corrFilter(df, .7)
fonte