【问题标题】:Pandas: Groupby names in index and columnsPandas:索引和列中的分组名称
【发布时间】:2020-04-03 21:28:47
【问题描述】:

我有一个对索引和列都使用 MultiIndex 的数据框。 例如:

df = pd.DataFrame(index=pd.MultiIndex.from_product([[1,2], [1,2,3], [4,5]], names=['i','j', 'k']), columns=pd.MultiIndex.from_product([[1,2], [1,2]], names=['x', 'y']))
for c in df.columns:
    df[c] = np.random.randint(100, size=(12,1))

x       1       2
y       1   2   1   2
i j k
1 1 4  10  13   0  76
    5  92  37  52  40
  2 4  88  77  50  22
    5  75  31  19   1
  3 4  61  23   5  47
    5  43  68  10  21
2 1 4  23  15  17   5
    5  47  68   6  94
  2 4   0  12  24  54
    5  83  27  46  19
  3 4   7  22   5  15
    5   7  10  89  79

我想按索引中的名称和列中的名称对值进行分组。 对于每个这样的组,我们将有一个二维数字数组(而不是一个系列)。我想聚合该二维数组中所有条目的std()

例如,假设我按['i', 'x'] 分组,一组将具有i=1x=1 的值。我想为这些二维数组中的每一个计算std,并生成一个DataFrame,其中i 值作为索引,x 值作为列。

实现这一目标的最佳方法是什么?

如果我使用stack() 来获取x 作为索引,我仍然会计算多个std() 而不是一个,因为仍然会有多个列。

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:

    您可以使用嵌套列表推导。对于您的示例,使用给定类型的 DataFrame (不一样,因为值是随机的;您可能希望修复种子值以便结果具有可比性)和 ix 作为感兴趣的索引,它会这样工作:

    # get values of the top level row index
    rows = set(df.index.get_level_values(0))
    # get values of the top level column index
    columns = set(df.columns.get_level_values(0))
    
    # for every sub-dataframe (every combination of top-level indices) 
    # compute sampling standard deviation (1 degree of freedom) across all values
    df_groupSD = pd.DataFrame([[df.loc[(row, )][(col, )].values.std(ddof=1)  
                                for col in columns] for row in rows], 
                              index = rows, columns = columns)
    
    # show result
    display(df_groupSD)  
    

    输出:

        1           2
    1   31.455115   25.433812
    2   29.421699   33.748962
    

    当然,可能有更好的方法。

    【讨论】:

    • 由于在我的情况下可能有多个级别,并且特定的兴趣级别可能并不总是首先出现,因此我通过这样做使其更通用:df.xs(1, level='i').xs(1, level='x', axis=1) 而不是 .loc基于选择。谢谢。
    • 很高兴我能提供帮助,并感谢您指出更通用的解决方案。
    • 我学到的另一件事是np.nanstd(values) 通常更适合。
    • 好点,如果只是缺少几个值,您仍然希望获得结果。
    【解决方案2】:

    您可以使用stack 将列的“y”级别作为索引,然后groupby 只有 i 才能获取:

    print (df.stack(level='y').groupby(['i']).std())
    x          1          2
    i                      
    1  32.966811  23.933462
    2  28.668825  28.541835
    

    【讨论】:

      【解决方案3】:

      试试下面的代码:

      df.groupby(level=0).apply(lambda grp: grp.stack().std())
      

      【讨论】:

        猜你喜欢
        • 2013-02-21
        • 2017-08-21
        • 2013-08-04
        • 2019-01-12
        • 1970-01-01
        • 2021-08-02
        相关资源
        最近更新 更多