【问题标题】:Count regex matches in one column by values in another column with pandas用熊猫计算另一列中的正则表达式匹配项
【发布时间】:2020-09-01 04:03:56
【问题描述】:

我正在使用 pandas,并且有一个数据框,其中包含一系列句子和说它们的人,如下所示:

 sentence                 person
 'hello world'              Matt
 'cake, delicious cake!'    Matt
 'lovely day'               Maria
 'i like cake'             Matt
 'a new day'                Maria
 'a new world'              Maria

我想通过person 计算sentence(例如cakeworldday)中正则表达式字符串的非重叠匹配。注意sentence 的每一行可能包含多个匹配项(例如cake):

person        'day'        'cake'       'world'
Matt            0            3             1
Maria           2            0             1

到目前为止,我正在这样做:

rows_cake = df[df['sentences'].str.contains(r"cake")
counts_cake = rows_cake.value_counts()

但是,这个str.contains 给了我包含cake 的行,但不是cake 的单个实例。

我知道我可以在rows_cake 上使用str.counts(r"cake")。但是,在实践中,我的数据框非常大(> 1000 万行),并且我使用的正则表达式非常复杂,因此如果可能,我正在寻找更有效的解决方案。

【问题讨论】:

    标签: python regex pandas dataframe


    【解决方案1】:

    也许您应该首先尝试获取句子本身,然后使用re 来执行优化的正则表达式:

    for row in df.itertuples(index=False):
       do_some_regex_stuff(row[0], row[1])#in this case row[0] is a sentence. row[1] is person
    

    据我所知,itertuples 非常安静(注释 1 here)。所以你唯一的优化问题是正则表达式本身。

    【讨论】:

      【解决方案2】:

      我想出了一个相当简单的解决方案。但不能声称它是最快或最有效的。

      import pandas as pd
      import numpy as np
      
      # to be used with read_clipboard()
      '''
      sentence    person
      'hello world'   Matt
      'cake, delicious cake!' Matt
      'lovely day'    Maria
      'i like cake'   Matt
      'a new day' Maria
      'a new world'   Maria
      '''
      
      df = pd.read_clipboard()
      # print(df)
      

      输出:

                        sentence person
      0            'hello world'   Matt
      1  'cake, delicious cake!'   Matt
      2             'lovely day'  Maria
      3            'i like cake'   Matt
      4              'a new day'  Maria
      5            'a new world'  Maria
      

      .

      # if the list of keywords is fix and relatively small
      keywords = ['day', 'cake', 'world']
      
      # for each keyword and each string, counting the occourance
      for key in keywords:
          df[key] = [(len(val.split(key)) - 1) for val in df['sentence']]
      
      # print(df)
      

      输出:

                       sentence person  day  cake  world
      0            'hello world'   Matt    0     0      1
      1  'cake, delicious cake!'   Matt    0     2      0
      2             'lovely day'  Maria    1     0      0
      3            'i like cake'   Matt    0     1      0
      4              'a new day'  Maria    1     0      0
      5            'a new world'  Maria    0     0      1
      

      .

      # create a simple pivot with what data you needed
      df_pivot = pd.pivot_table(df, 
      values=['day', 'cake', 'world'], 
      columns=['person'], 
      aggfunc=np.sum).T
      
      # print(df_pivot)
      

      最终输出:

              cake  day  world
      person
      Maria      0    2      1
      Matt       3    0      1
      

      如果这似乎是一种好方法,特别是考虑到数据量,欢迎提出建议。渴望学习。

      【讨论】:

        【解决方案3】:

        由于这主要涉及字符串,我建议将计算从 Pandas 中取出 - 在大多数情况下,在字符串操作方面,Python 比 Pandas 更快:

        #read in data
        df = pd.read_clipboard(sep='\s{2,}', engine='python')
        
        #create a dictionary of persons and sentences : 
        from collections import defaultdict, ChainMap
        d = defaultdict(list)
        for k,v in zip(df.person, df.sentence):
            d[k].append(v)
        
        
        d = {k:",".join(v) for k,v in d.items()}
        
        #search words
        strings = ("cake", "world", "day")
        
        #get count of words and create a dict
        m = defaultdict(list)
        for k,v in d.items():
            for st in strings:
                m[k].append({st:v.count(st)})
        
        res = {k:dict(ChainMap(*v)) for k,v in m.items()}
        
        
        print(res)
        {'Matt': {'day': 0, 'world': 1, 'cake': 3},
         'Maria': {'day': 2, 'world': 1, 'cake': 0}}
        
        output = pd.DataFrame(res).T
        
               day  world   cake
        Matt    0     1     3
        Maria   2     1     0
        

        测试速度,看看哪个更好。这对我和其他人也很有用。

        【讨论】:

        • 谢谢!这就说得通了。在这种情况下,strings 还可以包含一堆正则表达式吗?我使用的一些正则表达式非常复杂。
        • 是的,你可以,只要确保你会调整你的正则表达式以适应。
        猜你喜欢
        • 2020-05-25
        • 2016-03-08
        • 1970-01-01
        • 2020-01-15
        • 1970-01-01
        • 2020-06-09
        • 1970-01-01
        • 2021-06-16
        • 1970-01-01
        相关资源
        最近更新 更多