Pandas Groupby Условная агрегация - PullRequest
1 голос
/ 19 марта 2019

Допустим, у вас есть следующий фрейм данных:

data = pd.DataFrame({'Year': [2019]*5+[2020]*5,
          'Month': [1,1,2,2,3]*2,
          'Hour': [0,1,2,3,4]*2,
          'Value': [0.2,0.3,0.2,0.1,0.4,0.3,0.2,0.5,0.1,0.2]})

Затем установите «низкое» время равным часам от 1 до 3 (включительно), а «высокое» время равным всем остальным часам (в этом случае часов 0 и 4).То, что я хотел бы сделать, это получить среднее значение Value для «низкого» и «высокого» времени для каждого Year и Month.В идеале они должны быть добавлены в качестве новых столбцов к фрейму данных groupby () (т. Е. Конечный фрейм данных будет иметь столбцы Year, Month, Low и High).

Для цикловработать, но они не идеальны.Я также мог бы создать фиктивную переменную (например, 0 с и 1 с), чтобы обозначить «низкое» и «высокое» время в кадре данных для группировки.Однако мне кажется, что должен быть какой-то способ использования Pandas groupby (['Year', 'Month']). Agg (...) для достижения результата эффективным / оптимальным способом.До сих пор мне не повезло с использованием groupby + agg, в основном потому, что agg () использует только серию (не оставшийся фрейм данных), поэтому нельзя использовать условное выражение внутри agg на основе Hour для вычисления среднегоValue.

Ожидаемый результат от данных выборки:

Year Month High Low 0 2019 1 0.2 0.30 1 2019 2 NaN 0.15 2 2019 3 0.4 NaN 3 2020 1 0.3 0.20 4 2020 2 NaN 0.30 5 2020 3 0.2 NaN

Любая помощь приветствуется:)

Ответы [ 3 ]

3 голосов
/ 19 марта 2019

Рассмотрим pivot_table после создания поля индикатора низкого / высокого типа:

data['Type'] = np.where(data['Hour'].between(1,3), 'Low', 'High')

pvt_df = (pd.pivot_table(data, index=['Year', 'Month'], 
                         columns='Type', values='Value', aggfunc=np.mean)
            .reset_index()
            .rename_axis(None, axis='columns')
         )    

print(pvt_df)
#    Year  Month  High   Low
# 0  2019      1   0.2  0.30
# 1  2019      2   NaN  0.15
# 2  2019      3   0.4   NaN
# 3  2020      1   0.3  0.20
# 4  2020      2   NaN  0.30
# 5  2020      3   0.2   NaN
0 голосов
/ 19 марта 2019

Может не выиграть цену за самый красивый кусок кода, но если я вас правильно понимаю, это то, что вы хотите.

(поправьте меня, если я неправ, так как ожидаемый результат не включен)

Groupby 4 раза и объедините годы и месяцы вместе.После этого выполните окончательное объединение, чтобы собрать все столбцы вместе

low_hours = [1, 2, 3]

groupby1 = data[data.Hour.isin(low_hours)].groupby('Year').Value.mean().reset_index().rename({'Value':'Value_year_low'},axis=1)
groupby2 = data[~data.Hour.isin(low_hours)].groupby('Year').Value.mean().reset_index().rename({'Value':'Value_year_high'},axis=1).drop('Year', axis=1)
groupby3 = data[data.Hour.isin(low_hours)].groupby(['Year','Month']).Value.mean().reset_index().rename({'Value':'Value_month_low'},axis=1)
groupby4 = data[~data.Hour.isin(low_hours)].groupby(['Year','Month']).Value.mean().reset_index().rename({'Value':'Value_month_high'},axis=1).drop(['Year','Month'], axis=1)

df_final1 = pd.concat([groupby1, groupby2], axis=1)
df_final2 = pd.concat([groupby3, groupby4], axis=1)

df_final = pd.merge(df_final1, df_final2, on='Year')
print(df_final)
   Year  Value_year_low  Value_year_high  Month  Value_month_low  \
0  2019        0.200000             0.30      1             0.30   
1  2019        0.200000             0.30      2             0.15   
2  2020        0.266667             0.25      1             0.20   
3  2020        0.266667             0.25      2             0.30   

   Value_month_high  
0               0.2  
1               0.4  
2               0.3  
3               0.2  
0 голосов
/ 19 марта 2019
data = pd.DataFrame({'Year': [2019]*5+[2020]*5,
          'Month': [1,1,2,2,3]*2,
          'Hour': [0,1,2,3,4]*2,
          'Value': [0.2,0.3,0.2,0.1,0.4,0.3,0.2,0.5,0.1,0.2]})

data['low'] = (data['Hour'] > 0) & (data['Hour'] < 4)

data[data['low']][['Month', 'Year']].mean()
data[~data['low']][['Month', 'Year']].mean()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...