如何用Pandas按分组对非零值进行自动递增编号?
数据
Group Value 0 A 2 1 A 4 2 B 1 3 B 3 4 B 0 5 C 0 6 C 5
数据2
ts_code bkb_close date 2020-09-30 399106.SZ 0.0000 2020-10-09 399106.SZ 2215.9609 2020-10-12 399106.SZ 2289.3570 2020-10-13 399106.SZ 0.0000 2020-10-14 399106.SZ 0.0000 2020-10-15 399106.SZ 0.0000 2020-10-16 399106.SZ 0.0000 2020-10-19 399106.SZ 0.0000 2020-10-20 399106.SZ 0.0000 2020-10-21 399106.SZ 0.0000 2020-10-22 399106.SZ 0.0000 2020-10-23 399106.SZ 0.0000 2020-10-26 399106.SZ 0.0000 2020-10-27 399106.SZ 2223.9227 2020-10-28 399106.SZ 2239.1080 2020-10-28 399300.SZ 4737.2718 2020-10-29 399106.SZ 2249.5738 2020-10-29 399300.SZ 4772.9198 2020-10-30 399106.SZ 0.0000 2020-10-30 399300.SZ 0.0000 2020-11-02 399300.SZ 4720.8313 2020-11-02 399106.SZ 0.0000 2020-11-03 399106.SZ 2255.0834 2020-11-03 399300.SZ 0.0000
目标与预期结果
新增列C,按Group列分组后,基于Value列对非零值进行自动递增编号;零值对应的C列设为NaN,递增时跳过零值。
预期结果:
Group Value C 0 A 2 1 1 A 4 2 2 B 1 1 3 B 3 2 4 B 0 NaN 5 C 0 NaN 6 C 5 1
尝试代码
df['C']=df.groupby('Group').transform(lambda x: x[x>0].cumsum()+1)
问题分析与解决方案
当前代码的问题在于:用cumsum()对非零值求和而非计数,且x[x>0]过滤零值后会导致transform的索引不匹配,最终结果不符合预期。
以下是两种可行的解决方案:
方案一:分步实现(清晰易懂)
import pandas as pd # 1. 标记非零值为1,零值为0 df['non_zero_flag'] = df['Value'].gt(0).astype(int) # 2. 按Group分组后累计计数 df['C'] = df.groupby('Group')['non_zero_flag'].cumsum() # 3. 将原Value为0的行的C列设为NaN df.loc[df['Value'] == 0, 'C'] = pd.NA # 4. 移除临时标记列(可选) df = df.drop('non_zero_flag', axis=1)
方案二:简洁写法(一行完成)
df['C'] = df.groupby('Group')['Value'].apply( lambda x: x.gt(0).cumsum().where(x.gt(0)) )
执行任意一种方案后,即可得到符合预期的结果。
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

