RSS
菜单
全部文章快讯开发科技深度热点

第 49 章 Excel 常用功能与 pandas 对照

内容摘要

本篇把 Excel 里你天天在用的操作——VLOOKUP、透视表、筛选、排序、去重、条件格式、分列、查找替换——逐一翻译成 pandas 写法。每节先给一张"Excel 操作 | pandas 代码 | 说明"三栏对照表,再给一段可运行示例,并指出 Excel 里有、pandas 里没有(或反过来)的能力边界。前置知识:[第 04 章 数据读取与写入](04-数据读取与写入.md)、[第 11 章 数据合并:concat-merge-join](11-数据合并:concat-merge-join.md)、[第 12 章 数据重塑与透视表](12-数据重塑与透视表.md)。学完后你看到任何一张 Excel 表,都能立刻想到对应的 pandas 一行代码。

📖 本篇简介:本篇把 Excel 里你天天在用的操作——VLOOKUP、透视表、筛选、排序、去重、条件格式、分列、查找替换——逐一翻译成 pandas 写法。每节先给一张"Excel 操作 | pandas 代码 | 说明"三栏对照表,再给一段可运行示例,并指出 Excel 里有、pandas 里没有(或反过来)的能力边界。前置知识:第 04 章 数据读取与写入、第 11 章 数据合并:concat-merge-join、第 12 章 数据重塑与透视表。学完后你看到任何一张 Excel 表,都能立刻想到对应的 pandas 一行代码。
Excel 是"所见即所得"的电子表格,pandas 是"代码即数据"的列式分析框架。对照学习的价值,不是把 pandas 当成 Excel 的替代品,而是知道哪些操作该交给 Excel、哪些该交给 pandas。

目录

1. 开篇:Excel 功能 ↔ pandas 总对照表

2. VLOOKUP ↔ merge(精确 / 近似匹配)

3. 透视表 ↔ pivot_table

4. 筛选 ↔ 布尔索引 / query

5. 排序 ↔ sort_values

6. 去重 ↔ drop_duplicates

7. 条件格式 ↔ Styler(background_gradient / apply)

8. 数据验证 ↔ 清洗约束(范围 / 枚举检查)

9. 分列 ↔ str.split(expand=True)

10. 数字格式 ↔ dtype / round

11. 冻结窗格与打印设置(pandas 无直接对应)

12. 合并单元格 ↔ MultiIndex

13. 查找替换 ↔ replace

14. Excel 文件读写基础

15. 常见坑

16. 本章小结与练习题


1. 开篇:Excel 功能 ↔ pandas 总对照表

刚从 Excel 转 pandas 的同学,最大的痛苦不是"语法记不住",而是"我不知道 pandas 里有没有这个东西"。这张总表先把地图给你,后面再逐项展开:

| Excel 功能 | pandas 写法 | 说明 |

|------------|-------------|------|

| VLOOKUP / XLOOKUP | df.merge(other, on=..., how=...) | 列关联,最常用 left/inner |

| 数据透视表 | pd.pivot_table(df, index=, columns=, values=, aggfunc=) | 行列任意组合聚合 |

| 自动筛选(下拉箭头) | 布尔索引 df[(df.x>0) & (df.y=='a')] 或 df.query(...) | 比 Excel 更灵活,可保存成脚本 |

| 排序 | df.sort_values(by=, ascending=) | 多列排序传列表 |

| 删除重复项 | df.drop_duplicates(subset=, keep=) | 按列去重 |

| 条件格式(色阶 / 高亮) | df.style.background_gradient(...) | 仅渲染,不改数据 |

| 数据验证(下拉框 / 范围限制) | 事后清洗:df[~df.x.isin(allowed)] | pandas 不"拦截"输入,只"检查"结果 |

| 分列 | df["col"].str.split(",", expand=True) | 一行展开成多列 |

| 设置单元格数字格式 | df["col"].round(2) / .map(lambda x: f"¥{x:,.2f}") | pandas 只存数值,展示在 Styler |

| 冻结首行 / 打印区域 | 无直接对应 | 这些是 Excel 的"展示层"概念 |

| 合并单元格 | pd.MultiIndex.from_tuples(...) | pandas 用层级索引表达"分组头" |

| 查找替换 | df.replace({"旧":"新"}) | 整列甚至整表批量替换 |

| 读取 .xlsx | pd.read_excel(path, sheet_name=, engine="openpyxl") | 需装 openpyxl |

| 导出 .xlsx | df.to_excel(path, index=False) | 同样依赖 openpyxl |

💡 一句话心智模型:Excel 把"数据 + 展示 + 交互"揉在一张表里;pandas 只负责"数据 + 计算",展示层(颜色、冻结、打印、公式栏)基本交给 Styler 或 Excel 自己。

2. VLOOKUP ↔ merge(精确 / 近似匹配)

Excel 里最高频的函数之一是 =VLOOKUP(查找值, 查找区域, 返回列号, FALSE)。pandas 对应的不是某个函数,而是 pd.merge——它把"按 key 关联两张表"这件事做成了一等公民。

| Excel 操作 | pandas 代码 | 说明 |

|------------|-------------|------|

| =VLOOKUP(B2, 客户表!A:C, 2, FALSE) | orders.merge(cust, on="cust_id", how="left") | 精确匹配,左连接保留订单全部行 |

| =VLOOKUP(B2, 区间!A:B, 2, TRUE) 近似匹配 | pd.merge_asof(left, right, on="时间列") 或 pd.cut(...) | 要求右表 key 已排序 |

| INDEX + MATCH 双向查找 | df.set_index("code").loc["A002", "price"] | 见第 50 章 |

import pandas as pd

# 模拟两张表:订单表 + 客户表
orders = pd.DataFrame({
    "order_id": [101, 102, 103, 104],
    "cust_id": [1, 2, 1, 3],
    "amount": [120, 200, 80, 350],
})
cust = pd.DataFrame({
    "cust_id": [1, 2, 3],
    "cust_name": ["张三", "李四", "王五"],
    "city": ["北京", "上海", "广州"],
})

# Excel: =VLOOKUP(B2, 客户表!A:C, 2, FALSE)
# pandas: on 是连接键,how="left" 等价于"左表全保留"
merged = orders.merge(cust, on="cust_id", how="left")
print(merged)
   order_id  cust_id  amount cust_name city
0       101        1     120        张三   北京
1       102        2     200        李四   上海
2       103        1      80        张三   北京
3       104        3     350        王五   广州

精确 vs 近似的区别:

  • 精确匹配(VLOOKUP 第四参数 FALSE / 0):键必须完全相等,对应 merge(on=...)。
  • 近似匹配(VLOOKUP 第四参数 TRUE / 1):右表要先排序,找"小于等于查找值的最大键",对应 pd.merge_asof(...)(时间序列场景)或 pd.cut(...)(分段场景)。
⚠️ 常见坑:Excel 的 VLOOKUP 只能从左向右查;pandas 的 merge 没有这个限制,但连接键在两张表里的名字必须一致,不一致用 left_on= / right_on=。

3. 透视表 ↔ pivot_table

Excel 插入"数据透视表"对话框里拖拖拽拽的那套,pandas 里是一行 pd.pivot_table。

| Excel 操作 | pandas 代码 | 说明 |

|------------|-------------|------|

| 行:部门;列:季度;值:销售额;汇总方式:求和 | pd.pivot_table(df, index="部门", columns="季度", values="销售额", aggfunc="sum") | 行列任意拖 |

| 汇总方式改成"计数" | aggfunc="count" | 也可以是 np.mean / "max" |

| 勾选"总计" | margins=True, margins_name="合计" | 行末加合计行 |

| 空单元格填 0 | fill_value=0 | 避免 NaN |

df = pd.DataFrame({
    "部门": ["销售", "销售", "技术", "技术", "销售", "技术"],
    "季度": ["Q1", "Q2", "Q1", "Q2", "Q2", "Q1"],
    "销售额": [100, 150, 200, 180, 90, 220],
})

# 等价于 Excel 透视表:行=部门,列=季度,值=销售额,求和 + 总计
pivot = df.pivot_table(index="部门", columns="季度", values="销售额",
                       aggfunc="sum", fill_value=0,
                       margins=True, margins_name="合计")
print(pivot)
季度   Q1   Q2   合计
部门
技术  420  180  600
销售  100  240  340
合计  520  420  940
💡 Excel 透视表拖完后"结果是一张新表",pivot_table 返回的也是一张新 DataFrame,可以继续 to_excel 写回 Excel。

4. 筛选 ↔ 布尔索引 / query

Excel 表头那排小箭头叫"自动筛选"。pandas 没有 UI,但布尔索引是它的超集——你可以把任意复杂条件写在一行里。

| Excel 操作 | pandas 代码 | 说明 |

|------------|-------------|------|

| 筛选 dept = 销售 | df[df["dept"] == "销售"] | 布尔掩码 |

| 筛选 amount ≥ 1000 | df[df["amount"] >= 1000] | 比较运算 |

| 多条件(且) | df[(df.a==1) & (df.b>2)] | 每个条件加括号 |

| 多条件(或) | df[(df.a==1) \| (df.b>2)] | 竖线 \| |

| 包含某关键词 | df[df["name"].str.contains("张")] | str 访问器 |

| 类 SQL 写法 | df.query("dept == '销售' and amount >= 1000") | 字符串更简洁 |

sales = pd.DataFrame({
    "name": ["张三", "李四", "王五", "赵六"],
    "dept": ["销售", "技术", "销售", "技术"],
    "amount": [1200, 800, 1500, 600],
})

# 方式一:布尔索引(最常用)
m1 = sales[(sales["dept"] == "销售") & (sales["amount"] >= 1000)]
print("布尔索引:\n", m1)

# 方式二:query(表达式更接近 Excel 的筛选条件对话框)
m2 = sales.query("dept == '销售' and amount >= 1000")
print("query:\n", m2)
布尔索引:
   name dept  amount
0   张三   销售    1200
2   王五   销售    1500
query:
   name dept  amount
0   张三   销售    1200
2   王五   销售    1500
⚠️ 常见坑:每个布尔条件都要用圆括号括起来,否则 & 的优先级会让表达式先于 == 计算,得到 ValueError。

5. 排序 ↔ sort_values

Excel 工具栏上的 A→Z / Z→A 按钮,对应 sort_values。

| Excel 操作 | pandas 代码 | 说明 |

|------------|-------------|------|

| 按单列升序 | df.sort_values("col") | 默认 ascending=True |

| 按单列降序 | df.sort_values("col", ascending=False) | |

| 多列排序(先按部门,部门内按金额降序) | df.sort_values(by=["dept","amount"], ascending=[True,False]) | 传列表 |

| 按索引排序 | df.sort_index() | |

print(sales.sort_values(by=["dept", "amount"], ascending=[True, False]))
  name dept  amount
1   李四   技术     800
3   赵六   技术     600
2   王五   销售    1500
0   张三   销售    1200
💡 pandas 3.0 起 sort_values 等方法的 inplace=True 参数已被弃用/移除,直接接收返回值即可:df = df.sort_values(...)。

6. 去重 ↔ drop_duplicates

Excel 的"数据 → 删除重复项"按钮,对应 drop_duplicates。

| Excel 操作 | pandas 代码 | 说明 |

|------------|-------------|------|

| 按整行去重 | df.drop_duplicates() | 默认保留第一条 |

| 按某列去重(同 id 只留一行) | df.drop_duplicates(subset=["id"]) | subset 指定列 |

| 保留最后一条 | df.drop_duplicates(subset=["id"], keep="last") | keep="last" |

| 完全删除重复(不保留) | df.drop_duplicates(keep=False) | |

| 只看哪些行重复了 | df.duplicated(keep=False) | 返回布尔 Series |

dup = pd.DataFrame({
    "id": [1, 1, 2, 3, 3, 3],
    "name": ["A", "A", "B", "C", "C", "C"],
})
print("原始:\n", dup)
print("按 id 去重保留第一条:\n", dup.drop_duplicates(subset=["id"], keep="first"))
原始:
    id name
0   1    A
1   1    A
2   2    B
3   3    C
4   3    C
5   3    C
按 id 去重保留第一条:
    id name
0   1    A
2   2    B
3   3    C

7. 条件格式 ↔ Styler(background_gradient / apply)

Excel 的"开始 → 条件格式 → 色阶"可以把数值按大小染成红黄绿色。pandas 里对应的是 df.style,但它只负责渲染 HTML,不改 DataFrame 本身。

| Excel 操作 | pandas 代码 | 说明 |

|------------|-------------|------|

| 色阶(红-黄-绿) | df.style.background_gradient(cmap="RdYlGn") | 数值列自动按大小上色 |

| 大于某值标红 | df.style.applymap(lambda v: "color:red" if v>90 else "") | 逐格返回 CSS |

| 导出带格式的 Excel | df.style.to_excel("out.xlsx") | 需要 openpyxl |

score = pd.DataFrame({
    "姓名": ["张三", "李四", "王五"],
    "数学": [90, 55, 72],
    "英语": [60, 88, 40],
})

# 仅对"数学""英语"两列做红黄绿色阶
sty = score.style.background_gradient(cmap="RdYlGn", subset=["数学", "英语"])
print("Styler 对象类型:", type(sty).__name__)

# Styler 本身不打印数据,要导出 HTML 或 Excel 才能看到颜色
html = sty.to_html()
print("HTML 长度:", len(html), "包含 background:", "background" in html.lower())
Styler 对象类型: Styler
HTML 长度: 1583 包含 background: True
⚠️ 常见坑:
1. df.style 是 Styler 对象,不是 DataFrame,不能继续做 merge/groupby。
2. pandas 3.0 起 applymap 已被重命名为 map(DataFrame.style 里仍叫 applymap,但 DataFrame 本身的 applymap 已移除)。
3. Styler 依赖 jinja2,没装会报 The '.style' accessor requires jinja2。

8. 数据验证 ↔ 清洗约束(范围 / 枚举检查)

Excel 的"数据 → 数据验证"是输入时拦截(不合法的值根本输不进去)。pandas 没有"输入拦截"这个概念,但它有更强大的事后检查——把不合法的行筛出来。

| Excel 操作 | pandas 代码 | 说明 |

|------------|-------------|------|

| 限制 0 ≤ age ≤ 120 | df[(df.age<0) \| (df.age>120)] | 找出越界行 |

| 下拉框只能选"男/女" | df[~df.gender.isin({"男","女"})] | 枚举外的行 |

| 必填项不能为空 | df[df.col.isna()] | 找出缺失行 |

| 保存合法数据 | df_clean = df[df.age.between(0,120)] | 反向筛选 |

raw = pd.DataFrame({
    "age": [20, 35, 150, -5, 40],
    "gender": ["男", "女", "未知", "男", "其他"],
})

# 范围检查
bad_age = raw[(raw["age"] < 0) | (raw["age"] > 120)]
print("非法年龄行:\n", bad_age)

# 枚举检查
allowed = {"男", "女"}
bad_gender = raw[~raw["gender"].isin(allowed)]
print("非法性别行:\n", bad_gender)
非法年龄行:
    age gender
2  150     未知
3   -5      男
非法性别行:
    age gender
2  150     未知
4   40     其他
💡 工作流建议:Excel 适合"少量人工录入",pandas 适合"批量已有数据的清洗"。两者配合:Excel 录数据时开数据验证,导到 pandas 后再用上面的代码做二次兜底检查。

9. 分列 ↔ str.split(expand=True)

Excel"数据 → 分列"按分隔符把一列拆成多列。pandas 里是 str.split,关键参数 expand=True 让它返回 DataFrame 而不是列表。

| Excel 操作 | pandas 代码 | 说明 |

|------------|-------------|------|

| 按"-"分列 | df["col"].str.split("-", expand=True) | expand=True 才会变成多列 |

| 限制拆成 2 段 | str.split("-", n=1, expand=True) | n=1 只切一刀 |

| 按固定宽度切 | str.slice(0,3) / str[0:3] | 见第 50 章 LEFT/RIGHT/MID |

addr = pd.DataFrame({"full": ["北京-朝阳区-望京", "上海-浦东新区-陆家嘴", "广东-深圳-南山"]})
parts = addr["full"].str.split("-", expand=True)
parts.columns = ["省", "市", "区"]
print(parts)
    省     市    区
0  北京   朝阳区   望京
1  上海  浦东新区  陆家嘴
2  广东    深圳   南山
⚠️ 常见坑:忘了 expand=True,返回的是 Series of list,不能直接赋给多列;赋值时要先给列命名,再 pd.concat 回原表。

10. 数字格式 ↔ dtype / round

Excel 单元格格式里设"保留 2 位小数""加千分位""加货币符号"——这些只是显示效果,底层数值不变。pandas 更纯粹:它只存数值,展示格式交给 Styler 或字符串格式化。

| Excel 操作 | pandas 代码 | 说明 |

|------------|-------------|------|

| 保留 2 位小数 | df["col"].round(2) | 返回新 Series |

| 百分比显示 | (df["rate"]*100).round(2).astype(str) + "%" | 自己拼 |

| 货币格式 ¥1,234.50 | df["price"].map(lambda x: f"¥{x:,.2f}") | f-string 格式化 |

| 单元格显示 0.00 | Styler: df.style.format("{:.2f}") | 不改底层值 |

money = pd.DataFrame({"price": [19.999, 3.14159, 100.0]})
money["price_2f"] = money["price"].round(2)
print(money)
       price  price_2f
0   19.99900     20.00
1    3.14159      3.14
2  100.00000    100.00
⚠️ 常见坑:round(2) 是"四舍五入到 2 位",但底层还是 float,参与后续计算时会重新出现多位小数。要做"货币精确计算"应改用 Decimal 或 pandas 的 Float64(仍非精确),金融场景建议用整数"分"存储。

11. 冻结窗格与打印设置(pandas 无直接对应)

这一节专门说清楚:pandas 不做"展示层"的事。

| Excel 操作 | pandas 是否有对应 | 说明 |

|------------|-------------------|------|

| 视图 → 冻结首行 | ❌ 无 | 这是 Excel 打开文件后的浏览体验 |

| 页面布局 → 打印区域 | ❌ 无 | pandas 不生成"打印版式" |

| 插入图表(图表向导) | ✅ df.plot() / matplotlib | 见第 15 章 |

| 插入迷你图(Sparkline) | ⚠️ 需自己用 matplotlib 画 | pandas 无内置 |

| 设置列宽 / 行高 | ❌ 无 | 导出 Excel 后再用 openpyxl 调 |

| 自动换行 / 合并标题 | ❌ 无 | 同上 |

为什么 pandas 不做这些? 因为它的定位是"数据处理引擎",不是"展示软件"。正确协作方式:用 pandas 清洗计算 → df.to_excel("result.xlsx", index=False) 导出 → 在 Excel 里调冻结窗格、列宽、打印区域。需要自动化时可用 openpyxl 直接操作 xlsx(详见 第 22 章 数据读写进阶)。


12. 合并单元格 ↔ MultiIndex

Excel 里"合并居中"是为了做表头分组,比如:

|      销售      |      技术      |
| Q1  | Q2  | Q1  | Q2  |
| 100 | 150 | 200 | 180 |

pandas 不用合并单元格,而是用 MultiIndex(多层索引) 表达这种"分组头"。

| Excel 操作 | pandas 代码 | 说明 |

|------------|-------------|------|

| 合并单元格做表头 | pd.MultiIndex.from_tuples([("销售","Q1"),...], names=["部门","季度"]) | 行/列都能多层 |

| 透视表产生多层列 | pivot_table(...) 默认就是 MultiIndex | 见第 3 节 |

midx = pd.MultiIndex.from_tuples([
    ("销售", "Q1"), ("销售", "Q2"),
    ("技术", "Q1"), ("技术", "Q2"),
], names=["部门", "季度"])
df2 = pd.DataFrame({"销售额": [100, 150, 200, 180]}, index=midx)
print(df2)
       销售额
部门 季度
销售 Q1  100
   Q2  150
技术 Q1  200
   Q2  180
💡 pandas 的 MultiIndex 在"选择分组"上比 Excel 合并单元格强得多:df2.loc["销售"] 就能取出整个销售部门,合并单元格在 Excel 里反而是筛选排序的天敌。

13. 查找替换 ↔ replace

Excel 的 Ctrl+H 替换对话框,对应 df.replace。

| Excel 操作 | pandas 代码 | 说明 |

|------------|-------------|------|

| 把 "N/A" 替换成空 | df.replace("N/A", np.nan) | 全表扫描 |

| 多值映射 | df.replace({"旧1":"新1", "旧2":"新2"}) | 字典映射 |

| 正则替换 | df.replace({"col": r"^\s+$"}, np.nan, regex=True) | regex=True |

| 只替换某一列 | df["col"] = df["col"].replace(...) | 局部替换 |

s = pd.Series(["N/A", "正常", "缺失", "正常", "N/A"])
print(s.replace({"N/A": np.nan, "缺失": np.nan}))
0    NaN
1     正常
2    NaN
3     正常
4    NaN
dtype: str
💡 注意最后一行 dtype: str——pandas 3.0 默认字符串列就是 str 类型(旧版是 object),缺失值自动变成 pd.NA 或 np.nan,与字符串列共存。

14. Excel 文件读写基础

最基础的读写两行代码:

| Excel 操作 | pandas 代码 | 说明 |

|------------|-------------|------|

| 打开 .xlsx | pd.read_excel(path, sheet_name="Sheet1", engine="openpyxl") | 必须装 openpyxl |

| 另存为 .xlsx | df.to_excel(path, index=False, engine="openpyxl") | index=False 不导出行号 |

| 读所有 sheet | pd.read_excel(path, sheet_name=None) | 返回 {sheet名: DataFrame} |

| 写多个 sheet | with pd.ExcelWriter(path) as w: df1.to_excel(w, "A"); df2.to_excel(w, "B") | 上下文管理器 |

import os
out_xlsx = r"C:\Users\Administrator\AppData\Local\Temp\pandas_ch49_50\demo.xlsx"

df3 = pd.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"]})
df3.to_excel(out_xlsx, sheet_name="Sheet1", index=False, engine="openpyxl")

back = pd.read_excel(out_xlsx, sheet_name="Sheet1", engine="openpyxl")
print(back)
print("文件存在:", os.path.exists(out_xlsx))
   a  b
0  1  x
1  2  y
2  3  z
文件存在: True
💡 进阶玩法(指定列类型、跳过表头、读取合并单元格、写公式、用 xlsxwriter 加格式)见 第 22 章 数据读写进阶,这里不展开。

15. 常见坑

⚠️ 坑 1:Excel 日期序列号
Excel 用"1900 年 1 月 1 日 = 1"的整数存日期(而且还多算了 1900-02-29 这个不存在的日期)。如果你读到一列"看起来像日期"的整数(比如 44927),用:
pd.to_datetime(pd.Series([44927]), origin="1899-12-30", unit="D")
注意 origin 要写 1899-12-30 而不是 1900-01-01,这是为了兼容 Excel 的闰年 bug。

>

⚠️ 坑 2:公式单元格读出来是缓存值
pd.read_excel 默认读到的是 Excel 上次保存时的计算结果(缓存值),不是公式本身。如果 Excel 没打开重算过,缓存值可能是旧的。要读公式本身得用 openpyxl 直接操作 cell.value 加 data_only=False。

>

⚠️ 坑 3:多 sheet 读取
sheet_name=0 读第一个 sheet;sheet_name="销售表" 按名字读;sheet_name=None 一次读全部 sheet,返回 dict[str, DataFrame]。忘了写 sheet_name 默认只读第一个。

>

⚠️ 坑 4:中文路径
pd.read_excel("D:\\资料\\数据.xlsx") 在 Windows 上一般没问题,但如果遇到 FileNotFoundError,先用 os.path.exists(path) 验证路径是否正确,再检查反斜杠是否被转义(建议用原始字符串 r"...")。

>

⚠️ 坑 5:dtype 读取
Excel 里"数字 + 空单元格"混着的列,pandas 可能读成 float64(因为 NaN 是浮点),导致整数列多出 .0。用 pd.read_excel(..., dtype={"id": "Int64"}) 指定可空整数类型。

16. 本章小结与练习题

小结

1. Excel 高频操作在 pandas 里都有一一对应:VLOOKUP↔merge、透视表↔pivot_table、筛选↔布尔索引/query、排序↔sort_values、去重↔drop_duplicates。

2. 展示层(条件格式、冻结窗格、打印、合并单元格)pandas 只做一半:Styler 管颜色,其余交给 Excel。

3. pd.read_excel / to_excel 是基础读写,进阶(多 sheet、公式、合并单元格、样式)在第 22 章。

4. 日期序列号、公式缓存值、中文路径、dtype 推断是读 Excel 时的四大经典坑。

练习题

1. 给定 orders 和 cust 两张表(见第 2 节),用 merge 写出"只保留有客户信息的订单"(inner join)和"保留所有客户,即使没订单"(right join)两种写法,并说明结果行数差异。

2. 用 pivot_table 对第 3 节的销售数据做一次"部门 × 季度"的平均销售额透视(aggfunc="mean"),并加上 margins。

3. 用布尔索引和 query 两种方式,分别筛选出 sales 表中"销售部门 且 amount 大于 1000"的行,对比代码长度。

4. 解释:为什么 df.style.background_gradient(...) 之后,df 本身的数值没有任何变化?如果想让颜色真的导出到 Excel 文件里,应该怎么做?

5. 一段数据 age = [20, 200, -5, 30],请写一段 pandas 代码:把越界(<0 或 >120)的行替换成 NaN,然后用 dropna() 得到清洗后的 DataFrame。

6. (思考)Excel 的"合并单元格"在 pandas 里被 MultiIndex 取代。请说出 MultiIndex 相比合并单元格的两个优势(提示:从筛选、排序角度想)。


下一篇预告:第 50 章 Excel 公式与 pandas 对照 —— 把 SUMIF、COUNTIF、IF、VLOOKUP、RANK 这些 Excel 公式逐一翻译成 pandas 表达式。
— 全文完 —回到顶部 ↑
下载推广海报

文章推广海报

《第 49 章 Excel 常用功能与 pandas 对照》完整推广海报
DISCUSSION

文章回复

0 条公开回复
未登录回复需要审核后公开
还没有回复,欢迎参与讨论。