【问题标题】:How to group by according to the values of a list present in a column in dataframe python如何根据数据框python中列中存在的列表的值进行分组
【发布时间】:2018-08-19 14:27:31
【问题描述】:

我有一个像这样的熊猫电影数据框

id, name,     genre, release_year 
1    A    [a,b,c]     2017
2    B    [b,c]       2017
3    C    [a,c]       2010
4    D    [d,c]       2010
....

我想根据流派列表中的值按电影分组。 我的预期输出是:

year, genre, number_of_movies
2017  a       1
2017  b       2
2017  c       2
2010  a       1
2010  c       2 
...

有人可以帮我实现这个吗?

【问题讨论】:

  • 你有没有尝试过?

标签: python python-3.x pandas dataframe pandas-groupby


【解决方案1】:

这是一个collections.Counter 方法,它具有O(n) 复杂度,并且不需要df.groupby / df.apply:

from collections import Counter
from itertools import product, chain
import pandas as pd

df = pd.DataFrame({'id': [1, 2, 3, 4],
                   'name': ['A', 'B', 'C', 'D'],
                   'genre': [['a', 'b', 'c'], ['b', 'c'], ['a', 'c'], ['d', 'c']],
                   'year': [2017, 2017, 2010, 2010]})

c = Counter(chain.from_iterable([list(product([x['year']], x['genre'])) \
                                 for idx, x in df.iterrows()]))

# Counter({(2010, 'a'): 1,
#          (2010, 'c'): 2,
#          (2010, 'd'): 1,
#          (2017, 'a'): 1,
#          (2017, 'b'): 2,
#          (2017, 'c'): 2})

df = pd.DataFrame.from_dict(c, orient='index')

#            0
# (2017, a)  1
# (2017, b)  2
# (2017, c)  2
# (2010, a)  1
# (2010, c)  2
# (2010, d)  1

【讨论】:

  • 感谢您的回复。我尝试了解决方案。但是我的类型是:['Adventures','comedy'..] 在这种情况下,在第一步之后,我得到的输出如下:(2016, '['): 33, (2016, "'"): 206, (2016,'A'):40,(2016,'d'):28,(2016,'v'):20,(2016,'e'):83,(2016,'n'):70, (2016, 't'): 61, (2016, 'u'): 21, (2016, 'r'): 59, (2016, ','): 70, (2016, ''): 78, . ...但是预期的输出是 (2016, 'Adventure'), 40 ...
  • @Sitabja,我很困惑。根据您的输入,我已经达到了您想要的输出(使用 (year,genre) 作为索引除外).. 所以似乎逻辑被误用或您的数据不同。
  • 它正在工作,实际上我的输入有一些问题,我能够解决。非常感谢您的快速响应
【解决方案2】:

为了提高性能,使用itertools.chain 将genre 列展平:

from itertools import chain

df = pd.DataFrame({
      'genre' : list(
           chain.from_iterable(df.genre.tolist())
       ), 
      'release_year' : df.release_year.repeat(df.genre.str.len())
})

df
  genre  release_year
0     a          2017
0     b          2017
0     c          2017
1     b          2017
1     c          2017
2     a          2010
2     c          2010
3     d          2010
3     c          2010

现在,在genre 和release_year 上进行分组,然后找到每个组的size:

df.groupby(
     ['genre', 'release_year'], sort=False
 ).size()\
  .reset_index(name='number_of_movies')

  genre  release_year  number_of_movies
0     a          2017                 1
1     b          2017                 2
2     c          2017                 2
3     a          2010                 1
4     c          2010                 2
5     d          2010                 1

【讨论】:

    【解决方案3】:

    另一个很酷的方法是使用Counter,即

    from collections import Counter
    
    ndf = df.groupby('release_year')['genre'].apply(lambda x : Counter(np.concatenate(x.values))).reset_index()
    
    ndf = ndf.set_axis('release_year,genre,number_of_movies'.split(','),inplace=False,axis=1)
    

    输出:

       release_year genre  number_of_movies
    0          2010     a               1.0
    1          2010     c               2.0
    2          2010     d               1.0
    3          2017     a               1.0
    4          2017     b               2.0
    5          2017     c               2.0
    

    【讨论】:

      【解决方案4】:

      您可以通过构造函数创建新的DataFrame,通过stack 进行整形,并使用groupby 和size 进行计数:

      df1 = (pd.DataFrame(df['genre'].values.tolist(), index=df['release_year'].values)
               .stack()
               .reset_index(name='genre')
               .groupby(['release_year','genre'])
               .size()
               .reset_index(name='number_of_movies'))
      
      print (df1)
         release_year genre  number_of_movies
      0          2010     a                 1
      1          2010     c                 2
      2          2010     d                 1
      3          2017     a                 1
      4          2017     b                 2
      5          2017     c                 2
      

      【讨论】:

        猜你喜欢
        • 2016-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-19
        相关资源
        最近更新 更多