如何根据前置值筛选DataFrame,仅保留符合特定条件的数值?
问题说明
现有DataFrame df,要生成全0的新DataFrame df2,仅当以下两个条件同时满足时,对应位置设为1:
- 原
df中该位置的值是1 - 该位置之前有连续10个0(即从当前行的前一行开始,往前数10行全是0)
你之前写的代码运行后全为0,代码如下:
df2 = df.copy() for col in df2.columns: count_zeros = 0 for i in range(1, len(df2)): if df2[col][i] == 1 and count_zeros == 10: df2[col][i] = 1 count_zeros = 0 elif df2[col][i] == 1: df2[col][i] = 0 count_zeros = 0 else: count_zeros += 1
举个例子:只有第一列8/11/23和第三列8/16/23位置的1符合要求,应该保留,其他位置全为0。
原代码的问题
- 计数逻辑偏差:你用
count_zeros累加遍历过程中的连续0,但这个计数是从列的开头开始累计,不是以当前位置为终点往前数10个。比如中间出现过1会重置计数,但无法准确判断当前位置的前10个是否全为0。 - 索引遗漏:
range(1, len(df2))跳过了索引0的行,就算第一行的1符合条件也不会被处理。 - 基于修改后的副本计数:你先复制
df到df2,再修改df2的值来统计,这会干扰结果——比如原df的1被改成0后,后续会把这个0算进连续0的计数里,但实际上应该基于原始数据的0/1来统计。
正确解法
方法一:用Pandas向量化操作(推荐,处理大数据更快)
不用嵌套循环,借助Pandas的分组和累计计算实现:
import pandas as pd # 先创建全0的df2 df2 = pd.DataFrame(0, index=df.index, columns=df.columns) for col in df.columns: # 把原列的0标记为1,1标记为0,方便统计连续0的长度 zero_flag = (df[col] == 0).astype(int) # 给连续的0分组:每次遇到原数据的1(即zero_flag为0)就换一个分组 groups = (zero_flag != zero_flag.shift()).cumsum() # 计算每个分组内的连续0累计数 consecutive_zero_count = zero_flag.groupby(groups).cumsum() # 筛选符合条件的位置:原数据是1,且前面连续0的数量≥10 valid_positions = (df[col] == 1) & (consecutive_zero_count.shift(1) >= 10) # 把符合条件的位置设为1 df2.loc[valid_positions, col] = 1
方法二:修正循环逻辑(适合小数据集)
如果一定要用循环,必须基于原始df统计连续0,不能用修改后的df2:
df2 = pd.DataFrame(0, index=df.index, columns=df.columns) for col in df.columns: count_zeros = 0 for i in range(len(df)): val = df[col].iloc[i] if val == 1: # 检查前面是否攒够了10个连续0 if count_zeros >= 10: df2[col].iloc[i] = 1 # 遇到1就重置计数 count_zeros = 0 else: count_zeros += 1
注意点
- 如果要求是恰好连续10个0(不是至少10个),把代码里的
>=10改成==10即可。 - 方法一用Pandas内置功能,比循环效率高很多,数据集越大差距越明显。
内容的提问来源于stack exchange,提问作者ab ab
相关产品推荐
相关产品推荐

