【问题标题】:Extract and count unique hashtags per row from a pandas dataframe从 pandas 数据框中提取和计算每行的唯一主题标签
【发布时间】:2018-11-07 23:42:43
【问题描述】:

我有一个带有字符串列 Posts 的 pandas 数据框 df,如下所示:

df['Posts']
0       "This is an example #tag1"
1       "This too is an example #tag1 #tag2"
2       "Yup, still an example #tag1 #tag1 #tag3"

当我尝试使用以下代码计算主题标签的数量时,

count_hashtags = df['Posts'].str.extractall(r'(\#\w+)')[0].value_counts()

我明白了,

#tag1             4
#tag2             1
#tag3             1

但我需要计算每行唯一主题标签的数量,如下所示:

#tag1             3
#tag2             1
#tag3             1

【问题讨论】:

    标签: python python-3.x pandas counter series


    【解决方案1】:

    使用drop_duplicates去除每个帖子的重复标签,然后你可以使用value_counts

    df.Posts.str.extractall(
        r'(\#\w+)'
    ).reset_index().drop_duplicates(['level_0', 0])[0].value_counts()
    

    level=0 传递给reset_index 的较短替代方案

    df.Posts.str.extractall(
        r'(\#\w+)'
    ).reset_index(level=0).drop_duplicates()[0].value_counts()
    

    两者都会输出:

    #tag1    3
    #tag3    1
    #tag2    1
    Name: 0, dtype: int64
    

    【讨论】:

      【解决方案2】:

      这是使用itertools.chaincollections.Counter 的一种解决方案:

      import pandas as pd
      from collections import Counter
      from itertools import chain
      
      s = pd.Series(['This is an example #tag1',
                     'This too is an example #tag1 #tag2',
                     'Yup, still an example #tag1 #tag1 #tag3'])
      
      tags = s.map(lambda x: {i[1:] for i in x.split() if i.startswith('#')})
      
      res = Counter(chain.from_iterable(tags))
      
      print(res)
      
      Counter({'tag1': 3, 'tag2': 1, 'tag3': 1})
      

      性能基准测试

      collections.Counter 的速度大约是 pd.Series.str.extractall 的两倍:

      import pandas as pd
      from collections import Counter
      from itertools import chain
      
      s = pd.Series(['This is an example #tag1',
                     'This too is an example #tag1 #tag2',
                     'Yup, still an example #tag1 #tag1 #tag3'])
      
      def hal(s):
          return s.str.extractall(r'(\#\w+)')\
                  .reset_index(level=0)\
                  .drop_duplicates()[0]\
                  .value_counts()
      
      def jp(s):
          tags = s.map(lambda x: {i[1:] for i in x.split() if i.startswith('#')})
          return Counter(chain.from_iterable(tags))
      
      s = pd.concat([s]*100000, ignore_index=True)
      
      %timeit hal(s)  # 2.76 s per loop
      %timeit jp(s)   # 1.25 s per loop
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-03
        • 2019-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-12
        相关资源
        最近更新 更多