数据分析:合并二
✅ DA41 运动会各项目报名透视表
📌 题目描述
- 有两个 CSV 文件:
items.csv
:项目信息(item_id
,item_name
,location
)signup.csv
:员工报名信息(employee_id
,name
,sex
,department
,item_id
)
- 要求输出一个透视表,展示:
- 行索引:
sex
(性别)、department
(部门) - 列索引:
item_name
(项目名称) - 值:报名人数(统计
employee_id
的数量)
- 行索引:
- 不包含没人报名的项目
✅ 代码实现
import pandas as pd# 读取数据
items = pd.read_csv('items.csv')
signup = pd.read_csv('signup.csv')# 合并两个表,获取项目名称
merged = pd.merge(signup, items, on='item_id', how='inner')# 创建透视表
pivot = pd.pivot_table(merged,index=['sex', 'department'], # 多级行索引columns=['item_name'], # 列为项目名values='employee_id', # 统计员工IDaggfunc='count', # 聚合方式:计数fill_value=0 # 缺失值填0
)print(pivot)
🔍 解析
为什么用
merge
?- 因为
signup
表只有item_id
,没有项目名称,必须通过items.csv
获取item_name
- 使用
inner join
自动过滤掉“没人报名”的项目(因为signup
中没有对应记录)
- 因为
pivot_table
参数详解:index
: 行分组字段(支持多级)columns
: 列分组字段(会变成列名)values
: 要聚合的列(这里是employee_id
)aggfunc='count'
: 统计每组中非空的employee_id
数量 → 即报名人数fill_value=0
: 将 NaN 替换为 0,表格更美观
输出示例(示意):
item_name longJump run100m swim50m sex department 男 tech 2 1 0 女 education 1 0 3
⚠️ 常见错误
- 忘记合并表 → 缺少
item_name
- 用
outer join
→ 可能引入无意义项目 - 不指定
values
→ 默认会对所有数值列聚合,导致错误
✅ DA42 合并用户信息表与用户活跃表(简单)
📌 题目描述
- 有两个用户表:
Nowcoder1.csv
:用户基本信息(ID, 名字, 等级, 刷题量等)Nowcoder2.csv
:用户活跃数据(ID, 签到天数, 提交次数, 最后提交时间)
- 要求通过
Nowcoder_ID
合并两张表,输出完整信息
✅ 代码实现
import pandas as pd# 设置显示选项
pd.set_option('display.max_columns', None)
pd.set_option('display.width', 300)# 读取数据
df1 = pd.read_csv('Nowcoder1.csv')
df2 = pd.read_csv('Nowcoder2.csv')# 内连接合并
merged = pd.merge(df1, df2, on='Nowcoder_ID', how='inner')print(merged)
🔍 解析
为什么要用
inner join
?- 题目要求“合并输出”,隐含意思是只保留两张表都有的用户
- 如果某个用户只在一张表中有数据,可能是异常或未活跃用户,不输出也合理
how='inner'
vshow='left'
?inner
: 只保留两表共有的用户left
: 保留所有df1
的用户,df2
没有的字段填 NaN- 本题推荐
inner
,因为“完整表格”意味着两部分信息都要有
显示设置说明:
max_columns=None
: 防止列太多被省略width=300
: 让输出更宽,避免换行
✅ DA43 两份用户信息表格中的查找(简单)
📌 题目描述
- 同样是两个用户表(
Nowcoder1.csv
,Nowcoder2.csv
) - 要求输出:用户名、刷题量、代码提交次数
✅ 代码实现
import pandas as pd# 设置显示
pd.set_option('display.max_rows', None)
pd.set_option('display.max_columns', None)
pd.set_option('display.width', 300)# 读取
df1 = pd.read_csv('Nowcoder1.csv')
df2 = pd.read_csv('Nowcoder2.csv')# 左连接合并
merged = pd.merge(df1, df2, on='Nowcoder_ID', how='left')# 提取需要的三列
result = merged[['Name', 'Num_of_exercise', 'Number_of_submissions']]print(result)
🔍 解析
为什么用
left join
?- 目标是输出“用户的名字和刷题量”——这些都在
df1
中 - “代码提交次数”在
df2
中,但不要求每个用户都有 - 所以保留
df1
所有用户,df2
没有的提交次数显示为NaN
或0
- 目标是输出“用户的名字和刷题量”——这些都在
与 DA42 的区别:
题目 目的 推荐 how
DA42 输出完整用户信息 inner
DA43 输出特定字段,允许缺失 left
列选择技巧:
result = merged[['Name', 'Num_of_exercise', 'Number_of_submissions']]
- 使用双层中括号
[[...]]
选择多列 - 返回的是 DataFrame,不是 Series
- 使用双层中括号
🧠 扩展知识点总结
1. pd.merge()
的 how
参数对比
类型 | 说明 | 使用场景 |
---|---|---|
inner | 交集:只保留两表都有的键 | 数据完整性要求高 |
left | 左表全保留,右表匹配 | 分析主表 + 补充信息 |
right | 右表全保留 | 较少用 |
outer | 并集:保留所有键 | 全量分析,容忍缺失 |
2. pivot_table
核心参数
参数 | 作用 |
---|---|
index | 行分组字段(可多级) |
columns | 列分组字段(变成列名) |
values | 要聚合的列 |
aggfunc | 聚合函数('count' , 'sum' , 'mean' 等) |
fill_value | 填充缺失值(如 0 ) |
3. 读取 CSV 的 sep
问题(回顾)
pd.read_csv('data.csv') # 默认 sep=','(英文逗号)
pd.read_csv('data.tsv', sep='\t') # 制表符分隔必须指定
- ❌ 错误:
sep=','
(中文逗号) - ✅ 正确:
sep=','
或不写(默认)
✅ 学习建议
- 理解业务逻辑再选
how
:- 要不要保留没活跃的用户?→ 决定用
left
还是inner
- 要不要保留没活跃的用户?→ 决定用
- 多用
pivot_table
做报表:- 比
groupby + unstack
更直观
- 比
- 打印前设置显示选项:
pd.set_option('display.max_rows', None) pd.set_option('display.max_columns', None)
- 先合并再筛选列:
merge
→select columns
是标准流程
🎯 总结口诀
“合并看需求,inner 保完整,left 保主表;
透视用 pivot,index 行,columns 列,count 统人数。”