Столбец Groupby на основе условия в dataframe

#python #pandas #dataframe #group-by

#python #панды #фрейм данных #группировать по

Вопрос:

Я хочу объединить следующий dataframe df в соответствии с областью столбца и обитателями столбца. Кроме того, я хочу суммировать значение в области.

 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, но не могу найти подходящего решения.

Ответ №1:

Самое простое решение — заменить Area 0 , если False в Inhabitants by 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
 

Вы можете работать с агрегированным фреймом данных — фильтровать по большему 80 по Series.gt и связывать amp; с логическим столбцом и последним тестом, если хотя бы одно значение совпадает по GroupBy.any :

 df1 = df.groupby(['Region', 'Inhabitants'], as_index=False)['Area'].sum()
m = df1['Area'].ge(80) amp; 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.transform sum и фильтрации в исходном фрейме данных:

 s = df.groupby(['Region', 'Inhabitants'])['Area'].transform('sum')
m = s.ge(80) amp; 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
 

Следующее решение сначала фильтрует только True s строк и агрегирует sum только по Region :

 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
 

Комментарии:

1. спасибо, все варианты решения работают отлично