首页 > 解决方案 > 基于数据框中条件的分组列

问题描述

我想根据 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。如果每个区域的真实面积 >= 80,则应在添加的列 Region_ok 中将其说明为 True,否则为 False。这又应该按地区分组。结果应如下所示:

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

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

标签: pythonpandasdataframegroup-by

解决方案


最简单的解决方案 ir 替换Area0if False in Inhabitantsby Series.where,然后聚合总和,比较大于或等于 alnd 最后转换SeriesDataFrame

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 - 通过更大的过滤器过滤80Series.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

下一个解决方案首先仅过滤s 行,并且仅按以下方式True聚合:sumRegion

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

推荐阅读