Pandas:按ID聚合获取animal列最常见字符串(同计数取最后值)
解决方案:按ID聚合并获取出现频率最高/最后出现的Animal值
我来帮你搞定这个需求,下面提供两种基于Pandas的实现方案,都能完美匹配你的期望输出:
方法一:自定义分组函数(直观易懂)
这种方法逻辑清晰,适合刚接触Pandas分组操作的场景,每一步都能明确看到处理过程:
首先先构造你的示例数据集:
import pandas as pd # 构造示例数据 data = { 'id': [1,1,1,2,3,4,5,5], 'animal': ['dog','dog','cat','cat','dog','fish','dog','cat'], 'date': ['2018-01-01','2018-01-02','2018-01-03','2018-01-01','2018-01-01','2018-01-01','2018-01-01','2018-01-02'] } df = pd.DataFrame(data) # 建议把date转为datetime类型,确保排序准确 df['date'] = pd.to_datetime(df['date'])
然后定义处理每个分组的自定义函数,再应用到分组上:
def get_target_animal(group): # 先按日期排序,保证最新的记录在分组末尾 sorted_group = group.sort_values('date') # 统计当前ID下每个动物的出现频率 animal_counts = sorted_group['animal'].value_counts() # 获取最高出现频率 max_freq = animal_counts.max() # 筛选出所有达到最高频率的动物候选 candidates = animal_counts[animal_counts == max_freq].index.tolist() # 从分组末尾往前找第一个候选动物(也就是最后出现的那个) for animal in reversed(sorted_group['animal']): if animal in candidates: return animal # 按ID分组应用函数,整理成结果格式 result = df.groupby('id')['animal'].apply(get_target_animal).reset_index() result.columns = ['id', 'animal'] print(result)
运行后就能得到你想要的输出:
id animal 0 1 dog 1 2 cat 2 3 dog 3 4 fish 4 5 cat
方法二:基于排名的高效实现(适合大数据集)
如果你的数据集很大,上面的遍历方法效率会偏低,这种利用rank和排序的方法更高效:
import pandas as pd # 构造并预处理数据 data = { 'id': [1,1,1,2,3,4,5,5], 'animal': ['dog','dog','cat','cat','dog','fish','dog','cat'], 'date': ['2018-01-01','2018-01-02','2018-01-03','2018-01-01','2018-01-01','2018-01-01','2018-01-01','2018-01-02'] } df = pd.DataFrame(data) df['date'] = pd.to_datetime(df['date']) # 1. 给每条记录添加当前ID下对应动物的出现次数 df['animal_freq'] = df.groupby(['id', 'animal'])['animal'].transform('count') # 2. 给每个(ID,动物)组内的记录按日期逆序排名(最后出现的排第1) df['last_appear_rank'] = df.groupby(['id', 'animal'])['date'].rank(ascending=False, method='first') # 3. 按ID升序、频率降序、逆序排名升序排序,每个ID取第一条 result = df.sort_values( by=['id', 'animal_freq', 'last_appear_rank'], ascending=[True, False, True] ).groupby('id').first().reset_index()[['id', 'animal']] print(result)
这个方法的核心逻辑是:
- 先计算每个(ID,动物)组合的出现次数
- 再给每个组合内的记录按日期逆序排名,确保最后出现的记录排名最高
- 最后通过排序优先级(频率优先,频率相同则最后出现的优先),每个ID取第一条即可得到目标结果
内容的提问来源于stack exchange,提问作者Auren Ferguson
相关产品推荐
相关产品推荐

