首页 > 解决方案 > 从 DataFrames 列表中创建一个具有最佳值的 DataFrame

问题描述

我有一个数据框列表。这些 DataFrame 中的每一个看起来像这样:

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”总是与同一个“地方”相关联。

我想要一个最终的 DataFrame,我可以在其中看到前 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

标签: pythonpandasdataframe

解决方案


这里需要几个步骤。

首先,我们连接所有 dfs,df_list同时向每个 dfs 添加一列,以跟踪列表中该 df 的索引,我们将其放入 column 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

我们将value1value2分开对待。对于 value1,我们 groupby on ['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

这已经有了我们需要的信息(列value1di)。假设您希望格式更接近您指定的格式,我们需要为每个组提取 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

这就是您要求的 value1。如果您不喜欢这些,您可能需要重命名列标签

然后我们可以value2通过在上面的命令中更改 value1<-->value2 来做同样的事情,以产生df_agv2,这里不再重复步骤

如果你想把两者放在一起,你可以做类似的事情

pd.concat([df_agv1,df_agv2], axis=1)

推荐阅读