tablas - pandas python
correlación de columnas de pandas con significación estadística (4)
Puede usar las funciones de correlación scipy.stats para obtener el valor p.
Por ejemplo, si está buscando una correlación tal como la correlación Pearson, puede usar la función pearsonr .
from scipy.stats import pearsonr
pearsonr([1, 2, 3], [4, 3, 7])
Da salida
(0.7205766921228921, 0.48775429164459994)
Donde el primer valor en la tupla es el valor de correlación, y el segundo es el valor p.
En su caso, puede usar la función dropna
pandas para eliminar primero los valores NaN
.
df_clean = df[[''column1'', ''column2'']].dropna()
pearsonr(df_clean[''column1''], df_clean[''column2''])
¿Cuál es la mejor manera, dado un marco de datos de pandas, df, para obtener la correlación entre sus columnas df.1
y df.2
?
No quiero que el resultado cuente las filas con NaN
, lo que hace la correlación pandas
incorporada. Pero también quiero que pvalue
un pvalue
o un error estándar, que el built-in no pvalue
.
SciPy
parece quedar atrapado por los NaN, aunque creo que informa la importancia.
Ejemplo de datos:
1 2
0 2 NaN
1 NaN 1
2 1 2
3 -4 3
4 1.3 1
5 NaN NaN
He intentado resumir la lógica en una función, puede que no sea el enfoque más eficiente, pero le proporcionará un resultado similar a pandas df.corr (). Para usar esto simplemente ponga la siguiente función en su código y llámela proporcionando su objeto de marco de datos, es decir. corr_pvalue (your_dataframe) .
Redondeé los valores a 4 decimales, en caso de que desee una salida diferente, cambie el valor en la función de redondeo.
def corr_pvalue(df):
from scipy.stats import pearsonr
import numpy as np
import pandas as pd
numeric_df = df.dropna()._get_numeric_data()
cols = numeric_df.columns
mat = numeric_df.values
arr = np.zeros((len(cols),len(cols)), dtype=object)
for xi, x in enumerate(mat.T):
for yi, y in enumerate(mat.T[xi:]):
arr[xi, yi+xi] = map(lambda _: round(_,4), pearsonr(x,y))
arr[yi+xi, xi] = arr[xi, yi+xi]
return pd.DataFrame(arr, index=cols, columns=cols)
Lo he probado con pandas v0.18.1
Para calcular todos los valores p de una vez , puede usar la siguiente función calculate_pvalues
:
df = pd.DataFrame({''A'':[1,2,3], ''B'':[2,5,3], ''C'':[5,2,1], ''D'':[''text'',2,3] })
calculate_pvalues(df)
El resultado es similar al
corr()
(pero con valores p):A B C A 0 0.7877 0.1789 B 0.7877 0 0.6088 C 0.1789 0.6088 0
los valores p se redondean a 4 decimales
- La columna D se ignora ya que contiene texto.
A continuación está el código de la función :
from scipy.stats import pearsonr
import pandas as pd
def calculate_pvalues(df):
df = df.dropna()._get_numeric_data()
dfcols = pd.DataFrame(columns=df.columns)
pvalues = dfcols.transpose().join(dfcols, how=''outer'')
for r in df.columns:
for c in df.columns:
pvalues[r][c] = round(pearsonr(df[r], df[c])[1], 4)
return pvalues
La respuesta proporcionada por @Shashank es agradable. Sin embargo, si quieres una solución en pandas
puros, te puede gustar esto:
import pandas as pd
from pandas.io.data import DataReader
from datetime import datetime
import scipy.stats as stats
gdp = pd.DataFrame(DataReader("GDP", "fred", start=datetime(1990, 1, 1)))
vix = pd.DataFrame(DataReader("VIXCLS", "fred", start=datetime(1990, 1, 1)))
#Do it with a pandas regression to get the p value from the F-test
df = gdp.merge(vix,left_index=True, right_index=True, how=''left'')
vix_on_gdp = pd.ols(y=df[''VIXCLS''], x=df[''GDP''], intercept=True)
print(df[''VIXCLS''].corr(df[''GDP'']), vix_on_gdp.f_stat[''p-value''])
Resultados:
-0.0422917932738 0.851762475093
Los mismos resultados que la función de estadísticas:
#Do it with stats functions.
df_clean = df.dropna()
stats.pearsonr(df_clean[''VIXCLS''], df_clean[''GDP''])
Resultados:
(-0.042291793273791969, 0.85176247509284908)
Para extender a más variables, te doy un enfoque feo basado en bucle:
#Add a third field
oil = pd.DataFrame(DataReader("DCOILWTICO", "fred", start=datetime(1990, 1, 1)))
df = df.merge(oil,left_index=True, right_index=True, how=''left'')
#construct two arrays, one of the correlation and the other of the p-vals
rho = df.corr()
pval = np.zeros([df.shape[1],df.shape[1]])
for i in range(df.shape[1]): # rows are the number of rows in the matrix.
for j in range(df.shape[1]):
JonI = pd.ols(y=df.icol(i), x=df.icol(j), intercept=True)
pval[i,j] = JonI.f_stat[''p-value'']
Resultados de rho:
GDP VIXCLS DCOILWTICO
GDP 1.000000 -0.042292 0.870251
VIXCLS -0.042292 1.000000 -0.004612
DCOILWTICO 0.870251 -0.004612 1.000000
Resultados de pval:
[[ 0.00000000e+00 8.51762475e-01 1.11022302e-16]
[ 8.51762475e-01 0.00000000e+00 9.83747425e-01]
[ 1.11022302e-16 9.83747425e-01 0.00000000e+00]]