Выберите MultiIndex с помощью xs
и sum
, выход присваивается кортежу для MultiIndex
:
df[('','total')] = df.xs('Bill2', axis=1, level=1).sum(axis=1)
print (df)
Sep-19 Oct-19 Nov-19
Bill1 Bill2 Bill1 Bill2 Bill1 Bill2 total
A Ind OS 1 1 1 1 1 4 6
Для фильтрации по нескольким годам, например, только 2019
необходим фильтр по маске перед:
print (df)
Sep-20 Oct-19 Nov-19
Bill1 Bill2 Bill1 Bill2 Bill1 Bill2
A Ind OS 1 1 1 7 1 4
#convert first level for datetimes and then to years
level0 = pd.to_datetime(df.columns.get_level_values(0), format='%b-%y').year
print (level0)
Int64Index([2020, 2020, 2019, 2019, 2019, 2019], dtype='int64')
mask = level0 == 2019
df[('','total2019')] = df.loc[:, mask].xs('Bill2', axis=1, level=1).sum(axis=1)
print (df)
Sep-20 Oct-19 Nov-19
Bill1 Bill2 Bill1 Bill2 Bill1 Bill2 total2019
A Ind OS 1 1 1 7 1 4 11
РЕДАКТИРОВАТЬ:
Для правильной сортировки после добавления необходима новая строка суммы при работе с датами (или периодами), решение:
print (df)
Nov-19 Dec-19 Jan-20
Bill1 Bill2 Bill1 Bill2 Bill1 Bill2
A Ind OS 1 1.28 1 1.28 1 1.28
level0 = pd.to_datetime(df.columns.get_level_values(0), format='%b-%y')
level1 = df.columns.get_level_values(1)
print (level0)
DatetimeIndex(['2019-11-01', '2019-11-01', '2019-12-01', '2019-12-01',
'2020-01-01', '2020-01-01'],
dtype='datetime64[ns]', freq=None)
df.columns = [level0, level1]
mask = level0.year == 2019
df[(pd.to_datetime('2019-12-01'),'total2019')] = df.loc[:, mask].xs('Bill2', axis=1, level=1).sum(axis=1)
df = df.sort_index(level=0, axis=1)
print (df)
2019-11-01 2019-12-01 2020-01-01
Bill1 Bill2 Bill1 Bill2 total2019 Bill1 Bill2
A Ind OS 1 1.28 1 1.28 2.56 1 1.28
Последнее, если необходимооригинальный формат datetimes:
level0 = df.columns.get_level_values(0).strftime('%b-%y')
level1 = df.columns.get_level_values(1)
df.columns = [level0, level1]
print (df)
Nov-19 Dec-19 Jan-20
Bill1 Bill2 Bill1 Bill2 total2019 Bill1 Bill2
A Ind OS 1 1.28 1 1.28 2.56 1 1.28