Pandas corr() 经常返回 NaN

11

我正在尝试在数据框上运行一个我认为应该是简单的相关函数,但它在我不认为应该的地方返回NaN。

代码:

# setup
import pandas as pd
import io

csv = io.StringIO(u'''
id  date    num
A   2018-08-01  99
A   2018-08-02  50
A   2018-08-03  100
A   2018-08-04  100
A   2018-08-05  100
B   2018-07-31  500
B   2018-08-01  100
B   2018-08-02  100
B   2018-08-03  0
B   2018-08-05  100
B   2018-08-06  500
B   2018-08-07  500
B   2018-08-08  100
C   2018-08-01  100
C   2018-08-02  50
C   2018-08-03  100
C   2018-08-06  300
''')

df = pd.read_csv(csv, sep = '\t')

# Format manipulation
df = df[df['num'] > 50]
df = df.pivot(index = 'date', columns = 'id', values = 'num')
df = pd.DataFrame(df.to_records())

# Main correlation calculations
print df.iloc[:, 1:].corr()

主题 DataFrame:

       A      B      C
0    NaN  500.0    NaN
1   99.0  100.0  100.0
2    NaN  100.0    NaN
3  100.0    NaN  100.0
4  100.0    NaN    NaN
5  100.0  100.0    NaN
6    NaN  500.0  300.0
7    NaN  500.0    NaN
8    NaN  100.0    NaN

corr() 结果:

    A    B    C
A  1.0  NaN  NaN
B  NaN  1.0  1.0
C  NaN  1.0  1.0

根据该函数(有限的)文档,它应该排除“NA/null值”。由于每列存在重叠值,结果难道不应全部为非NaN吗? 这里这里有很好的讨论,但都没有回答我的问题。我尝试了这里讨论的float64方法,但也失败了。
@hellpanderr的评论提出了一个很好的观点,我使用的是0.22.0
附加问题-虽然我不是数学家,但这个结果中B和C之间如何存在1:1的关系?

pandas=0.23.4 gives me [[1.0, nan, 0.9998469895178864], [nan, 1.0, 0.9819805060619657], [0.9998469895178864, 0.9819805060619657, 1.0]] - hellpanderr
我可能稍微调整了一下,我刚刚更新了代码(将> 10改为> 50),这样我发布的结果与之前相同。不确定这是否会对你产生影响。 - elPastor
1
现在我得到了和你一样的结果。 - hellpanderr
如果您尝试使用 df.cov()[['C','B']] / df.std()[['C','B']].product() 手动完成此操作呢? - hellpanderr
现在你进入了我帖子中“我不是数学家”的部分。实际上并不清楚。当涉及到核心统计计算时,我有点超纲了。 - elPastor
经过一些研究(以及这篇帖子:https://stats.stackexchange.com/a/94152),似乎两个包含两个数字数组之间的相关性总是1:1。因此,这回答了奖励问题,但不是主要的NaN问题。 - elPastor
1个回答

14

看起来这个结果是你所处理数据的一个产物。正如你所写的,NA 被忽略了,所以它基本上可以归结为:

df[['B', 'C']].dropna()

       B      C
1  100.0  100.0
6  500.0  300.0

所以,每列只剩下两个值用于计算,这应该会导致相关系数为1

df[['B', 'C']].dropna().corr()

     B    C
B  1.0  1.0
C  1.0  1.0

那么,剩余组合的 NA 从何而来?

df[['A', 'B']].dropna()

       A      B
1   99.0  100.0
5  100.0  100.0


df[['A', 'C']].dropna()

       A      C
1   99.0  100.0
3  100.0  100.0

所以,这里每列最终只有两个值。不同之处在于列 BC 只包含一个值 (100),这会导致标准差为 0

df[['A', 'C']].dropna().std()

A    0.707107
C    0.000000

计算相关系数时,需要除以标准差,这会导致出现NA


4
Cleb,感谢您做了大量的工作,我认为您在关于标准差的最后一部分做得非常好。已接受。 - elPastor
@elPastor:很高兴能帮忙。我应该在这里放一个简短的故障排除部分并引用你的问题。 - Cleb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接