【问题标题】: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

谢谢

【问题讨论】:

    标签: python python-2.7 pandas dataframe


    【解决方案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)
    

    希望有帮助!

    【讨论】:

    【解决方案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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-15
      • 1970-01-01
      • 1970-01-01
      • 2015-10-25
      相关资源
      最近更新 更多