【问题标题】:Search for Multiple String Values of Entire Row of Dataframe in python pandas在python pandas中搜索整行Dataframe的多个字符串值
【发布时间】:2018-06-13 20:44:05
【问题描述】:

在熊猫数据框中,我想逐行搜索多个字符串值。如果该行包含一个字符串值,则该函数将为该行添加/打印到基于
的 df 1 或 0 末尾的空列中 关于如何选择匹配(部分)字符串的 Pandas DataFrame 行的教程有很多。

例如:

import pandas as pd

#create sample data
data = {'model': ['Lisa', 'Lisa 2', 'Macintosh 128K', 'Macintosh 512K'],
        'launched': [1983,1984,1984,1984],
        'discontinued': [1986, 1985, 1984, 1986]}

df = pd.DataFrame(data, columns = ['model', 'launched', 'discontinued'])
df

我从这个网站上提取了上面的例子: https://davidhamann.de/2017/06/26/pandas-select-elements-by-string/

如何对整行进行多值搜索:'int'、'tos'、'198'?

然后打印到下一个停止的列中,根据该行是否包含该关键字,该列将具有 1 或 0。

【问题讨论】:

    标签: python string pandas dataframe


    【解决方案1】:

    如果你有

    l=['int', 'tos', '198']
    

    然后你使用str.contains 通过与'|' 连接来获取包含任何这些单词的每个模型

    df.model.str.contains('|'.join(l))
    
    0    False
    1    False
    2     True
    3     True
    

    编辑

    如果打算按照@jpp 的解释检查所有列,我建议:

    from functools import reduce
    res = reduce(lambda a,b: a | b, [df[col].astype(str).str.contains(m) for col in df.columns])
    
    0    False
    1     True
    2     True
    3     True
    

    如果你想把它作为一个包含整数值的列,就这样做

    df['new_col'] = res.astype(int)
    
         new_col
    0    0
    1    1
    2    1
    3    1
    

    【讨论】:

      【解决方案2】:

      如果我理解正确,您希望检查每行的所有列中是否存在字符串。鉴于您有混合类型(整数、字符串),这并不简单。一种方法是将pd.DataFrame.apply 与自定义函数一起使用。

      我们需要记住的要点是将整个数据框转换为类型str,因为您无法测试整数中子字符串的存在。

      match = ['int', 'tos', '1985']
      
      def string_finder(row, words):
          if any(word in field for field in row for word in words):
              return True
          return False
      
      df['isContained'] = df.astype(str).apply(string_finder, words=match, axis=1)
      
      print(df)
      
                  model  launched  discontinued  isContained
      0            Lisa      1983          1986        False
      1          Lisa 2      1984          1985         True
      2  Macintosh 128K      1984          1984         True
      3  Macintosh 512K      1984          1986         True
      

      【讨论】:

        【解决方案3】:

        因此,不使用花哨的 pandas 人员的最简单方法是使用两个 for 循环。我想如果有人可以提供更好的解决方案,但我的方法是这样的:

        def check_all_for(column_name, search_terms):
            df[column_name] = ''
            for row in df.iterrows():
                flag = 0
                for element in row:
                    for search_term in search_terms:
                        if search_term in (str(element)).lower():
                            flag = 1
                row[column_name] = flag
        

        假设您已将 dataframe 定义为 df 并且您想用 1 和 0 标记新列

        【讨论】:

          【解决方案4】:

          您需要检查model 是否是match 的子字符串。

          match = [ 'int', 'tos', '198']
          df['isContained'] = df['model'].apply(lambda x: 1 if any(s in x for s in match) else 0)
          

          输出:

                      model  launched  discontinued  isContained
          0            Lisa      1983          1986            0
          1          Lisa 2      1984          1985            0
          2  Macintosh 128K      1984          1984            1
          3  Macintosh 512K      1984          1986            1
          

          【讨论】:

            【解决方案5】:

            @Guy_Fuqua,我的理解是您想确保所有单词都包含在一行中,对吗?

            如果是这样,那么对 jpp 答案稍作修改将帮助您实现这一点,请注意此处的 AssessAllString 函数

            match = ['int', 'tos', '1984']
            
            def string_finder(row, words):
                if any(word in field for field in row for word in words):
                    return True
                return False
            
            def AssessAllString (row,words):
                b=True
                for x in words:
                  b = b&string_finder(row,[x])
                return b
            
            df['isContained'] = df.astype(str).apply(AssessAllString, words=match, axis=1)
            
            print(df)
            
                        model  launched  discontinued  isContained
            0  Lisa            1983      1986          False      
            1  Lisa 2          1984      1985          False      
            2  Macintosh 128K  1984      1984          True       
            3  Macintosh 512K  1984      1986          True 
            

            另一个例子:

            match = ['isa','1984']
            df['isContained'] = df.astype(str).apply(AssessAllString, words=match, axis=1)
            
                        model  launched  discontinued  isContained
            0  Lisa            1983      1986          False      
            1  Lisa 2          1984      1985          True       
            2  Macintosh 128K  1984      1984          False      
            3  Macintosh 512K  1984      1986          False 
            

            我认为代码仍然需要优化,但到目前为止应该符合目的

            【讨论】:

              猜你喜欢
              • 2019-05-04
              • 2020-10-13
              • 2022-01-03
              • 2017-09-09
              • 2012-08-20
              • 2021-09-05
              • 2015-05-12
              • 2022-01-03
              • 2014-04-16
              相关资源
              最近更新 更多