【问题标题】:Python pandas cross check substring and contain relations between columnsPython pandas 交叉检查子字符串并包含列之间的关系
【发布时间】:2022-10-24 10:59:38
【问题描述】:
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

A 和 B 同时包含字符串和子字符串,我想检查 A 列是否有值“计数器”,该值是在 B 列“计数”中有一个子字符串,或者是 B 列“计数器”的子字符串.如果任何对此满意,返回True。 (类似于 .isin 和 .str.contains 的组合)。 C 是输出,它说明 A 的值是 B 的子字符串还是 A 包含 B。像 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 列执行 or 操作

但如果我反过来做,比如

list2=a1['B'].tolist()
output2=[]
for i in list2:
    output2.append(any(a1['A'].str.contains(i,regex=False)))

清单 2 将包含关于 B 列而不是 A 列的验证结果。

我怎么能写这个代码?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    实现此目的的一种方法如下:

    • 对于a_contains_b,使用Series.str.contains 和一个由B 列中的值列表组成的字符串,joined| 分隔符来创建替代项(例如:'animal|count|cata|rownumbers|counters|inner|time|strong|kind|membrane')。
    • 对于b_contains_a,我们希望使用Series.str.extractall,因为我们需要将结果反馈给Series.isin,以了解A 列中的哪些行已匹配。 IE。 extractall (+ [0].tolist()) 的结果将是 ['ani', 'counter'],我们将其用作 df.A.isin 的输入。
    • 最后,我们使用两个布尔系列作为新列的输入。使用|,因为如果任一系列包含True,我们需要True。将结果括在括号中并应用 Series.where 结合 Series.notna 以覆盖行中的所有 False 值,而列 NaN 中的值是 A
    import pandas as pd
    import numpy as np
    
    data = {'A': {0: 'catastrop', 1: 'ani', 2: 'rows', 3: 'Second', 4: 'counter', 
                  5: 'column', 6: np.nan, 7: np.nan, 8: np.nan, 9: np.nan}, 
            'B': {0: 'animal', 1: 'count', 2: 'cata', 3: 'rownumbers', 
                  4: 'counters', 5: 'inner', 6: 'time', 7: 'strong', 8: 'kind', 
                  9: 'membrane'}, 
            'C': {0: True, 1: True, 2: False, 3: False, 4: True, 5: False, 
                  6: np.nan, 7: np.nan, 8: np.nan, 9: np.nan}}
    
    df = pd.DataFrame(data)
    
    a_contains_b = df.A.str.contains('|'.join(df.B.dropna().tolist()))
    
    b_contains_a = df.A.isin(df.B.str.extractall(
        '('+'|'.join(df.A.dropna().tolist()) + ')')[0].tolist())
    
    df['D'] = (b_contains_a | a_contains_b).where(df.A.notna())
    
    print(df)
    
               A           B      C      D
    0  catastrop      animal   True   True
    1        ani       count   True   True
    2       rows        cata  False  False
    3     Second  rownumbers  False  False
    4    counter    counters   True   True
    5     column       inner  False  False
    6        NaN        time    NaN    NaN
    7        NaN      strong    NaN    NaN
    8        NaN        kind    NaN    NaN
    9        NaN    membrane    NaN    NaN
    

    注:如果您希望匹配不区分大小写,请考虑使用Series.str.lower。对于str.contains,您也可以使用参数case,并将其设置为False

    【讨论】:

      猜你喜欢
      • 2017-10-03
      • 1970-01-01
      • 1970-01-01
      • 2021-03-22
      • 1970-01-01
      • 2021-10-02
      • 1970-01-01
      • 2015-07-27
      • 1970-01-01
      相关资源
      最近更新 更多