代码之家  ›  专栏  ›  技术社区  ›  sudonym

如何测试熊猫数据框字符串列中的哪个单元格包含给定引用字符串的子字符串?

  •  1
  • sudonym  · 技术社区  · 7 年前

    我正在处理的熊猫数据框如下所示:

    0 Item         Category
    1 Hammer       A
    2 Car          A
    3 Cardiologist B
    4 Park         A
    5 Parkway      A
    6 CarparkCar   A
    

    我需要找到所有的细胞 Item 包含特定字母序列的,定义为引用词的子字符串。我对包含参考词中不存在的其他字母的单元格不感兴趣。

    reference_word = Carpark
    

    所需输出:

    0 Item         Category   Contains_substring_of_reference_word
    1 Hammer       A          FALSE
    2 Car          A          TRUE
    3 Cardiologist B          FALSE
    4 Park         A          TRUE
    5 Parkway      A          FALSE
    6 CarparkCar   A          TRUE
    

    如何检查熊猫数据框列的哪个单元格包含给定单词/字符串的子字符串?

    2 回复  |  直到 7 年前
        1
  •  3
  •   cs95 abhishek58g    7 年前

    选项1
    一种简单的方法是使用 apply + set.issubset -

    v = df.Item.str.lower().apply(lambda x: set(x).issubset('carpark'))
    v
    
    0    False
    1     True
    2    False
    3     True
    4    False
    5     True
    Name: Item, dtype: bool
    

    将结果分配回-

    df['Contains_substring_of_reference_word'] = v
    df
    
               Item Category  Contains_substring_of_reference_word
    0        Hammer        A                                 False
    1           Car        A                                  True
    2  Cardiologist        B                                 False
    3          Park        A                                  True
    4       Parkway        A                                 False
    5    CarparkCar        A                                  True
    

    选项2
    另一个解决方案使用 set.difference 操作-

    (df.Item.str.lower().apply(set) - set('carpark')).str.len() == 0
    
    0    False
    1     True
    2    False
    3     True
    4    False
    5     True
    Name: Item, dtype: bool
    

    选项3
    添加另一个选项 np.vectorize ,这应该更快。

    c = set('carpark')
    def foo(x):
         return c.issuperset(x.lower())
    
    v = np.vectorize(foo)
    
    v(df.Item)
    array([False,  True, False,  True, False,  True], dtype=bool)
    

    计时

    df = pd.concat([df] * 100000, ignore_index=True)  
    
    %timeit df.Item.str.lower().apply(lambda x: set(x).issubset('carpark'))
    1 loop, best of 3: 927 ms per loop
    
    %timeit (df.Item.str.lower().apply(set) - set('carpark')).str.len() == 0
    1 loop, best of 3: 1.13 s per loop
    
    %timeit v(df.Item)
    1 loop, best of 3: 497 ms per loop
    
        2
  •  1
  •   piRSquared    7 年前

    您可以通过理解和使用 <= 表示子集。

    sets = np.array([set(x.lower()) for x in df.Item.values.tolist()])
    df.assign(Bool=sets <= set('carpark'))
    
               Item Category   Bool
    0                              
    1        Hammer        A  False
    2           Car        A   True
    3  Cardiologist        B  False
    4          Park        A   True
    5       Parkway        A  False
    6    CarparkCar        A   True