🔷 DA37:统计运动会项目报名人数(仅输出有人报名的项目)
✅ 题目描述
给定两个 CSV 文件:
items.csv
:包含项目信息(item_id, item_name, location)signup.csv
:包含员工报名信息(employee_id, name, sex, department, item_id)
要求:统计每个项目的报名人数,只输出报名人数不为 0 的项目。
💡 即:只要有人报了的项目才显示。
✅ 正确代码
import pandas as pddf_items = pd.read_csv('items.csv', sep=',')
df_signup = pd.read_csv('signup.csv', sep=',')# 内连接合并,自动过滤没有报名记录的项目
df_merge = pd.merge(df_items, df_signup, on='item_id')# 按项目名称分组,统计 employee_id 的数量
result = df_merge.groupby('item_name')['employee_id'].size()print(result)
🔍 代码解析
行 | 解释 |
---|---|
pd.merge(..., on='item_id') | 使用 item_id 作为键进行内连接(默认),只有在两个表中都存在的项目才会保留 → 自动排除无人报名的项目 |
.groupby('item_name') | 按“项目名称”分组 |
['employee_id'].size() | 统计每组中有多少条记录(即报名人数)<br>⚠️ 注意:size() 包括 NaN 值;若用 count() 则会跳过 NaN(更安全) |
print(result) | 输出 Series:索引是项目名,值是人数 |
✅ 特点:使用 inner join(默认),天然只保留有报名数据的项目。
🧠 扩展知识
知识点 | 说明 |
---|---|
merge() 默认行为 | 不指定 how 时,默认为 'inner' ,即只保留两表共有的 key |
groupby().size() vs .count() | <ul><li>size() :返回每组总行数,包括 NaN</li><li>count() :对各列统计非空值个数</li></ul>在此场景下两者等价(employee_id 不为空) |
输出格式 | 返回的是一个 Series ,打印时自动省略列名,符合题目要求 |
🔷 DA38:统计运动会项目报名人数(二)—— 包含无人报名的项目
✅ 题目描述
同上,但这次要求:
输出 items.csv 中所有项目的报名人数,即使没人报名也显示为 0。
✅ 正确代码
import pandas as pddf_items = pd.read_csv('items.csv', sep=',')
df_signup = pd.read_csv('signup.csv', sep=',')# 左连接:以 items 为主表,保留所有项目
df_merge = pd.merge(df_items, df_signup, on='item_id', how='left')# 分组并使用 count 统计非空 employee_id 数量
result = df_merge.groupby('item_name')['employee_id'].count()print(result)
🔍 代码解析
关键点 | 解释 |
---|---|
how='left' | 左连接,确保 df_items 中的所有项目都被保留<br>→ 即使没人报名,也会出现在结果中,employee_id 为 NaN |
.count() | 只统计非 NaN 的值 → 无人报名则为 0 |
groupby('item_name') | 按项目名聚合 |
print(result) | 输出所有项目及其报名人数(含 0) |
✅ 核心思想:主表驱动 + left join + count 处理缺失值
🧠 扩展知识
技巧 | 应用场景 |
---|---|
left join | 主表完整、从表补充信息的经典模式(如商品+销量) |
fillna(0) | 如果你想显式补零:df_merge['employee_id'].fillna(0) |
reindex() | 若想确保所有项目按 items.csv 顺序出现,可用 reindex |
🔷 DA39:多报名表的运动项目人数统计
✅ 题目描述
新增一个文件 signup1.csv
,是另一个部门的报名数据。 要求:将 signup.csv
和 signup1.csv
合并后,再统计各项目的报名人数(只输出有人报名的)。
✅ 正确代码
import pandas as pditem = pd.read_csv("items.csv", sep=",")
sign = pd.read_csv("signup.csv", sep=",")
sign1 = pd.read_csv("signup1.csv", sep=",")# 上下拼接两个报名表
sign_m = pd.concat([sign, sign1], axis=0)# 与项目表内连接
m = pd.merge(sign_m, item, how="inner", on="item_id")# 按项目名分组,统计员工数量
print(m.groupby("item_name")["employee_id"].count())
🔍 代码解析
步骤 | 说明 |
---|---|
pd.concat([sign, sign1], axis=0) | 将两个报名表纵向堆叠(union),合并成一张大报名表 |
axis=0 | 沿行方向拼接(上下接) |
merge(..., how='inner') | 只保留存在于 items.csv 中的项目(防止无效 item_id) |
groupby().count() | 统计每个项目的总报名人数(来自两个文件) |
✅ 重点:先合并报名数据,再关联项目信息。
🧠 扩展知识
方法 | 用途 |
---|---|
pd.concat([...], ignore_index=True) | 重置行索引,避免重复 index |
append() 已弃用 | 推荐使用 concat 替代 |
去重处理 | 若担心重复报名:sign_m.drop_duplicates(subset=['employee_id', 'item_id']) |
🔷 DA40:统计职能部门中报名标枪的员工信息
✅ 题目描述
找出 职能部门(functional) 中报名了 标枪(javelin) 的所有员工,并输出他们的:
- employee_id
- name
- sex
⚠️ 注意:结果要重置索引(从 0 开始连续编号)
✅ 正确代码
import pandas as pd df1 = pd.read_csv("items.csv", sep=',')
df2 = pd.read_csv("signup.csv", sep=',')# 先合并项目和报名信息
df = pd.merge(df1, df2, on='item_id')# 筛选条件:部门是 functional,项目是 javelin
df_fun = df[(df.department == 'functional') & (df.item_name == "javelin")]# 选择指定列并重置索引
result = df_fun[["employee_id", "name", "sex"]].reset_index(drop=True)print(result)
🔍 代码解析
步骤 | 说明 |
---|---|
pd.merge(..., on='item_id') | 获取每个报名记录对应的项目名称 |
(df.A == X) & (df.B == Y) | 多条件筛选,注意括号和 & (不能用 and ) |
df[[...]] | 选取特定列 |
.reset_index(drop=True) | 重新生成从 0 开始的整数索引,丢弃原索引 |
✅ 输出是一个 DataFrame,结构清晰。
🧠 扩展知识
技术点 | 提示 |
---|---|
条件逻辑运算符 | <ul><li>& :且</li><li>| :或</li><li>~ :非</li></ul>必须加括号! |
字符串匹配 | 若不确定拼写可用:<br>df.item_name.str.contains('javelin', case=False) |
query() 方法 | 更简洁的筛选方式:<br>df.query("department == 'functional' and item_name == 'javelin'") |
drop=True | 避免旧索引变成新列 |
📚 总结对比表(四题核心差异)
题号 | 目标 | 关键操作 | 连接方式 | 聚合/筛选 |
---|---|---|---|---|
DA37 | 有人报名的项目人数 | merge + groupby + size | inner (default) | 只输出有数据的 |
DA38 | 所有项目(含0人) | merge + left + count | left | 显示0人项目 |
DA39 | 多报名表汇总 | concat + merge + count | inner | 合并多个源数据 |
DA40 | 特定人群信息查询 | merge + 多条件筛选 + 列选择 | inner | 输出明细数据 |
🛠️ 通用技巧总结
场景 | 推荐做法 |
---|---|
合并多个 CSV 报名表 | pd.concat([df1, df2], axis=0) |
关联项目信息 | pd.merge(..., on='item_id') |
统计数量 | groupby().size() 或 .count() |
保留主表全部数据 | how='left' |
筛选满足多个条件的数据 | (cond1) & (cond2) |
输出前清理索引 | .reset_index(drop=True) |
防止拼写错误 | 检查字段名:df.columns.tolist() |
✅ 学习建议
- 动手实践:把这几道题的数据自己构造出来跑一遍。
- 理解 merge 类型:inner/left/right/outer 的区别是关键。
- 掌握 groupby 和 count/size:数据分析最常用组合。