如何用Pandas实现列间字符串与子串的双向包含校验?
需求与解决方案
示例数据
| A | B | C |
|---|---|---|
| catastrop | animal | True |
| ani | count | True |
| rows | cata | False |
| Second | rownumbers | False |
| counter | counters | True |
| column | inner | False |
| time | ||
| strong | ||
| kind | ||
| membrane |
需求描述
现有包含字符串与子串的Pandas DataFrame列A和B,需实现列C的逻辑:若A的值是B的子串,或B的值是A的子串,满足任一条件则返回True,否则返回False(空值对应空结果)。例如:catastrop包含cata返回True,ani是animal的子串返回True。
尝试的代码
我初步编写的代码如下:
list1=a1['A'].tolist() output1=[] for i in list1: output1.append(any(a1['B'].str.contains(i,regex=False)))
并计划与B列的校验结果做或运算,但反向校验的代码:
list2=a1['B'].tolist() output2=[] for i in list2: output2.append(any(a1['A'].str.contains(i,regex=False)))
得到的是针对B列的校验结果,而非A列的。请问如何编写正确的Pandas代码实现需求?
正确实现方案
方案一:逐行判断(易理解)
import pandas as pd # 转换空字符串为pd.NA,统一空值判断逻辑 a1['A'] = a1['A'].replace('', pd.NA) a1['B'] = a1['B'].replace('', pd.NA) # 生成列C a1['C'] = a1.apply( lambda row: pd.NA if pd.isna(row['A']) or pd.isna(row['B']) else (row['A'] in row['B'] or row['B'] in row['A']), axis=1 )
方案二:矢量化操作(高性能)
如果数据集较大,优先用这个版本,避免逐行循环:
import pandas as pd # 转换空字符串为pd.NA a1['A'] = a1['A'].replace('', pd.NA) a1['B'] = a1['B'].replace('', pd.NA) # 生成两个子串判断掩码 mask_a_in_b = a1['A'].notna() & a1['B'].notna() & a1['B'].str.contains(a1['A'], regex=False) mask_b_in_a = a1['A'].notna() & a1['B'].notna() & a1['A'].str.contains(a1['B'], regex=False) # 合并掩码得到C列,空值位置填充pd.NA a1['C'] = (mask_a_in_b | mask_b_in_a).where(a1['A'].notna() & a1['B'].notna(), pd.NA)
关键说明
你的原代码逻辑错误在于:any(a1['B'].str.contains(i))是判断当前A值是否存在于所有B行中,而不是对应行的B值。上面的方案都是针对同一行的A和B进行子串判断,完全符合需求。
内容的提问来源于stack exchange,提问作者XJTLU media
相关产品推荐
相关产品推荐

