【问题标题】:Groupby column based on condition in dataframe基于数据框中条件的分组列
【发布时间】:2020-11-27 12:08:50
【问题描述】:

我想根据 Region 列和 Inhabitants 列组合以下数据框 df。另外,我想总结一下Area的值。

import pandas as pd
df = pd.DataFrame({'Region': ['Region1', 'Region1', 'Region1', 'Region2', 'Region2', 'Region2', 'Region3', 'Region3', 'Region4', 'Region4'], 'Inhabitants': [True, False, True, True, False, True, True, True, False, False], 'Area': [60, 20, 20, 60, 30, 10, 50, 50, 50, 50]})
print(df)

  Region  Inhabitants  Area
0  Region1         True    60
1  Region1        False    20
2  Region1         True    20
3  Region2         True    60
4  Region2        False    30
5  Region2         True    10
6  Region3         True    50
7  Region3         True    50
8  Region4        False    50
9  Region4        False    50

这适用于这段代码:

df = df.groupby(['Region', 'Inhabitants'], as_index=False)['Area'].sum()
print(df)

 Region  Inhabitants  Area
0  Region1        False    20
1  Region1         True    80
2  Region2        False    30
3  Region2         True    70
4  Region3         True   100
5  Region4        False   100

最后我想确定每个区域的真实面积之和是否> = 80。这应该在添加的列Region_ok中说明为True,如果每个区域的真实面积> = 80或False,如果不是。这又应该按地区分组。结果应如下所示:

    Region        Region_ok
0  Region1        True
1  Region2        False
2  Region3        True
3  Region4        False

我用 groupby 尝试了几件事,但找不到合适的解决方案。

【问题讨论】:

    标签: python pandas dataframe group-by


    【解决方案1】:

    最简单的解决方案是将Area 替换为0 如果Inhabitants 中的False 为Series.where,然后汇总总和,比较大于或等于最后将Series 转换为DataFrame

    df2 = (df['Area'].where(df['Inhabitants'], 0)
                     .groupby(df['Region'])
                     .sum()
                     .ge(80)
                     .reset_index(name='Region_ok'))
    print(df2)
        Region  Region_ok
    0  Region1       True
    1  Region2      False
    2  Region3       True
    3  Region4      False
    

    您可以使用聚合 DataFrame - 通过 80 通过 Series.gt 过滤并使用带有布尔列的 & 进行链接,最后测试是否至少有一个值与 GroupBy.any 匹配:

    df1 = df.groupby(['Region', 'Inhabitants'], as_index=False)['Area'].sum()
    m = df1['Area'].ge(80) & df1['Inhabitants']
    
    df2 = m.groupby(df1['Region']).any().reset_index(name='Region_ok')
    print(df2)
        Region  Region_ok
    0  Region1       True
    1  Region2      False
    2  Region3       True
    3  Region4      False
    

    类似的想法,但使用原始数据是使用 GroupBy.transformsum 并在原始数据框中过滤:

    s = df.groupby(['Region', 'Inhabitants'])['Area'].transform('sum')
    m = s.ge(80) & df['Inhabitants']
    
    df2 = m.groupby(df['Region']).any().reset_index(name='Region_ok')
    print(df2)
        Region  Region_ok
    0  Region1       True
    1  Region2      False
    2  Region3       True
    3  Region4      False
    

    下一个解决方案首先仅过滤 Trues 行,并仅通过 Region 聚合 sum

    s = df[df['Inhabitants']].groupby('Region')['Area'].sum()
    df2 = (s.ge(80)
            .reindex(df['Region'].unique(), fill_value=False)
            .reset_index(name='Region_ok'))
    
    print(df2)
        Region  Region_ok
    0  Region1       True
    1  Region2      False
    2  Region3       True
    3  Region4      False
    

    【讨论】:

    • 谢谢,所有解决方案变体都能完美运行
    猜你喜欢
    • 2021-11-21
    • 2020-01-19
    • 2021-09-29
    • 2018-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-23
    • 2018-03-27
    相关资源
    最近更新 更多