pandas groupby和agg多个级别

j7dteeu8  于 2023-04-19  发布在  其他
关注(0)|答案(4)|浏览(153)

我有几个非常非常大的数据集(简化)。但是请注意,并非所有SB(在本例中为1-4)都在每个LFrame中表示...

LFrame, Pwr, SB, Channels_Active, Channels_Assigned
     1,  10,  1,               2,                 2
     1,   2,  2,               2,                 1
     1,   4,  3,               3,                 2
     1,   6,  3,               2,                 2
    10,   8,  1,               2,                 2
    10,   2,  2,               3,                 2
    10,   4,  3,               2,                 1
    10,   2,  3,               2,                 1
    10,   5,  4,               2,                 2

我需要用几种方式合并它。我相信有一个版本的groupby我可以使用......但我不能弄清楚。也许像这样:

call_data_map = {
    'LFrame'             :('LFrame','first'),
    'Total_Pwr'          :("Pwr", 'sum'),
    'Channels_Act'       :("Channels_Active", 'sum'),
    'Channels_Assigned'  :("Channels_Assigned", 'sum'),
    ??? some kind of generator? (sb :('SB', 'sum') for sb in range(1,5)) ??
}

df.groupby('LFrame').agg(**call_data_map) ???

我希望输出看起来像这样(其中我对SB求和以获得每个SB中的总功率和总功率)。cols(1-4)来自SB col,并且我知道范围始终为1-4:

LFrame, Total_Pwr, Channels_Act, Channels_Assigned,  1, 2,  3, 4
     1,        22,            9,                 7, 10, 2, 10, 0
    10,        21,           11,                 8,  8, 2,  6, 5

有没有一种有效的方法来做到这一点?使用列表解析和建立行(在每个文件上)是缓慢的。

6yt4nkrj

6yt4nkrj1#

我会做一个pivot_table

out = (df.pivot_table(index="LFrame", columns="SB", values="Pwr",
                      aggfunc="sum", fill_value=0, margins=True,
                      margins_name="Total_Pwr")
         .drop("Total_Pwr").reset_index().rename_axis(None, axis=1)
)

输出:

print(out)

   LFrame   1  2   3  4  Total_Pwr
0       1  10  2  10  0         22
1      10   8  2   6  5         21
sshcrbum

sshcrbum2#

编号的列是一个透视表,但其他列只是一个基本的groupby-sum。所以我们可以简单地单独创建它们,然后进行concat。

sums = (
    df.groupby('LFrame')
    [['Pwr', 'Channels_Active', 'Channels_Assigned']]
    .sum()
    .rename(columns={'Pwr': 'Total_Pwr', 'Channels_Active': 'Channels_Act'})
    )
sb = df.pivot_table(
    index='LFrame', columns='SB', values='Pwr',
    aggfunc=sum, fill_value=0)
pd.concat([sums, sb], axis=1)

结果:

Total_Pwr  Channels_Act  Channels_Assigned   1  2   3  4
LFrame                                                          
1              22             9                  7  10  2  10  0
10             21            11                  8   8  2   6  5
aoyhnmkz

aoyhnmkz3#

下面是使用groupby().join()的方法:

(df.groupby('LFrame').agg(Total_Pwr = ('Pwr','sum'))
.join(df.groupby('LFrame')['SB'].value_counts().unstack().fillna(0))
    .reset_index())

输出:

LFrame  Total_Pwr    1    2    3    4
0       1         22  1.0  1.0  2.0  0.0
1      10         21  1.0  1.0  2.0  1.0
czq61nw1

czq61nw14#

要获得OP问题中显示的列序列,您可以通过@Timeless稍微修改答案,取消对drop()的调用,而是使用pipe和iloc:

out = ( df
    .pivot_table(index='LFrame', columns='SB', values='Pwr', 
        aggfunc='sum', fill_value=0, margins=True, margins_name='Total_Pwr')
    .pipe(lambda d: d.iloc[0:-1, [-1] + list(range(d.shape[1]-1))])
    .rename_axis(None, axis='columns')
    .reset_index() )

输出:

LFrame  Total_Pwr   1  2   3  4
0       1         22  10  2  10  0
1      10         21   8  2   6  5

相关问题