在另一列上分组后查找列值的最大出现次数

Posted

技术标签:

【中文标题】在另一列上分组后查找列值的最大出现次数【英文标题】:Finding max occurrence of a column's value, after group-by on another column 【发布时间】:2016-07-10 12:49:50 【问题描述】:

我有一个熊猫数据框:

        id                city
 000.tushar@gmail.com   Bangalore
 00078r@gmail.com       Mumbai
0007ayan@gmail.com      Jamshedpur
0007ayan@gmail.com      Jamshedpur
000.tushar@gmail.com    Bangalore
  00078r@gmail.com      Mumbai
  00078r@gmail.com      Vijayawada
  00078r@gmail.com      Vijayawada
  00078r@gmail.com      Vijayawada

我想找到 id-wise 最多出现的城市名称。因此,对于给定的 ID,我可以看出 - 这是他最喜欢的城市:

         id             city
000.tushar@gmail.com   Bangalore
00078r@gmail.com       Vijayawada
0007ayan@gmail.com     Jamshedpur

使用 groupby id 和 city 给出:

         id                   city       count
0  000.tushar@gmail.com       Bangalore    2
1      00078r@gmail.com        Mumbai      2
2      00078r@gmail.com      Vijayawada    3
3    0007ayan@gmail.com      Jamshedpur    2

如何进行下一步?我相信一些 group-by 申请会做到这一点,但不知道究竟会做什么。所以请建议。

如果某个 id 的两个或三个城市的计数相同,我可以返回其中任何一个城市。

【问题讨论】:

另一个选项是pd.crosstab(df['city'], df['id']).idxmax(axis=0),但如果 id 和 city 有许多唯一值,crosstab 可能会生成一个非常大的框架。 对于我提到的数据框,这个交叉表 sn-p 只给了我 000.tushar@gmail.com Vijayawada 记录。我认为它是在整体 id 集上找到最大城市计数。不是 id 明智的最大城市计数。 pandas recommended 方法是 groupby('id').apply(your_custom_function),根据我的回答 【参考方案1】:

recommended 方法是groupby('id').apply(your_custom_function),其中 your_custom_function 按“城市”聚合并返回最大值(或如您所述,多个最大值)。我们甚至不必使用.agg('city')

import pandas as pd

def get_top_city(g):
    return g['city'].value_counts().idxmax()    

df = pd.DataFrame.from_records(
         [('000.tushar@gmail.com', 'Bangalore'), ('00078r@gmail.com',     'Mumbai'),
         ('0007ayan@gmail.com',   'Jamshedpur'),('0007ayan@gmail.com',   'Jamshedpur'),
         ('000.tushar@gmail.com', 'Bangalore'), ('00078r@gmail.com',     'Mumbai'),
         ('00078r@gmail.com',     'Vijayawada'),('00078r@gmail.com',     'Vijayawada'),
         ('00078r@gmail.com',     'Vijayawada')],
         columns=['id','city'],
         index=None
     )

topdf = df.groupby('id').apply(get_top_city)

id
000.tushar@gmail.com     Bangalore
00078r@gmail.com        Vijayawada
0007ayan@gmail.com      Jamshedpur

# or topdf.items()/iteritems() if you want as list of (id,city) tuples

[('000.tushar@gmail.com', 'Bangalore'), ('00078r@gmail.com', 'Vijayawada'), ('0007ayan@gmail.com', 'Jamshedpur')]

【讨论】:

不,它没有给出正确的结果,只需添加一条记录,如 ('000.tushar@gmail.com', 'XYZ'),你会明白为什么这不是这样做的方法.它最终会为“000.tushar@gmail.com”提供“xyz”,而“班加罗尔”应该是答案。 它只是按 id 进行分组,并从该组的所有城市返回最大值,并按字母顺序进行比较。我需要计数/出现明智的最大值。 已修复(我的解决方案实际上之前有,我只是试图最小化代码) ...或g['city'].value_counts().idxmax(),如果你想删除不需要的索引【参考方案2】:

您可以尝试将groupbysizeidxmax 结合使用。输出是元组列表(因为MultiIndex),所以使用apply

df = df.groupby(['id','city']).size().groupby(level=0).idxmax()
                              .apply(lambda x: x[1]).reset_index(name='city')

另一种解决方案:

s = df.groupby(['id','city']).size()
df = s.loc[s.groupby(level=0).idxmax()].reset_index().drop(0,axis=1)

或者:

df = df.groupby(['id'])['city'].apply(lambda x: x.value_counts().index[0]).reset_index()

print (df)
                     id        city
0  000.tushar@gmail.com   Bangalore
1      00078r@gmail.com  Vijayawada
2    0007ayan@gmail.com  Jamshedpur

【讨论】:

您可以避免手动创建然后操作MultiIndex;看我的回答。 @smci - 不确定,但apply + agg 有点过于复杂;)我添加了另外两个解决方案。 df = df.groupby(['id'])['city'].apply(lambda x: x.value_counts().index[0]).reset_index() 应该更好 - 而不是两倍 groupby。在您的解决方案中还需要.reset_index().drop(0,axis=1) 为什么熊猫工具箱中仍然存在排名功能(速度较慢)。开个玩笑(P.S-它在其他情况下也有帮助(帮了我很多)。 @Satya - pandas 很大,我认为应该优化很多代码;)但这并不容易,因为库很大。

以上是关于在另一列上分组后查找列值的最大出现次数的主要内容,如果未能解决你的问题,请参考以下文章

在按两列分组时选择最大值,并在另一列上排序

EXCEL 比较一列数据是不是在另一列出现过

SQL如何查询出某一列中不同值出现的次数?

Spark Scala聚合函数,用于查找组中列值的出现次数

在另一列上复制在某些条件下具有空值的列

熊猫在一列上分组,另一列上的最大日期python