pandas逐行取字符串列指定索引字符匹配对应列值的方法
问题说明
现有如下结构的DataFrame:
Policy Letter Password Lower Upper Count Lower_Minus_1 Upper_Minus_1 0 4-5 l rllllj 4 5 4 3 4 1 4-10 s ssskssphrlpscsxrfsr 4 10 8 3 9 2 14-18 p ppppppppppppppppppp 14 18 19 13 17 3 1-6 z zzlzvmqbzzclrz 1 6 6 0 5 4 4-5 j jhjjhxhjkxj 4 5 5 3 4
需求为逐行读取Lower_Minus_1列的值作为索引,提取对应行Password列字符串该位置的字符,判断是否与Letter列的字符匹配。
固定取索引3的写法df['Password'].str[3] == df['Letter']可以正常运行,但仅能统一取所有行的第3位,不符合逐行动态取位的要求。自行尝试的两种写法均运行失败:
- 写法
print(df['Password'].str[df['Letter']] == df['Letter'])所有行均返回False,匹配成功总数为0 - 写法
print(df.apply(lambda x: x['Password'].str[x['Lower_Minus_1']], axis=1) == df['Letter'])抛出AttributeError,错误信息为'str' object has no attribute 'str'
失败原因分析
- 第一种写法传参错误:
Series.str[]支持传入等长的整数序列逐行取位,但你传入的是df['Letter'](存储的是待匹配的目标字符,不是位置索引),参数完全不符合要求,因此返回全False。 - 第二种写法误用
.str访问器:apply(axis=1)逐行遍历时,每行返回的x['Password']是原生Python字符串对象,不是pandas Series,不存在.str属性,直接用Python原生字符串索引取值即可,无需调用.str。
正确实现方案
以下三种写法均可实现需求,可根据场景选择:
- 方案1:pandas原生向量化写法(最简洁)
直接给str[]传入位置列df['Lower_Minus_1']即可,无额外循环开销:
match_result = df['Password'].str[df['Lower_Minus_1']] == df['Letter'] print(match_result)
- 方案2:修正apply逻辑(可读性最高)
去掉lambda中多余的.str访问器,直接对单行字符串取索引:
match_result = df.apply(lambda x: x['Password'][x['Lower_Minus_1']] == x['Letter'], axis=1) print(match_result)
- 方案3:列表推导式(性能最优,适合超大数据集)
原生Python遍历的开销远低于pandas apply,运行速度最快:
match_result = [pwd[pos] == target for pwd, pos, target in zip(df['Password'], df['Lower_Minus_1'], df['Letter'])] # 需要和原DataFrame索引对齐时,转成Series即可 # match_result = pd.Series(match_result, index=df.index)
三种写法前5行的输出均和固定取索引3的结果一致:
0 True 1 False 2 True 3 True 4 True dtype: bool
统计匹配成功总数直接调用match_result.sum()即可。
内容的提问来源于stack exchange,提问作者MarkS
相关产品推荐
相关产品推荐

