在Pandas中提取特定列值唯一的行并添加计数列
问题
我的DataFrame如下:
id name class -------------------------- 0 Nick a 1 Jane b 2 Jacon a 3 Jack b 4 Cooze a -------------------------- 5 Nick b 6 Jane b 7 Jacon c 8 Jack a 9 Cooze a -------------------------- 10 John a
我需要提取所有在class列中值唯一的name,同时添加新列显示每个name-class组合的重复次数,最终结果如下:
id name class count ----------------------------------- 0 Jane b 2 1 Cooze a 2 2 John a 1
补充说明:John被纳入是因为它在name列中仅出现一次,因此其class列值唯一。
我已经尝试了以下代码:
data = { 'name': ['Nick', 'Jane', 'Jacon', 'Jack', 'Cooze', 'Nick', 'Jane', 'Jacon', 'Jack', 'Cooze', 'John'], 'class': ['a', 'b', 'a', 'b', 'a', 'b', 'b', 'c', 'a', 'a', 'a']} df = pd.DataFrame(data) new_data = df.groupby('name')['class'].unique() print(new_data)
得到的输出:
name Cooze [a] Jack [b, a] Jacon [a, c] Jane [b] John [a] Nick [a, b] Name: class, dtype: object
接下来我想获取每个class唯一值列表的长度,筛选出长度为1的项,但操作时出现多种错误,而且感觉可以有更简便的方法。作为Pandas新手,请问该如何实现需求?
解决方案
这里提供两种简洁高效的实现方法,核心是利用nunique()直接统计每个name对应的class唯一值数量,避免手动处理数组的麻烦:
方法一:先筛选有效name,再统计次数
- 先通过分组计算每个name的class唯一值数量,筛选出数量为1的name;
- 从原DataFrame中提取这些name的记录,再按
name和class分组统计重复次数,最后整理成目标格式。
代码示例:
import pandas as pd data = { 'name': ['Nick', 'Jane', 'Jacon', 'Jack', 'Cooze', 'Nick', 'Jane', 'Jacon', 'Jack', 'Cooze', 'John'], 'class': ['a', 'b', 'a', 'b', 'a', 'b', 'b', 'c', 'a', 'a', 'a']} df = pd.DataFrame(data) # 筛选出class值唯一的name valid_names = df.groupby('name')['class'].nunique()[lambda x: x == 1].index # 筛选记录、统计次数并整理格式 result = df[df['name'].isin(valid_names)] \ .groupby(['name', 'class'], as_index=False) \ .size() \ .rename(columns={'size': 'count'}) \ .reset_index(drop=True) \ .rename_axis('id').reset_index() print(result)
输出结果:
id name class count 0 0 Cooze a 2 1 1 Jane b 2 2 2 John a 1
方法二:用transform标记后直接筛选统计
通过transform在原DataFrame的每行添加对应name的class唯一值数量,直接筛选符合条件的行后统计次数:
代码示例:
import pandas as pd data = { 'name': ['Nick', 'Jane', 'Jacon', 'Jack', 'Cooze', 'Nick', 'Jane', 'Jacon', 'Jack', 'Cooze', 'John'], 'class': ['a', 'b', 'a', 'b', 'a', 'b', 'b', 'c', 'a', 'a', 'a']} df = pd.DataFrame(data) # 给每行标记对应name的class唯一值数量 df['class_unique_count'] = df.groupby('name')['class'].transform('nunique') # 筛选、统计并整理格式 result = df[df['class_unique_count'] == 1] \ .groupby(['name', 'class'], as_index=False) \ .size() \ .rename(columns={'size': 'count'}) \ .reset_index(drop=True) \ .rename_axis('id').reset_index() print(result)
输出与方法一完全一致。
关键提示
nunique()是这里的核心,它直接返回分组后某列的唯一值数量,比你之前用的unique()更适合这个场景,省去了手动计算列表长度的步骤,避免操作数组时的错误;- 最后通过
rename_axis('id').reset_index()生成目标中的id列,完美匹配需求格式。
内容的提问来源于stack exchange,提问作者user6781
相关产品推荐
相关产品推荐

