在 Pandas 中是不是有一种 pythonic 的方法来做一个列联表?

Posted

技术标签:

【中文标题】在 Pandas 中是不是有一种 pythonic 的方法来做一个列联表?【英文标题】:Is there a pythonic way to do a contingency table in Pandas?在 Pandas 中是否有一种 pythonic 的方法来做一个列联表? 【发布时间】:2015-07-06 05:48:51 【问题描述】:

给定一个如下所示的数据框:

            A   B      
2005-09-06  5  -2  
2005-09-07 -1   3  
2005-09-08  4   5 
2005-09-09 -8   2
2005-09-10 -2  -5
2005-09-11 -7   9 
2005-09-12  2   8  
2005-09-13  6  -5  
2005-09-14  6  -5  

有没有像这样创建 2x2 矩阵的 Pythonic 方法:

    1  0
 1  a  b
 0  c  d

地点:

a = A 列和 B 列的对应元素均为正数的 obs 数。

b = B 列中 A 列对应元素为正数和负数的 obs 数。

c = obs 的数量,其中 A 列的相应元素在 B 列中为负数和正数。

d = A 列和 B 列对应元素均为负数的 obs 数。

对于本例,输出将是:

    1  0
 1  2  3
 0  3  1

谢谢

【问题讨论】:

【参考方案1】:

使用 pandas 函数crosstab 可能是最简单的。借用上面的Dyno Fu:

import pandas as pd
from StringIO import StringIO
table = """dt          A   B
2005-09-06  5  -2
2005-09-07 -1   3
2005-09-08  4   5
2005-09-09 -8   2
2005-09-10 -2  -5
2005-09-11 -7   9
2005-09-12  2   8
2005-09-13  6  -5
2005-09-14  6  -5
"""
sio = StringIO(table)
df = pd.read_table(sio, sep=r"\s+", parse_dates=['dt'])
df.set_index("dt", inplace=True)

pd.crosstab(df.A > 0, df.B > 0)

输出:

B      False  True 
A                  
False      1      3
True       3      2

[2 rows x 2 columns]

如果您想使用 scipy.stats 等进行 Fisher 精确检验,也可以使用该表:

from scipy.stats import fisher_exact
tab = pd.crosstab(df.A > 0, df.B > 0)
fisher_exact(tab)

【讨论】:

谢谢!感谢您的努力。【参考方案2】:

让我们将您的数据框称为data。试试

a = data['A']>0
b = data['B']>0
data.groupby([a,b]).count() 

【讨论】:

谁否决了这个答案:请发表评论 - 为什么。 这个答案创建了一个具有两个索引的数据框,而不是所需的列联表格式,其中这两个索引分别位于 X 和 Y 轴上【参考方案3】:

这是一个关于 pandas 交叉表功能的非常有用的页面:

https://chrisalbon.com/python/data_wrangling/pandas_crosstabs/

所以我认为你应该使用你想做的事

import pandas as pd
pd.crosstab(data['A']>0, data['B']>0)

希望有帮助!

【讨论】:

更新链接(我认为)chrisalbon.com/python/data_wrangling/pandas_crosstabs【参考方案4】:
import pandas as pd
from StringIO import StringIO

table = """dt          A   B
2005-09-06  5  -2
2005-09-07 -1   3
2005-09-08  4   5
2005-09-09 -8   2
2005-09-10 -2  -5
2005-09-11 -7   9
2005-09-12  2   8
2005-09-13  6  -5
2005-09-14  6  -5
"""
sio = StringIO(table)
df = pd.read_table(sio, sep=r"\s+", parse_dates=['dt'])
df.set_index("dt", inplace=True)

a = df['A'] > 0
b = df['B'] > 0
df1 = df.groupby([a,b]).count()
print df1["A"].unstack()

输出:

B      False  True
A
False      1      3
True       3      2

这只是 lnanenok 的回答,并使用 unstack() 使其更具可读性。功劳应该归于lanenok。

【讨论】:

以上是关于在 Pandas 中是不是有一种 pythonic 的方法来做一个列联表?的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中,是不是有一种方便的方法来重载 C++ 中的方法? [复制]

是否有一种功能可以在维持我的订单的同时将我的数字在 pandas 中四舍五入?

确定一天是不是是 Python / Pandas 中的工作日

Pandas 跨记录扩展 json 字段

python 3中是不是有一种方法可以使两个用户定义的函数只需要输入一次

pandas