python - 多索引 Pandas Dataframe 划分

标签 python pandas multi-index

考虑一个多索引数据框:

import numpy as np
import pandas as pd

df1 = pd.DataFrame(np.random.rand(3, 3), index=['a', 'b', 'c'], columns=['col1', 'col2', 'col3'])
df2 = pd.DataFrame(np.random.rand(3, 3), index=['a', 'b', 'c'], columns=['col1', 'col2', 'col3'])
df3 = pd.DataFrame(np.random.rand(3, 3), index=['a', 'b', 'c'], columns=['col1', 'col2', 'col3'])
df = pd.concat([df1, df2, df3], axis=0, keys=['A', 'B', 'C'])

这给出了df:

            col1        col2        col3
A   a   0.893752    0.554021    0.492867
    b   0.319270    0.263366    0.542281
    c   0.082265    0.635637    0.796405
B   a   0.954748    0.684624    0.488293
    b   0.485414    0.966693    0.211348
    c   0.411648    0.989666    0.028412
C   a   0.701327    0.025172    0.320882
    b   0.073527    0.060885    0.111406
    c   0.169269    0.627686    0.438393

(您的数字会有所不同)

我该怎么办:

  • 将行 (A, b) 和 (A, c) 除以 (A, a)
  • 将行 (B, b) 和 (B, c) 除以 (B, a)
  • 将行 (C, b) 和 (C, c) 除以 (C, a)

...一次调用?

我的尝试:

idx = pd.IndexSlice
ratio_list = [df.loc[idx[x,:], :].div(df.loc[idx[x,'a'], :]) for x in ['A', 'B', 'C']]
ratio = pd.concat(ratio_list, axis=0)

这给出了比率:

            col1        col2        col3
A   a   1.000000    1.000000    1.000000
    b   0.357225    0.475371    1.100259
    c   0.092044    1.147315    1.615864
B   a   1.000000    1.000000    1.000000
    b   0.508422    1.412005    0.432830
    c   0.431159    1.445560    0.058186
C   a   1.000000    1.000000    1.000000
    b   0.104840    2.418784    0.347188
    c   0.241355    24.936324   1.366214

请参阅以下来自 @Smordy 和 @ouoboros1 的回答。两者都很棒。 groupby-transform 更简洁,但是当数据帧很大时,np.repeat 的性能肯定更高。

nrow = 100  # iterate through this
df = df = pd.DataFrame(np.random.rand(nrow*3, 3), 
                       columns=['col1', 'col2', 'col3'],
                       index=pd.MultiIndex.from_product([[*'ABC'], ['row' + str(ii) for ii in range(0, nrow)]]))

# pandas `groupby-transform` from @Smordy
%timeit df.div(df.groupby(level=0).transform('first'))

# `numpy.repeat` from @ouroboros1 
%timeit df.div(np.repeat(df.loc[(slice(None), ['row0']), :].to_numpy(), nrow, axis=0))

结果:

enter image description here

这里时间因子似乎稳定在 3 倍左右。如果我们增加列数,时间因子将再次上升。

最佳答案

您可以通过使用 groupbytransform 来更有效地尝试

result = df.div(df.groupby(level=0).transform('first'))

关于python - 多索引 Pandas Dataframe 划分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76722678/

相关文章:

python - Pandas reshape 数据

python - 删除分层索引中的 Pandas 顶级列

python - 如何在特定级别为多索引列添加前缀?

python - Pandas 多索引数据帧: replace certain values by values from other column on 2nd level

python - CsvReader 下一个函数

python - Pandas : how to add Column name on dataframe on csv file

Python:具有不同颜色节点的网络 Spring 布局

python - 如何在正在运行的 doctest 中使用 ipython 的 IPShellEmbed

python - 从扫描文档opencv python中提取内衬表

python - 如何从数据框列中提取与列表的精确匹配?