¿Cómo encuentra las principales correlaciones en una matriz de correlación con Pandas? Hay muchas respuestas sobre cómo hacer esto con R ( Mostrar correlaciones como una lista ordenada, no como una matriz grande o una forma eficiente de obtener pares altamente correlacionados de un conjunto de datos grande en Python o R ), pero me pregunto cómo hacerlo. con pandas? En mi caso, la matriz es 4460x4460, así que no puedo hacerlo visualmente.
python
pandas
correlation
Kyle Brandt
fuente
fuente
La respuesta de @ HYRY es perfecta. Simplemente construyendo sobre esa respuesta agregando un poco más de lógica para evitar duplicaciones y autocorrelaciones y una clasificación adecuada:
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))
Eso da el siguiente resultado:
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
fuente
au_corr = au_corr.drop(labels=labels_to_drop).sort_values(ascending=False)
:# -- partial selection or non-unique index
Solución de pocas líneas sin pares de variables redundantes:
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
Luego, puede iterar a través de los nombres de los pares de variables (que son múltiples índices de pandas.Series) y sus valores como este:
for index, value in sol.items(): # do some staff
fuente
os
como nombre de variable porque enmascara elos
desdeimport os
si está disponible en el códigoCombinando algunas características de las respuestas de @HYRY y @ arun, puede imprimir las correlaciones principales para el marco de datos
df
en una sola línea usando:Nota: la única desventaja es que si tiene correlaciones 1.0 que no son una variable en sí misma, la
drop_duplicates()
adición las eliminaríafuente
drop_duplicates
eliminaría todas las correlaciones que son iguales?v1
av2
yv3
av4
) no sería exactamente la mismaUtilice el siguiente código para ver las correlaciones en orden descendente.
# See the correlations in descending order corr = df.corr() # df is the pandas dataframe c1 = corr.abs().unstack() c1.sort_values(ascending = False)
fuente
corr = df.corr()
Puede hacerlo gráficamente de acuerdo con este sencillo código sustituyendo sus datos.
corr = df.corr() kot = corr[corr>=.9] plt.figure(figsize=(12,8)) sns.heatmap(kot, cmap="Greens")
fuente
Muchas buenas respuestas aquí. La forma más fácil que encontré fue una combinación de algunas de las respuestas anteriores.
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()
fuente
Úselo
itertools.combinations
para obtener todas las correlaciones únicas de la propia matriz de correlación de los pandas.corr()
, generar una lista de listas y retroalimentarla en un DataFrame para usar '.sort_values'. Conjuntoascending = True
para mostrar las correlaciones más bajas en la parte superiorcorrank
toma un DataFrame como argumento porque requiere.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)
fuente
Yo no queria
unstack
complicar demasiado este problema, ya que solo quería eliminar algunas funciones altamente correlacionadas como parte de una fase de selección de funciones.Así que terminé con la siguiente solución 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])
En este caso, si desea eliminar características correlacionadas, puede mapear a través de la
corr_cols
matriz filtrada y eliminar las indexadas impares (o indexadas pares).fuente
corr_cols = corr.max().sort_values(ascending=False)
acorr_cols = corr.unstack()
Me gustó más la publicación de Addison Klinke, por ser la más simple, pero usé la sugerencia de Wojciech Moszczyńsk para filtrar y trazar gráficos, pero extendí el filtro para evitar valores absolutos, así que dada una matriz de correlación grande, fíltrala, grafica y luego aplana:
Creado, filtrado y graficado
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()
Función
Al final, creé una pequeña función para crear la matriz de correlación, filtrarla y luego aplanarla. Como idea, podría extenderse fácilmente, por ejemplo, límites superior e inferior asimé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)
fuente
Estaba probando algunas de las soluciones aquí, pero luego se me ocurrió la mía propia. Espero que esto pueda ser útil para el próximo, así que lo comparto aquí:
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)
fuente
Este es un código mejorado de @MiFi. Este orden en abs pero sin excluir los 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)
fuente
La siguiente función debería funcionar. Esta implementación
y también es configurable para que pueda mantener tanto las autocorrelaciones como los duplicados. También puede informar sobre tantos pares de características como desee.
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
fuente