对Pandas Dataframe 的不同列执行聚合操作的矢量化

e5nqia27  于 2023-01-15  发布在  其他
关注(0)|答案(1)|浏览(106)

我有一个Pandas Dataframe ,大部分包含布尔列。一个小例子是:

import pandas as pd

df = pd.DataFrame({"A": [1, 2, 3, 1, 2, 3],
                   "B": ['a', 'b', 'c', 'a', 'b', 'c'],
                   "f1": [True, True, True, True, True, False],
                   "f2": [True, True, True, True, False, True],
                   "f3": [True, True, True, False, True, True],
                   "f4": [True, True, False, True, True, True],
                   "f5": [True, False, True, True, True, True],
                   "target1": [True, False, True, True, False, True],
                   "target2": [False, True, True, False, True, False]})

df

输出:

A   B   f1      f2      f3      f4      f5    target1  target2
0   1   a   True    True    True    True    True    True    False
1   2   b   True    True    True    True    False   False   True
2   3   c   True    True    True    False   True    True    True
3   1   a   True    True    False   True    True    True    False
4   2   b   True    False   True    True    True    False   True
5   3   c   False   True    True    True    True    True    False

对于每个f列的每个True和False类以及("A", "B")列中的所有组,我想对target1target2列求和。

for col in ["f1", "f2", "f3", "f4", "f5"]:
    print(col, "\n", 
          df[df[col]].groupby(["A", "B"]).agg({"target1": "sum", "target2": "sum"}), "\n",
          df[~df[col]].groupby(["A", "B"]).agg({"target1": "sum", "target2": "sum"}))

现在,我需要在不使用for循环的情况下执行此操作;我的意思是对f列进行向量化,以减少计算时间(计算时间应该几乎等于对一个f列进行向量化所需的时间)。

mkshixfv

mkshixfv1#

使用DataFrame.melt,因此可以按列名fvalueTrue/False进行聚合:

df = df.melt(['A','B','target1','target2'])

df1 = df.groupby(["A", "B","variable","value"]).agg({"target1": "sum", "target2": "sum"})
print (df1)
                    target1  target2
A B variable value                  
1 a f1       True         2        0
    f2       True         2        0
    f3       False        1        0
             True         1        0
    f4       True         2        0
    f5       True         2        0
2 b f1       True         0        2
    f2       False        0        1
             True         0        1
    f3       True         0        2
    f4       True         0        2
    f5       False        0        1
             True         0        1
3 c f1       False        1        0
             True         1        1
    f2       True         2        1
    f3       True         2        1
    f4       False        1        1
             True         1        0
    f5       True         2        1

然后可以通过以下方式进行选择:

print (df1.query("variable=='f1' and value==True").droplevel([-1,-2]))
     target1  target2
A B                  
1 a        2        0
2 b        0        2
3 c        1        1

或者:

idx = pd.IndexSlice
print (df1.loc[idx[:, :, 'f1', True],:].droplevel([-1,-2]))
     target1  target2
A B                  
1 a        2        0
2 b        0        2
3 c        1        1

相关问题