#python #pandas
#python #pandas
Вопрос:
Я использую Python3.7 и Pandas v0.25.3. У меня есть такой фрейм данных,
pri_col col1 col2 Date
r1 3 4 2020-09-10
r2 4 1 2020-09-10
r1 2 7 2020-09-11
r3 6 4 2020-09-11
Я хочу что-то вроде,
pri_col col1_2020-09-10 col2_2020-09-10 col1_2020-09-11 col2_2020-09-11
r1 3 4 NaN NaN
r2 4 1 NaN NaN
r1 NaN NaN 2 7
r3 NaN NaN 6 4
Я попробовал следующий код:
import pandas as pd
df = pd.DataFrame([['r1', '3', '4', '2020-09-10'], ['r2', '4', '1', '2020-09-10'], ['r1', '2', '7', '2020-09-11'], ['r3', '6', '4', '2020-09-11']], columns=['pri_col', 'col1', 'col2', 'Date'])
print(df)
df_list = list()
for key, item in df.groupby('Date'):
item = item.drop('Date', axis=1)
item.columns = ['pri_col'] [str(x) '_' str(key) for x in item.columns if x != 'pri_col']
df_list.append(item)
finDf = pd.concat(df_list, sort=False)
print(finDf)
Но этот код не оптимизирован для больших фреймов данных. Возможно ли иметь векторизованную реализацию для этого приложения в Pandas?
Многоуровневый фрейм данных также подходит для меня, если код векторизован. На верхнем уровне у меня может быть значение столбца «Дата», а на следующем уровне у меня могут быть столбцы.
Ответ №1:
Изменить форму с DataFrame.set_index
помощью , DataFrame.stack
и DataFrame.unstack
это первая идея, которую необходимо сгладить MultiIndex
:
df = (df.set_index(['pri_col','Date'], append=True)
.stack()
.unstack([3,2])
)
df.columns = [f'{a}-{b}' for a, b in df.columns]
df = df.reset_index(level=1).
print (df)
pri_col col1-2020-09-10 col2-2020-09-10 col1-2020-09-11 col2-2020-09-11
0 r1 3.0 4.0 NaN NaN
1 r2 4.0 1.0 NaN NaN
2 r1 NaN NaN 2.0 7.0
3 r3 NaN NaN 6.0 4.0
Или изменить форму с помощью DataFrame.melt
и DataFrame.pivot
:
df = (df.reset_index()
.melt(id_vars=['index','pri_col','Date'],
var_name='cols',
value_name='val')
.pivot(index=['index','pri_col'],
columns=['cols','Date'],
values='val'))
df.columns = [f'{a}-{b}' for a, b in df.columns]
df = df.reset_index(level=1).rename_axis(None)
print (df)
pri_col col1-2020-09-10 col1-2020-09-11 col2-2020-09-10 col2-2020-09-11
0 r1 3.0 NaN 4.0 NaN
1 r2 4.0 NaN 1.0 NaN
2 r1 NaN 2.0 NaN 7.0
3 r3 NaN 6.0 NaN 4.0
Комментарии:
1. Привет. Я получаю сообщение об ошибке в сводной части.
raise DataError("No numeric types to aggregate") pandas.core.base.DataError: No numeric types to aggregate
2. @AsifIqbal — это означает, что столбцы
col1
col2
не заполняются числом, как работает первое решение?3. Первое решение работает хорошо. Но не могли бы вы уточнить длинные цепочки в обоих ответах, чтобы я мог адаптировать их к своему приложению? На самом деле я новичок в Pandas. Так что извините, если мне нужно какое-то ненужное объяснение.
4. @AsifIqbal — Конечно, дайте мне знать, если что-то непонятно. For second используется
pivot_table
с агрегацией по умолчаниюmean
, поэтому он терпит неудачу, если не числовые столбцы. Возможное решение здесь — изменить его сaggfunc='mean'
наaggfunc='first'
5. если ваша версия pandas> 1.1,
pivot
поддерживает создание мультииндексов, поэтому вам не нужно полагаться наpivot_table
фиктивную функцию агрегирования