如何加速Pandas中拆分列生成新列的操作?
高效填充Pandas DataFrame的root列需求
现有一个包含last_element和root列的Pandas DataFrame,示例代码及数据如下:
import pandas as pd df_test = pd.DataFrame({"last_element":["2000A01.2 B003", "8000N02 B001"]*100000, "root":[None, "8000N02"]*100000}) df_test.head()
数据样例:
| last_element | root | |
|---|---|---|
| 0 | 2000A01.2 B003 | |
| 1 | 8000N02 B001 | 8000N02 |
| 2 | 2000A01.2 B003 | |
| 3 | 8000N02 B001 | 8000N02 |
| 4 | 2000A01.2 B003 |
处理规则:当root列值为空时,从last_element列中提取空格前的内容作为root值。目前已实现两种解决方案,但真实数据处理耗时超一分钟,需更高效的实现方法。
现有解决方案1 - 自定义函数
%%timeit df_test = pd.DataFrame({"last_element":["2000A01.2 B003", "8000N02 B001"]*100000, "root":[None, "8000N02"]*100000}) def fill_root(row): if pd.isna(row.root) & pd.notna(row.last_element): return row.last_element.split(' ')[0] else: return row.root df_test.assign(new_root = lambda x: x.apply(fill_root, axis=1))
耗时:
5.14 s ± 41.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
现有解决方案2 - 匿名函数Apply方法
%%timeit df_test['new_root'] = df_test.apply(lambda row: row.last_element.split(' ')[0] if pd.isna(row.root) else row.root, axis=1)
耗时:
3.67 s ± 21.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
高效优化方案 - 矢量化操作实现
Pandas的apply是逐行处理,效率较低,改用矢量化字符串操作+fillna可以大幅提升速度:
%%timeit df_test = pd.DataFrame({"last_element":["2000A01.2 B003", "8000N02 B001"]*100000, "root":[None, "8000N02"]*100000}) # 提取last_element空格前的部分,限制仅分割一次提升效率 temp_root = df_test['last_element'].str.split(' ', n=1).str[0] # 用提取结果批量填充root的空值 df_test['new_root'] = df_test['root'].fillna(temp_root)
耗时测试(同数据集):
52.8 ms ± 2.1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
优化原理
- 矢量化操作基于Pandas底层C实现批量处理,避免了逐行Python循环的性能开销
str.split(' ', n=1)限制仅分割一次,减少不必要的计算fillna直接批量填充缺失值,逻辑简洁且性能远高于逐行判断
内容的提问来源于stack exchange,提问作者Marco_CH
相关产品推荐
相关产品推荐

