如何在Python中按组按年份计算累积唯一值数量?
在Python中按组计算累积唯一值
需求说明
按Group列分组,新增Want列,其值为按Year顺序累积的Type列唯一值数量,不同组的年份分布无需统一处理。
示例输入DataFrame
| Group | Year | Type |
|---|---|---|
| A | 1998 | red |
| A | 1998 | blue |
| A | 2002 | red |
| A | 2005 | blue |
| A | 2008 | blue |
| A | 2008 | yello |
| B | 1998 | red |
| B | 2001 | red |
| B | 2003 | red |
| C | 1996 | red |
| C | 2002 | orange |
| C | 2002 | red |
| C | 2012 | blue |
| C | 2012 | yello |
期望输出DataFrame
| Group | Year | Type | Want |
|---|---|---|---|
| A | 1998 | red | 2 |
| A | 1998 | blue | 2 |
| A | 2002 | red | 2 |
| A | 2005 | blue | 2 |
| A | 2008 | blue | 3 |
| A | 2008 | yello | 3 |
| B | 1998 | red | 1 |
| B | 2001 | red | 1 |
| B | 2003 | red | 1 |
| C | 1996 | red | 1 |
| C | 2002 | orange | 2 |
| C | 2002 | red | 2 |
| C | 2012 | blue | 4 |
| C | 2012 | yello | 4 |
解决方案
方法1:逐行累积记录(小数据集适用)
通过分组后逐行迭代,用集合记录已出现的Type,实时更新计数:
import pandas as pd # 构造示例数据 df = pd.DataFrame({ 'Group': ['A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'C'], 'Year': [1998, 1998, 2002, 2005, 2008, 2008, 1998, 2001, 2003, 1996, 2002, 2002, 2012, 2012], 'Type': ['red', 'blue', 'red', 'blue', 'blue', 'yello', 'red', 'red', 'red', 'red', 'orange', 'red', 'blue', 'yello'] }) def cumulative_unique(group): # 按年份排序,保证累积顺序 group = group.sort_values('Year') seen_types = set() count_list = [] for _, row in group.iterrows(): seen_types.add(row['Type']) count_list.append(len(seen_types)) group['Want'] = count_list return group # 分组应用函数 result = df.groupby('Group', group_keys=False).apply(cumulative_unique) print(result)
方法2:先去重再累积(大数据集适用)
先对每个Group-Year的Type去重,减少重复计算,再累积统计唯一值数量,最后合并回原数据:
import pandas as pd # 构造示例数据 df = pd.DataFrame({ 'Group': ['A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'C'], 'Year': [1998, 1998, 2002, 2005, 2008, 2008, 1998, 2001, 2003, 1996, 2002, 2002, 2012, 2012], 'Type': ['red', 'blue', 'red', 'blue', 'blue', 'yello', 'red', 'red', 'red', 'red', 'orange', 'red', 'blue', 'yello'] }) # 1. 提取每个Group-Year下的唯一Type unique_year_type = df.groupby(['Group', 'Year'])['Type'].unique().reset_index() # 2. 按Group分组,累积计算唯一值数量 def accumulate_count(group): group = group.sort_values('Year') # 累积合并Type列表并去重 group['cumulative'] = group['Type'].cumsum().apply(lambda x: list(set(x))) group['Want'] = group['cumulative'].str.len() return group[['Group', 'Year', 'Want']] year_want_map = unique_year_type.groupby('Group', group_keys=False).apply(accumulate_count) # 3. 合并回原DataFrame result = df.merge(year_want_map, on=['Group', 'Year'], how='left') print(result)
说明
- 方法1逻辑直观,适合小数据集;
- 方法2通过先去重减少计算量,效率更高,适合大数据集;
- 两种方法均保证按
Year顺序累积,且不同组独立计算。
内容的提问来源于stack exchange,提问作者leilei
相关产品推荐
相关产品推荐

