使用pandas从列值计数中获取顶行

时间:2017-08-10 13:35:45

标签: python pandas

我们说我有这种数据。这是对一些产品的一系列评论。

prod_id text    rating
AB123   some text   5
AB123   some text   2
AB123   some text   4
AC456   some text   3
AC456   some text   2
AD777   some text   2
AD777   some text   5
AD777   some text   5
AD777   some text   4
AE999   some text   4
AF000   some text   5
AG222   some text   5
AG222   some text   3
AG222   some text   3

我想知道哪个产品评论最多(行数最多),所以我使用以下代码来获得前3个产品(我只需要3个评价最多的产品)。

s = df['prod_id'].value_counts().sort_values(ascending=False).head(3)

然后我会得到这个结果。

AD777   4
AB123   3
AG222   3

但我真正需要的是带有上述ID的行。我需要所有AD777,AB123和AG222的整行,如下所示。

product_id  text    rating
AD777   some text   2
AD777   some text   5
AD777   some text   5
AD777   some text   4
AB123   some text   5
AB123   some text   2
AB123   some text   4
AG222   some text   5
AG222   some text   3
AG222   some text   3

我该怎么做?我试过了print(df.iloc[s]),但当然它没有用。当我阅读文档时,value_counts返回系列而非数据框。任何的想法?感谢

4 个答案:

答案 0 :(得分:2)

我认为您需要merge left加入与DataFrame index创建的s

df = pd.DataFrame({'prod_id':s.index}).merge(df, how='left')
print (df)
  prod_id       text  rating
0   AD777  some text       2
1   AD777  some text       5
2   AD777  some text       5
3   AD777  some text       4
4   AB123  some text       5
5   AB123  some text       2
6   AB123  some text       4
7   AG222  some text       5
8   AG222  some text       3
9   AG222  some text       3

答案 1 :(得分:2)

试试这个?

df[df.prod_id.isin(df.prod_id.value_counts().head(3).index)]

编辑: 感谢@jezrael指出订单问题。

df.assign(Forsort=df.prod_id.map(df.prod_id.value_counts().head(3))).\
      dropna().sort_values('Forsort',ascending=False).drop('Forsort',axis=1)



Out[150]: 
   prod_id  text  rating
5    AD777  some       2
6    AD777  some       5
7    AD777  some       5
8    AD777  some       4
0    AB123  some       5
1    AB123  some       2
2    AB123  some       4
11   AG222  some       5
12   AG222  some       3
13   AG222  some       3

答案 2 :(得分:2)

这是一个单线解决方案,它不使用辅助系列:

In [63]: df.assign(rank=df.groupby('prod_id')['prod_id']
    ...:                  .transform('size')
    ...:                  .rank(method='dense', ascending=False)) \
    ...:   .sort_values('rank') \
    ...:   .query("rank <= 3") \
    ...:   .drop('rank', 1)
Out[63]:
   prod_id       text  rating
5    AD777  some text       2
6    AD777  some text       5
7    AD777  some text       5
8    AD777  some text       4
0    AB123  some text       5
1    AB123  some text       2
2    AB123  some text       4
11   AG222  some text       5
12   AG222  some text       3
13   AG222  some text       3
3    AC456  some text       3
4    AC456  some text       2

但如果您已经拥有s系列,那么@ jezrael的解决方案看起来会更优雅。

答案 3 :(得分:0)

这是最适合我的解决方案:

Df.groupby('prod_id').first() 
相关问题