我的数据框如下
id val type
aa 0 C
aa 1 T
aa 2 T
aa 3 T
aa 0 M
aa 1 M
aa 2 C
aa 3 M
bbb 0 C
bbb 1 T
bbb 2 T
bbb 3 T
bbb 0 M
bbb 1 M
bbb 2 C
bbb 3 T
cccccc 0 C
cccccc 1 T
cccccc 2 T
cccccc 3 T
cccccc 0 M
cccccc 1 M
cccccc 0 C
cccccc 1 C
我想先做一个groupby
“ ID”,然后再做sum
&count
列“ val”中的行,但是应该加起来的行只是包含以下内容的行“类型”与每个组中“类型”列的最后一个值相同。
例如,组的最后一行具有“类型” M,因此仅对组中具有“类型” M的行进行求和和计数。因此,需要将值0、1和3相加,并且计数为3。
上述df的预期输出如下。输出中的“类型”列不是必需的,如果花费更多时间可以将其忽略。我在这里展示它只是为了让我更清楚地说明要实现的目标。
id val count type
aa 4 3 M
bbb 9 4 T
cccccc 1 3 C
答案 0 :(得分:2)
使用GroupBy.transform
和last
进行过滤,然后通过命名聚合进行聚合,适用于0.25+的熊猫:
df = (df[df['type'].eq(df.groupby('id')['type'].transform('last'))]
.groupby('id').agg(val=('val', 'sum'),
count=('val', 'size'),
type=('type','last')))
print (df)
val count type
id
aa 4 3 M
bbb 9 4 T
cccccc 1 3 C
由Series.map
和DataFrame.drop_duplicates
创建的系列DataFrame.set_index
的另一种解决方案:
s = df.drop_duplicates('id', keep='last').set_index('id')['type']
df = (df[df['type'].eq(df['id'].map(s))]
.groupby('id').agg(val=('val', 'sum'),
count=('val', 'size'),
type=('type','last')))
print (df)
val count type
id
aa 4 3 M
bbb 9 4 T
cccccc 1 3 C
答案 1 :(得分:1)
# find the last type by group
last_type = df[["id", "type"]].groupby("id").tail(1)
df['count'] = 1
# inner merge with the last type (i.e. keep only the last type by group)
df.merge(last_type, on=["id", "type"], how="inner").groupby(["id", "type"]).agg({'val':'sum', 'count': 'sum'}).reset_index()
输出
id type val count
0 aa M 4 3
1 bbb T 9 4
2 cccccc C 1 3