Pandas – Filtrar en todas las columnas

Tengo una matriz de correlación cuadrada en pandas, y estoy tratando de adivinar la forma más eficiente de devolver todos los valores donde el valor (siempre un valor flotante -1 <= x <= 1) está por encima de un cierto umbral.

El método pandas.DataFrame.filter solicita una lista de columnas o un RegEx, pero siempre quiero pasar todas las columnas. ¿Existe alguna práctica recomendada al respecto?

No estoy seguro de cuál es el resultado deseado, ya que no proporcionó una muestra, pero le daré mis dos centavos por lo que haría:

 In[1]: import pandas as pd import numpy as np df = pd.DataFrame(np.random.rand(10,5)) corr = df.corr() corr.shape Out[1]: (5, 5) 

Ahora, extraigamos el triángulo superior de la matriz de correlación (es simétrica), excluyendo la diagonal . Para esto vamos a usar np.tril , lo convertiremos en un booleano y obtendremos lo contrario utilizando el operador ~ .

 In [2]: corr_triu = corr.where(~np.tril(np.ones(corr.shape)).astype(np.bool)) corr_triu Out[2]: 0 1 2 3 4 0 NaN 0.228763 -0.276406 0.286771 -0.050825 1 NaN NaN -0.562459 -0.596057 0.540656 2 NaN NaN NaN 0.402752 0.042400 3 NaN NaN NaN NaN -0.642285 4 NaN NaN NaN NaN NaN 

Ahora apilemos esto y filtremos todos los valores que están por encima de 0.3 por ejemplo:

 In [3]: corr_triu = corr_triu.stack() corr_triu[corr_triu > 0.3] Out[3]: 1 4 0.540656 2 3 0.402752 dtype: float64 

Si quieres hacerlo un poco más bonito:

 In [4]: corr_triu.name = 'Pearson Correlation Coefficient' corr_triu.index.names = ['Col1', 'Col2'] In [5]: corr_triu[corr_triu > 0.3].to_frame() Out[5]: Pearson Correlation Coefficient Col1 Col2 1 4 0.540656 2 3 0.402752 

Hay dos maneras de hacer esto:

Suponer:

 In [7]: c = np.array([-1,-2,-2,-3,-4,-6,-7,-8]) In [8]: a = np.array([1,2,3,4,6,7,8,9]) In [9]: b = np.array([2,4,6,8,10,12,13,15]) In [10]: c = np.array([-1,-2,-2,-3,-4,-6,-7,-8]) In [11]: corr = np.corrcoef([a,b,c]) In [12]: df = pd.DataFrame(corr) In [13]: df Out[13]: 0 1 2 0 1.000000 0.995350 -0.980521 1 0.995350 1.000000 -0.971724 2 -0.980521 -0.971724 1.000000 

Entonces puedes simplemente:

 In [14]: df > 0.5 Out[14]: 0 1 2 0 True True False 1 True True False 2 False False True In [15]: df[df > 0.5] Out[15]: 0 1 2 0 1.00000 0.99535 NaN 1 0.99535 1.00000 NaN 2 NaN NaN 1.0 

Si solo desea los valores, la forma más sencilla es trabajar con las estructuras de datos numpy subyacentes utilizando el atributo de values :

 In [17]: df.values Out[17]: array([[ 1. , 0.99535001, -0.9805214 ], [ 0.99535001, 1. , -0.97172394], [-0.9805214 , -0.97172394, 1. ]]) In [18]: df.values[(df > 0.5).values] Out[18]: array([ 1. , 0.99535001, 0.99535001, 1. , 1. ]) 

En lugar de .values , como lo señala ayhan, puedes usar la stack que automáticamente suelta NaN y también mantiene las tags …

 In [22]: df.index = ['a','b','c'] In [23]: df.columns=['a','b','c'] In [24]: df Out[24]: abc a 1.000000 0.995350 -0.980521 b 0.995350 1.000000 -0.971724 c -0.980521 -0.971724 1.000000 In [25]: df.stack() > 0.5 Out[25]: aa True b True c False ba True b True c False ca False b False c True dtype: bool In [26]: df.stack()[df.stack() > 0.5] Out[26]: aa 1.00000 b 0.99535 ba 0.99535 b 1.00000 cc 1.00000 dtype: float64 

Siempre puedes volver…

 In [29]: (df.stack()[df.stack() > 0.5]).unstack() Out[29]: abc a 1.00000 0.99535 NaN b 0.99535 1.00000 NaN c NaN NaN 1.0