我最终遇到了@ahbon 提出的同样问题:如果有多个列可以分组怎么办?这是我发现的最接近我的问题的问题。经过一番认真的斗争,我得出了一个解决办法。
据我所知(有 pandas 特定功能可以做类似的事情)它不可能是优雅/正统的,所以我很感激一些反馈。
就是这样:
import pandas as pd
import random
random.seed(123)
df = pd.DataFrame({"A":list('a'*4+'b'*4+'c'*4+'d'*4),
"B":list('xy'*8),
"C":random.sample(range(17), 16)})
print(df)
A B C
0 a x 1
1 a y 8
2 a x 16
3 a y 12
4 b x 6
5 b y 4
6 b x 14
7 b y 0
8 c x 13
9 c y 5
10 c x 2
11 c y 9
12 d x 10
13 d y 11
14 d x 3
15 d y 15
首先获取0值的索引以检索非零数据并按组获取平均值。
idx = list(df[df["C"] != 0].index)
data_to_group = df.iloc[idx,]
grouped_data = pd.DataFrame(data_to_group.groupby(["A", "B"])["C"].mean())
现在是棘手的部分。这是我的印象,它可能是一个更优雅的解决方案:
- 堆栈、取消堆栈和重置索引
- 然后与
df 中的行子集合并,其中C 是0;从第一个删除C,从第二个保留C
- 最后用这个子集更新
df,C 中没有零。
grouped_data = grouped_data.stack().unstack().reset_index()
zero_rows = df[df.C == 0]
zero_rows_replaced = pd.merge(left = zero_rows, right = grouped_data,
how = "left", on=["A", "B"],
suffixes=('_x','')).drop('C_x', axis=1)
zero_rows_replaced = zero_rows_replaced.set_index(zero_rows.index.copy())
df.update(zero_rows_replaced)
print(df)
A B C
0 a x 1
1 a y 8
2 a x 16
3 a y 12
4 b x 6
5 b y 4
6 b x 14
7 b y 4
8 c x 13
9 c y 5
10 c x 2
11 c y 9
12 d x 10
13 d y 11
14 d x 3
15 d y 15