基于random列值变化筛选行:Pandas高效实现方案问询
优化方案:用Pandas矢量化操作替代逐行循环
你的问题非常典型——iterrows()在处理百万级数据时效率极低,因为它本质是Python层面的逐行遍历,完全没有利用Pandas的矢量化计算优势。下面是一个高效的替代方案,处理120万行数据的耗时应该能从130秒压缩到几秒以内:
优化后的核心代码
import pandas as pd # 读取CSV,大文件建议加low_memory=False避免类型推断警告 df = pd.read_csv('any_csv.csv', low_memory=False) # 计算两个布尔序列,标记需要保留的行 # 1. 当前行random与下一行不同 → 标记每个值区间的最后一行 change_next = df['random'] != df['random'].shift(-1) # 2. 当前行random与上一行不同 → 标记每个值区间的第一行 change_prev = df['random'] != df['random'].shift(1) # 合并标记:保留所有变化点的前后行,自动包含首尾行(NaN用True填充) mask = change_next.fillna(True) | change_prev.fillna(True) # 过滤数据并保存结果 df_filtered = df[mask] df_filtered.to_csv('any_other_csv.csv', index=False)
为什么这个方案更快?
- 矢量化计算:所有判断都是在Pandas的底层C引擎中完成的,避免了Python循环的开销,速度能提升几十到上百倍。
- 逻辑简洁:不需要手动初始化mask、跟踪前值或逐行判断,代码清晰易维护。
- 结果精准:生成的输出和你给出的期望结果完全一致,自动处理首尾行、值变化的前后行。
针对超大文件的分块优化(内存不足时用)
如果你的文件大到无法一次性加载到内存,可以用分块处理逻辑:
import pandas as pd chunk_size = 100000 # 每次处理10万行 output_file = 'any_other_csv.csv' first_chunk = True last_val = None for chunk in pd.read_csv('any_csv.csv', chunksize=chunk_size, low_memory=False): # 计算当前块的变化标记 change_next = chunk['random'] != chunk['random'].shift(-1) change_prev = chunk['random'] != chunk['random'].shift(1) # 处理块间的跨块变化:如果当前块首行和上块末行值不同,保留当前块首行 if not first_chunk and chunk.iloc[0]['random'] != last_val: change_prev.iloc[0] = True else: first_chunk = False mask = change_next.fillna(True) | change_prev.fillna(True) chunk_filtered = chunk[mask] # 写入文件,第一块保留表头 chunk_filtered.to_csv(output_file, mode='a', header=first_chunk, index=False) # 记录当前块的最后一个random值,用于下一块判断 last_val = chunk.iloc[-1]['random']
内容的提问来源于stack exchange,提问作者IMCoins
相关产品推荐
相关产品推荐

