Объединить дублированные столбцы в DataFrame
Если у меня есть фрейм данных, в котором есть столбцы с одинаковыми именами, есть ли способ объединить столбцы с одинаковыми именами с какой-либо функцией (например, суммой)?
Например с:
In [186]:
df["NY-WEB01"].head()
Out[186]:
NY-WEB01 NY-WEB01
DateTime
2012-10-18 16:00:00 5.6 2.8
2012-10-18 17:00:00 18.6 12.0
2012-10-18 18:00:00 18.4 12.0
2012-10-18 19:00:00 18.2 12.0
2012-10-18 20:00:00 19.2 12.0
Как можно свернуть столбцы NY-WEB01 (есть группа дубликатов столбцов, а не только NY-WEB01), суммируя каждую строку, где имя столбца совпадает?
Ответы
Ответ 1
Я считаю, что это делает то, что вам нужно:
df.groupby(lambda x:x, axis=1).sum()
Альтернативно, от 3% до 15% быстрее в зависимости от длины df:
df.groupby(df.columns, axis=1).sum()
EDIT: Чтобы расширить это значение за пределы суммы, используйте .agg()
(сокращение от .aggregate()
):
df.groupby(df.columns, axis=1).agg(numpy.max)
Ответ 2
Здесь вам не нужна лямбда, и вам не нужно явно запрашивать df.columns
; groupby
принимает аргумент level
вы можете указать вместе с аргументом axis
. Это чище, ИМО.
# Setup
np.random.seed(0)
df = pd.DataFrame(np.random.choice(50, (5, 5)), columns=list('AABBB'))
df
A A B B B
0 44 47 0 3 3
1 39 9 19 21 36
2 23 6 24 24 12
3 1 38 39 23 46
4 24 17 37 25 13
df.groupby(level=0, axis=1).sum()
A B
0 91 6
1 48 76
2 29 60
3 39 108
4 41 75
Обработка MultiIndex
Еще один случай, который следует учитывать при работе со столбцами MultiIndex
. Рассматривать
df.columns = pd.MultiIndex.from_arrays([['one']*3 + ['two']*2, df.columns])
df
one two
A A B B B
0 44 47 0 3 3
1 39 9 19 21 36
2 23 6 24 24 12
3 1 38 39 23 46
4 24 17 37 25 13
Чтобы выполнить агрегацию на верхних уровнях, используйте
df.groupby(level=1, axis=1).sum()
A B
0 91 6
1 48 76
2 29 60
3 39 108
4 41 75
или, если производится агрегация только по верхнему уровню, используйте
df.groupby(level=[0, 1], axis=1).sum()
one two
A B B
0 91 0 6
1 48 19 57
2 29 24 36
3 39 39 69
4 41 37 38
Удаление дубликатов столбцов
Если вы пришли сюда, чтобы узнать, как просто отбросить дублирующиеся столбцы (без выполнения агрегации), используйте Index.duplicated
:
df.loc[:,~df.columns.duplicated()]
A B
0 44 0
1 39 19
2 23 24
3 1 39
4 24 37
Или, чтобы сохранить последние, укажите keep='last'
(по умолчанию 'first'
),
df.loc[:,~df.columns.duplicated(keep='last')]
A B
0 47 3
1 9 36
2 6 12
3 38 46
4 17 13
groupby
варианты для двух вышеупомянутых решений: df.groupby(level=0, axis=1).first()
и ....last()
соответственно.
Ответ 3
Здесь возможное решение для общих проще функций агрегации, таких как sum
, mean
, median
, max
, min
, std
- использовать только параметры axis=1
для работы с колоннами и level
:
#coldspeed samples
np.random.seed(0)
df = pd.DataFrame(np.random.choice(50, (5, 5)), columns=list('AABBB'))
print (df)
print (df.sum(axis=1, level=0))
A B
0 91 6
1 48 76
2 29 60
3 39 108
4 41 75
df.columns = pd.MultiIndex.from_arrays([['one']*3 + ['two']*2, df.columns])
print (df.sum(axis=1, level=1))
A B
0 91 6
1 48 76
2 29 60
3 39 108
4 41 75
print (df.sum(axis=1, level=[0,1]))
one two
A B B
0 91 0 6
1 48 19 57
2 29 24 36
3 39 39 69
4 41 37 38
Аналогично это работает для индекса, затем используйте axis=0
вместо axis=1
:
np.random.seed(0)
df = pd.DataFrame(np.random.choice(50, (5, 5)), columns=list('ABCDE'), index=list('aabbc'))
print (df)
A B C D E
a 44 47 0 3 3
a 39 9 19 21 36
b 23 6 24 24 12
b 1 38 39 23 46
c 24 17 37 25 13
print (df.min(axis=0, level=0))
A B C D E
a 39 9 0 3 3
b 1 6 24 23 12
c 24 17 37 25 13
df.index = pd.MultiIndex.from_arrays([['bar']*3 + ['foo']*2, df.index])
print (df.mean(axis=0, level=1))
A B C D E
a 41.5 28.0 9.5 12.0 19.5
b 12.0 22.0 31.5 23.5 29.0
c 24.0 17.0 37.0 25.0 13.0
print (df.max(axis=0, level=[0,1]))
A B C D E
bar a 44 47 19 21 36
b 23 6 24 24 12
foo b 1 38 39 23 46
c 24 17 37 25 13
Если необходимо использовать другие функции, такие как first
, last
, size
, count
используйте coldspeed answer