如何采用更Pythonic且高效的方法在Pandas DataFrame中多条件处理字符串生成新列
更Pythonic的Pandas列生成方案:摆脱iterrows,用向量化操作提速
嘿,我完全懂你想摆脱iterrows()逐行遍历的低效,改用Pandas原生向量化方法生成新列的需求——这绝对是提升代码效率和可读性的正确方向!
下面我会用np.select()结合Pandas字符串处理方法,把你那一堆if-elif逻辑转换成简洁高效的向量化代码,完美匹配你想要的输出结果:
第一步:准备示例数据
先还原你的原始DataFrame:
import pandas as pd import numpy as np df = pd.DataFrame( [ ["ab", "abcdef"], ["de", "abdghi"], ["gh", "0"], ["ij", "123-456-789"], ["kl", "afzhkp"], ["mn", "qtbkpse"], ], columns=["c1", "Office"] )
第二步:用np.select()构建多分支逻辑
np.select()可以让我们把多个条件和对应的值配对,完美替代嵌套的if-elif结构,而且全程是向量化操作,速度比iterrows()快太多!
生成N_1列
我们先定义所有触发N_1取值的条件,以及对应的值:
# 定义N_1的触发条件 conditions_n1 = [ # 情况1:Office为"0"或空值 (df["Office"] == "0") | df["Office"].isna(), # 情况2:以"abc"或"abd"开头 df["Office"].str.startswith(("abc", "abd")), # 情况3:以"Bu"开头(保留你原逻辑里的分支) df["Office"].str.startswith("Bu"), # 情况4:包含"-"字符 df["Office"].str.contains("-"), # 情况5:Office长度为6 df["Office"].str.len() == 6 ] # 对应每个条件的N_1取值 values_n1 = [ "Unknown", df["Office"].str[:3], df["Office"].str.split(" ").str[0], df["Office"].str.split("-").str[1], df["Office"].str[:3] ] # 生成N_1:默认情况取前4个字符 df["N_1"] = np.select(conditions_n1, values_n1, default=df["Office"].str[:4])
生成N_2列
用同样的逻辑处理N_2:
# 定义N_2的触发条件 conditions_n2 = [ (df["Office"] == "0") | df["Office"].isna(), df["Office"].str.startswith(("abc", "abd")), df["Office"].str.startswith("Bu"), df["Office"].str.contains("-"), df["Office"].str.len() == 6 ] # 对应每个条件的N_2取值 values_n2 = [ "Unknown", df["Office"].str[3:], df["Office"].str.split(" ").str[1], df["Office"].str.split("-").str[2], df["Office"].str[3:] ] # 生成N_2:默认情况取第4个字符之后的部分 df["N_2"] = np.select(conditions_n2, values_n2, default=df["Office"].str[4:])
第三步:验证结果
运行完上面的代码后,你的DataFrame就会和期望的完全一致:
c1 Office N_1 N_2 0 ab abcdef abc def 1 de abdghi abd ghi 2 gh 0 Unknown Unknown 3 ij 123-456-789 456 789 4 kl afzhkp afz hkp 5 mn qtbkpse qtbk pse
为什么这个方案更好?
- 速度飙升:向量化操作完全避免了逐行遍历的开销,数据量越大,对比
iterrows()的优势越明显 - 可读性更强:把条件和取值清晰分离,逻辑一目了然,后期维护更方便
- 原生优化:Pandas的
str方法都是底层优化过的,比自己写循环高效得多
内容的提问来源于stack exchange,提问作者pymat
相关产品推荐
相关产品推荐

