根据动态索引条件向 Pandas DataFrame 添加列

4

我有一个数据框,其中有一列随机从“1”开始计数。我的目标是生成一个新列,将当前列除以上一个计数的最后一个值。请参见以下示例。

这是我的当前数据框:

    col
0   1.0
1   2.0
2   3.0
3   1.0
4   2.0
5   1.0
6   2.0
7   3.0
8   4.0
9   5.0
10  1.0
11  2.0
12  3.0

尝试获得以下输出:
    col  new_col
0   1.0  0.333
1   2.0  0.667
2   3.0  1.000
3   1.0  0.500
4   2.0  1.000
5   1.0  0.200
6   2.0  0.400
7   3.0  0.600
8   4.0  0.800
9   5.0  1.000
10  1.0  0.333
11  2.0  0.667
12  3.0  1.000

到目前为止,我尝试过以下方法:

df['col_bool'] = pd.DataFrame(df['col']  == 1.0)
idx_lst = [x - 2 for x in df.index[df['col_bool']].tolist()]
idx_lst = idx_lst[1:]

mask = (df['col'] != 1.0)
df_valid = df[mask]
for i in idx_lst:
    df['new_col'] = 1.0 / df_valid.iloc[i]['col']
    df.loc[mask, 'new_col'] = df_valid['col'] / df_valid.iloc[i]['col']

这显然会导致索引错误。也许我需要每次复制一个DataFrame并连接起来。我相信这会起作用,但我想问一下是否有任何快捷方式?
2个回答

7

尝试:

df['new_col'] = df['col'].div(df.groupby((df['col'] == 1).cumsum()).transform('last'))

输出:

    col   new_col
0   1.0  0.333333
1   2.0  0.666667
2   3.0  1.000000
3   1.0  0.500000
4   2.0  1.000000
5   1.0  0.200000
6   2.0  0.400000
7   3.0  0.600000
8   4.0  0.800000
9   5.0  1.000000
10  1.0  0.333333
11  2.0  0.666667
12  3.0  1.000000

1
谢谢分享!非常优雅。我使用了您的建议,只需要在最后再次选择列名即可。df ['new_col'] = df ['col'].div(df.groupby((df['col'] == 1).cumsum()).transform('last')['col']) - tryingtolearn
@tryingtolearn 祝你编程愉快!请保持安全和健康。 - Scott Boston

4
你可以尝试:
df['new_col'] = df.groupby((df.col.ne(df.col.shift().add(1))).cumsum())[
    'col'].transform(lambda x: x.div(len(x)))

或者:
df['new_col'] = df.col.div(df.groupby((df.col.ne(df.col.shift().add(1))).cumsum())
           ['col'].transform('count'))

输出:

    col   new_col
0   1.0  0.333333
1   2.0  0.666667
2   3.0  1.000000
3   1.0  0.500000
4   2.0  1.000000
5   1.0  0.200000
6   2.0  0.400000
7   3.0  0.600000
8   4.0  0.800000
9   5.0  1.000000
10  1.0  0.333333
11  2.0  0.666667
12  3.0  1.000000

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接