У меня есть следующий фрейм данных в следующем формате:
df = pd.DataFrame({'Date': np.repeat(['20190101', '20190102'], 8),
'Category': list(np.repeat(['A', 'B'], 4))*2,
'Sub-Category': list(np.repeat(['X', 'Y'], 2))*4,
'Samples': range(16)})
# print(df)
Date Category Sub-Category Samples
0 20190101 A X 0
1 20190101 A X 1
2 20190101 A Y 2
3 20190101 A Y 3
4 20190101 B X 4
5 20190101 B X 5
6 20190101 B Y 6
7 20190101 B Y 7
8 20190102 A X 8
9 20190102 A X 9
10 20190102 A Y 10
11 20190102 A Y 11
12 20190102 B X 12
13 20190102 B X 13
14 20190102 B Y 14
15 20190102 B Y 15
В каждой дате есть категория, и в каждой категории есть несколько подкатегорий. Кроме того, каждая подкатегория имеет несколько выборок.
Что я хочу сделать, так это преобразовать столбец «Подкатегория» из длинного формата в широкоформатный без агрегирования по образцам, например:
desired_df = pd.DataFrame({'Date': np.repeat(['20190101', '20190102'], 4),
'Category': list(np.repeat(['A', 'B'], 2))*2,
'X': [0, 1, 4, 5, 8, 9, 12, 13],
'Y': [2, 3, 6, 7, 10, 11, 14, 15]
})
# print(desired_df)
Date Category X Y
0 20190101 A 0 2
1 20190101 A 1 3
2 20190101 B 4 6
3 20190101 B 5 7
4 20190102 A 8 10
5 20190102 A 9 11
6 20190102 B 12 14
7 20190102 B 13 15
Я думаю, что нашел способ добиться этого, но это кажется довольно уродливым и хакерским: сначала нужно создать новый столбец для номера образца, а затем создать новый индекс, который объединяет всю эту информацию вместе, поворачивая, а затем снова отделяем все это:
def add_sample_index(df):
df['sample_index'] = range(len(df))
return df
new_df = df.groupby(['Date', 'Category', 'Sub-Category']).apply(add_sample_index)
new_df['new_index'] = new_df['Date'] + '_' + new_df['Category'] + '_' + new_df['sample_index'].astype(str)
wide_df = new_df.pivot(index='new_index', columns='Sub-Category', values='Samples').reset_index()
wide_df['Date'], wide_df['Category'], wide_df['sample_index'] = wide_df['new_index'].str.split('_').str
wide_df.drop(['new_index', 'sample_index'],
inplace=True, axis='columns')
final_df = wide_df[['Date', 'Category', 'X', 'Y']]
# print((final_df == desired_df).all().all())
True
Мой вопрос: есть ли лучший, более эффективный способ решения этой проблемы?