相对于每个组pandas特定行的百分比变化



对于每一组,我想计算相对于"a"(在第二个索引)。每个"a"可能在不同的位置。

绝笔:

df = pd.DataFrame({"A":[1,1,1,3,3,3, 1,1,1,3,3,3],
"B":["a", "b", "c", "a", "b", "c", "a", "b", "c", "a", "b", "c"],
"click":[100, 200, 123, 333, 222, 333, 100, 200, 123, 333, 222, 333],
"exp":[10000, 10000, 10000, 10000, 10000, 10000, 20000, 20000, 20000, 20000, 20000, 20000]})
grp_df = df.groupby(["A", "B"]).sum()
grp_df["ctr"] = grp_df["click"] / grp_df["exp"] * 100
grp_df = (grp_df.groupby(level=0, group_keys=False)
.apply(lambda g: g.sort_values('ctr', ascending=False))
)
grp_df["rank"] = (grp_df.groupby(level=0, group_keys=False)["ctr"]
.rank(ascending=False))

输出:

click   exp     ctr     rank
A   B               
1   b   400     30000   1.333333    1.0
c   246     30000   0.820000    2.0
a   200     30000   0.666667    3.0
3   a   666     30000   2.220000    1.5
c   666     30000   2.220000    1.5
b   444     30000   1.480000    3.0
所需输出:

click   exp     ctr     rank    relative_p
A   B                   
1   b   400     30000   1.333333    1.0     1.000000
c   246     30000   0.820000    2.0     0.230000
a   200     30000   0.666667    3.0     0.000000
3   a   666     30000   2.220000    1.5     0.000000
c   666     30000   2.220000    1.5     0.000000
b   444     30000   1.480000    3.0     -0.333333

我可以通过循环遍历每一行来实现这一点,但是想知道是否有更有效的方法。可能是利用熊猫提供的pct_change()操作能力。

new_dfs = list()
grp1_lst = grp_df.index.get_level_values("A").unique().tolist()
for grp in grp1_lst:
df = grp_df.loc[grp_df.index.get_level_values("A") == grp].copy()
org_ctr = df.loc[df.index.get_level_values("B") == "a"]["ctr"].iloc[0]
df["relative_p"] = (df["ctr"] - org_ctr) /org_ctr
new_dfs.append(df)

new_df = pd.concat(new_dfs)

想法是用Series.where替换非a行到缺失值,然后用GroupBy.first使用GroupBy.transform:

org_ctr = (grp_df['ctr'].where(grp_df.index.get_level_values("B") == "a")
.groupby(level=0)
.transform('first'))
grp_df["relative_p"] = (grp_df["ctr"] - org_ctr) /org_ctr
print (grp_df)
click    exp       ctr  rank  relative_p
A B                                          
1 b    400  30000  1.333333   1.0    1.000000
c    246  30000  0.820000   2.0    0.230000
a    200  30000  0.666667   3.0    0.000000
3 a    666  30000  2.220000   1.5    0.000000
c    666  30000  2.220000   1.5    0.000000
b    444  30000  1.480000   3.0   -0.333333

最新更新