#python #pandas #dataframe
#python #pandas #фрейм данных
Вопрос:
У меня есть список фреймов данных. Каждый из этих фреймов данных выглядит следующим образом :
df_list[0] =
place place2 value1 value2
0 x a 10 0
1 y a 15 10
2 z b 5 10
Чтобы дать вам конкретный пример, я покажу еще два :
df_list[1] =
place place2 value1 value2
0 x a 20 20
1 y a 0 0
df_list[2]=
place place2 value1 value2
0 x a 50 10
1 y a 30 20
2 z b 0 40
Как вы можете видеть, не каждый из этих фреймов данных содержит все возможные «места». Однако ‘place2’ всегда ассоциируется с одним и тем же ‘place’.
Я хотел бы иметь окончательный фрейм данных, в котором я мог бы видеть верхние 3 ‘value1’ и ‘value2’ и связанные с ними «i», как df_list[i]
и для каждого «места». Формат действительно не имеет значения, но, например, он может выглядеть так :
place place2 v1_1st v1_1st_i v2_1st v2_1st_i v1_2nd v1_2nd_i v2_2nd v2_2nd_i v1_3rd v1_3rd_i ...
x a 50 2 20. 1 20. 1. 10. 0. 10. 2
y a 30 2 20. 2. 15. 0. 10. 0. 0. 1
z b 5 0 40. 2. 0. 2. 10. 0. NaN. NaN
Спасибо, что поддерживаете меня! xoxo
Комментарии:
1. вы должны указать свой код отслеживания.
Ответ №1:
Здесь потребуется несколько шагов.
Сначала мы объединяем все dfs df_list
, добавляя к каждому столбцу столбец, который отслеживает индекс этого df в списке, мы помещаем его в столбец di
:
df_ag = pd.concat([d.assign(di = n) for n,d in enumerate(df_list)], axis=0, ignore_index=True)
df_ag
создает
place place2 value1 value2 di
-- ------- -------- -------- -------- ----
0 x a 10 0 0
1 y a 15 10 0
2 z b 5 10 0
3 x a 20 20 1
4 y a 0 0 1
5 x a 50 10 2
6 y a 30 20 2
7 z b 0 40 2
Мы будем рассматривать value1
и value2
отдельно. Для значения1 мы группируем ['place', 'place2']
, находим 3 наибольших значения для каждой группы и ранжируем их (через reset_index()
внутри каждой группы)
df_agv1 = df_ag.groupby(['place','place2']).apply(lambda d: d.nlargest(3, 'value1').reset_index(drop=True))
df_agv1
это приводит к
place place2 value1 value2 di
place place2
x a 0 x a 50 10 2
1 x a 20 20 1
2 x a 10 0 0
y a 0 y a 30 20 2
1 y a 15 10 0
2 y a 0 0 1
z b 0 z b 5 10 0
1 z b 0 40 2
В нем уже есть необходимая нам информация (столбцы value1
и di
). Предполагая, что вы хотите, чтобы формат был ближе к указанному вами формату, нам нужно извлечь value1 и di для каждой группы. Мы можем сделать это следующим образом:
df_agv1 = df_agv1.drop(columns = ['place','place2','value2']).unstack(level=2)
df_agv1.columns = df_agv1.columns.to_flat_index()
df_agv1
который выдает
('value1', 0) ('value1', 1) ('value1', 2) ('di', 0) ('di', 1) ('di', 2)
---------- --------------- --------------- --------------- ----------- ----------- -----------
('x', 'a') 50 20 10 2 1 0
('y', 'a') 30 15 0 2 0 1
('z', 'b') 5 0 nan 0 2 nan
и это то, что вы просили для значения1. Вы можете переименовать метки столбцов, если они вам не нравятся
Затем мы можем сделать то же самое для value2
, изменив значение1<—>значение2 в приведенных выше командах, чтобы произвести df_agv2
, я не повторяю шаги здесь
Если вы хотите объединить их вместе, вы можете сделать что-то вроде
pd.concat([df_agv1,df_agv2], axis=1)
Ответ №2:
Другой вариант
df1 = pd.DataFrame([['x', 'a', 10, 0], ['y', 'a', 15, 10], ['z', 'b', 5, 10]], columns=['place', 'place2', 'value', 'value2'])
df2 = pd.DataFrame([['x', 'a', 20, 20], ['y', 'a', 0, 0]], columns=['place', 'place2', 'value', 'value2'])
df3 = pd.DataFrame([['x', 'a', 50, 10], ['y', 'a', 30, 20], ['z', 'b', 0, 40]], columns=['place', 'place2', 'value', 'value2'])
df_list =[df1, df2, df3]
Определите позицию списка для для каждого фрейма данных в списке:
for i, df in enumerate(df_list):
df['listposition'] = i
Объединение фреймов данных:
df_temp = pd.concat(df_list, axis=0)
анализируйте значение и значение2 отдельно, но таким же образом, чтобы объединить позже:
df_pv1 = df_temp[['place','place2','value', 'listposition']].sort_values('value')
df_pv1.rename(columns={'listposition': 'listposition'}, inplace=True)
df_pv2 = df_temp[['place','place2', 'value2', 'listposition']].sort_values('value2')
df_pv2.rename(columns={'listposition': 'listposition2'}, inplace=True)
группировка по месту, place2 (с учетом того, что мы сортировали столбцы значений по убыванию)
df_ranked_pv1 = df_pv1.groupby(['place','place2']).head(3).sort_values(['place', 'place2', 'value'], ascending=[True, True, False])
df_ranked_pv2 = df_pv2.groupby(['place','place2']).head(3).sort_values(['place', 'place2', 'value2'], ascending=[True, True, False])
Соберите все это вместе. Вы упомянули, что формат не был установлен, так что это другой макет.
df_final = pd.concat([df_ranked_pv1, df_ranked_pv2[['value2', 'listposition2']]], axis=1)
In [125]: df_final
Out[125]:
place place2 value listposition value2 listposition2
0 x a 50 2 20 1
0 x a 20 1 10 2
0 x a 10 0 0 0
1 y a 30 2 20 2
1 y a 15 0 10 0
1 y a 0 1 0 1
2 z b 5 0 40 2
2 z b 0 2 10 0