Создание фрейма данных с наилучшими значениями из списка фреймов данных

#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