pandas 修改多列的GroupBy

xxb16uws  于 2023-10-14  发布在  其他
关注(0)|答案(2)|浏览(84)

我有一个dataframe,看起来像这样:

Team Division   Q1   Q2   Q3   Q4
0     Flames  Pacific  4.0  1.0  3.0  1.0
1     Flames  Pacific  4.0  1.0  2.0  2.0
2     Oilers  Pacific  3.0  1.0  1.0  3.0
3    Canucks  Pacific  2.0  NaN  4.0  2.0
4   Senators  Eastern  1.0  4.0  4.0  3.0
5      Leats  Eastern  4.0  3.0  4.0  2.0
6      Leats  Eastern  NaN  4.0  4.0  4.0
7    Canucks  Pacific  2.0  2.0  2.0  3.0
8     Oilers  Pacific  3.0  1.0  NaN  4.0
9     Flames  Pacific  3.0  4.0  4.0  3.0
10    Oilers  Pacific  2.0  3.0  1.0  4.0
11    Oilers  Pacific  4.0  NaN  2.0  1.0
12  Senators  Eastern  4.0  3.0  3.0  3.0
13     Leats  Eastern  2.0  4.0  4.0  NaN

我希望能够通过'团队'和'司'列分组,然后在Q1,Q2,Q3,Q4列汇总数据。我目前有这样的代码,它是由“团队”分组,然后计算每个问题列中的4的数量,并将该值除以每列中的计数。我希望能够组的'司'列以及可能的其他列在未来。如何做到这一点?

grouped = (df.filter(like='Q').groupby(df['Team'])
             .agg(lambda x: x.eq(4).sum()/x.count())
          )
print(grouped)
ubof19bj

ubof19bj1#

如果我理解正确的话,您希望能够维护非Q列。
由于每个团队都有一个独特的部门,只需将部门添加为grouper:

out = (df.filter(like='Q').groupby([df['Team'], df['Division']])
         .agg(lambda x: x.eq(4).sum()/x.count())
      )

输出量:

Q1        Q2        Q3   Q4
Team     Division                                   
Canucks  Pacific   0.000000  0.000000  0.500000  0.0
Flames   Pacific   0.666667  0.333333  0.333333  0.0
Leats    Eastern   0.500000  0.666667  1.000000  0.5
Oilers   Pacific   0.250000  0.000000  0.000000  0.5
Senators Eastern   0.500000  0.500000  0.500000  0.0

每个团队的分区不唯一

如果每个团队的Division不唯一,逻辑就有点复杂了。您是否希望按团队汇总并保留多个部门的信息?或者你只是想使用团队/部门作为石斑鱼?
要仅按团队聚合,但每个部门有一行,您可以创建一个聚合函数字典,以收集每个团队的潜在多个部门,并explode输出:

funcs = ( {'Division': set}
        | {c: lambda x: x.eq(4).sum()/x.count() for c in df.filter(like='Q')}
        )
out = df.groupby('Team', as_index=False).agg(funcs).explode('Division')

这不会改变所提供的示例输入的任何内容,但是如果您有多个Division的Teams,则会重复行。
例如,如果我们将第一行中的“Pacific”替换为“Pacific 2”,则会得到给予:

Team  Division        Q1        Q2        Q3   Q4
0   Canucks   Pacific  0.000000  0.000000  0.500000  0.0
1    Flames   Pacific  0.666667  0.333333  0.333333  0.0
1    Flames  Pacific2  0.666667  0.333333  0.333333  0.0  # added a new row
2     Leats   Eastern  0.500000  0.666667  1.000000  0.5
3    Oilers   Pacific  0.250000  0.000000  0.000000  0.5
4  Senators   Eastern  0.500000  0.500000  0.500000  0.0

与此相反,第一种方法将为团队/部门的每个组合独立地汇总数据。

Q1        Q2   Q3   Q4
Team     Division                          
Canucks  Pacific   0.00  0.000000  0.5  0.0
Flames   Pacific   0.50  0.500000  0.5  0.0
         Pacific2  1.00  0.000000  0.0  0.0
Leats    Eastern   0.50  0.666667  1.0  0.5
Oilers   Pacific   0.25  0.000000  0.0  0.5
Senators Eastern   0.50  0.500000  0.5  0.0
5uzkadbs

5uzkadbs2#

这可能是正确的:

import pandas as pd

# Your dataframe
data = {
    'Team': ['Flames', 'Flames', 'Oilers', 'Canucks', 'Senators', 'Leats', 'Leats', 'Canucks', 'Oilers', 'Flames', 'Oilers', 'Oilers', 'Senators', 'Leats'],
    'Division': ['Pacific', 'Pacific', 'Pacific', 'Pacific', 'Eastern', 'Eastern', 'Eastern', 'Pacific', 'Pacific', 'Pacific', 'Pacific', 'Pacific', 'Eastern', 'Eastern'],
    'Q1': [4.0, 4.0, 3.0, 2.0, 1.0, 4.0, None, 2.0, 3.0, 3.0, 2.0, 4.0, 4.0, 2.0],
    'Q2': [1.0, 1.0, 1.0, None, 4.0, 3.0, 4.0, 2.0, 1.0, 4.0, 3.0, None, 3.0, 4.0],
    'Q3': [3.0, 2.0, 1.0, 4.0, 4.0, 4.0, 4.0, 2.0, None, 4.0, 1.0, 2.0, 3.0, 4.0],
    'Q4': [1.0, 2.0, 3.0, 2.0, 3.0, 2.0, 4.0, 3.0, 4.0, 3.0, 4.0, 1.0, 3.0, None]
}

df = pd.DataFrame(data)

# Define aggregation functions
agg_funcs = {
    'Q1': lambda x: x.count() / x.size,
    'Q2': lambda x: x.count() / x.size,
    'Q3': lambda x: x.count() / x.size,
    'Q4': lambda x: x.count() / x.size
}

# Group by 'Team' and 'Division' and apply aggregation functions
result = df.groupby(['Team', 'Division']).agg(agg_funcs).reset_index()

# Rename the columns for clarity
result.columns = ['Team', 'Division', 'Q1_Aggregate', 'Q2_Aggregate', 'Q3_Aggregate', 'Q4_Aggregate']

print(result)

输出为:

Team Division  Q1_Aggregate  Q2_Aggregate  Q3_Aggregate  Q4_Aggregate
0   Canucks  Pacific      1.000000          0.50          1.00      1.000000
1    Flames  Pacific      1.000000          1.00          1.00      1.000000
2     Leats  Eastern      0.666667          1.00          1.00      0.666667
3    Oilers  Pacific      1.000000          0.75          0.75      1.000000
4  Senators  Eastern      1.000000          1.00          1.00      1.000000

相关问题