在多级索引中使用pandas apply函数

10

我希望能够在多级索引的数据框中应用一个函数(主要是groupby describe数据框),而不使用for循环来遍历0级索引。

我想要应用的函数:

def CI(x):
    import math
    sigma = x["std"]
    n = x["count"]
    return 1.96 * sigma / math.sqrt(n)

我的数据框的样本:

df = df.iloc[47:52, [3,4,-1]]

               a          b                    id
47          0.218182   0.000000  0d1974107c6731989c762e96def73568
48          0.000000   0.000000  0d1974107c6731989c762e96def73568
49          0.218182   0.130909  0d1974107c6731989c762e96def73568
50          0.000000   0.000000  0fd4f3b4adf43682f08e693a905b7432
51          0.000000   0.000000  0fd4f3b4adf43682f08e693a905b7432

我会将零替换为 NaN:

df = df.replace(float(0), np.nan)

根据id和描述来分组并获取多层索引:

df_group = df.groupby("id").describe()

我认为当前的解决方案不太好,需要改进:

l_df = []
for column in df_group.columns.levels[0]:
    df = pd.DataFrame({"CI" : df_group[column].apply(CI, axis = 1)})
    l_df.append(df)
CI = pd.concat(l_df, axis = 1)
CI.columns = df_group.columns.levels[0]

所以我得到了这样的东西:
                                    a       b
id
06f32e6e45da385834dac983256d59f3    nan     nan
0d1974107c6731989c762e96def73568    0.005   0.225
0fd4f3b4adf43682f08e693a905b7432    0.008   nan
11e0057cdc8b8e1b1cdabfa8a092ea5f    0.018   0.582
120549af6977623bd01d77135a91a523    0.008   0.204

所以,如果我的顶级列从a到z,每个都包含std和count列,我如何同时将我的函数应用于这些列?

谢谢约翰的回复。这是一个更简短的解决方案,但原则上它只是重新表述了我的解决方案。我想知道在 pandas 中是否有一种方法可以在多级索引级别上进行操作,而不需要使用 for 循环或列表推导式。 - LostBoardOnTaurangaBeach
1个回答

9
使用groupbyaxis=1level进行分组,可以在第一列级别上进行迭代和应用。
In [104]: (df.groupby("id").describe()
             .groupby(level=0, axis=1)
             .apply(lambda x: x[x.name].apply(CI, axis=1)))
Out[104]:
                                    a   b
id
0d1974107c6731989c762e96def73568  0.0 NaN
0fd4f3b4adf43682f08e693a905b7432  NaN NaN

事实上,如果你愿意,你并不需要使用 CI

In [105]: (df.groupby("id").describe()
             .groupby(level=0, axis=1).apply(lambda x: x[x.name]
             .apply(lambda x: 1.96*x['std']/np.sqrt(x['count']), axis=1)))
Out[105]:
                                    a   b
id
0d1974107c6731989c762e96def73568  0.0 NaN
0fd4f3b4adf43682f08e693a905b7432  NaN NaN

示例 df

In [106]: df
Out[106]:
           a         b                                id
47  0.218182       NaN  0d1974107c6731989c762e96def73568
48       NaN       NaN  0d1974107c6731989c762e96def73568
49  0.218182  0.130909  0d1974107c6731989c762e96def73568
50       NaN       NaN  0fd4f3b4adf43682f08e693a905b7432
51       NaN       NaN  0fd4f3b4adf43682f08e693a905b7432

1
谢谢您的回答。我可以问一下您是如何将结果打印到StackOverflow上的吗?因为当我尝试从Jupyter笔记本中复制时,格式会混乱,我不得不手动进行很多更正。 - LostBoardOnTaurangaBeach
1
阅读 https://meta.stackexchange.com/questions/216464/how-to-insert-code-properly-on-stack-overflow 和 https://dev59.com/O2Ij5IYBdhLWcg3wk182。 - Zero

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