author: 专注Python实战,分享爬虫与数据分析干货
title: Python爬虫实战⑲|Pandas数据合并与重塑,多数据源整合
update: 2026-04-26
tags: Python,Pandas,合并,merge,concat,join,数据重塑,melt,pivot
作者:专注Python实战,分享爬虫与数据分析干货
更新时间:2026年4月
适合人群:有Pandas基础、需要整合多个数据源的开发者
前言:数据散落在多个文件,怎么合并?
爬虫经常产生多个数据文件:
- 不同页面的数据 → 需要纵向拼接
- 商品信息 + 价格信息 → 需要横向关联
- 宽表 ↔ 长表 → 需要重塑
今天解决所有数据合并问题!
一、纵向拼接(concat)
1.1 基础拼接
python
import pandas as pd
df1 = pd.DataFrame({"姓名": ["张三", "李四"], "年龄": [25, 30]})
df2 = pd.DataFrame({"姓名": ["王五", "赵六"], "年龄": [28, 35]})
# 纵向拼接(上下合并)
result = pd.concat([df1, df2], ignore_index=True)
print(result)
# 姓名 年龄
# 0 张三 25
# 1 李四 30
# 2 王五 28
# 3 赵六 35
1.2 列不完全一致时的拼接
python
df1 = pd.DataFrame({"姓名": ["张三"], "年龄": [25], "城市": ["北京"]})
df2 = pd.DataFrame({"姓名": ["李四"], "年龄": [30], "部门": ["技术"]})
# join="outer":保留所有列(默认)
result = pd.concat([df1, df2], ignore_index=True)
print(result)
# 姓名 年龄 城市 部门
# 0 张三 25 北京 NaN
# 1 李四 30 NaN 技术
# join="inner":只保留共有列
result = pd.concat([df1, df2], ignore_index=True, join="inner")
print(result)
# 姓名 年龄
# 0 张三 25
# 1 李四 30
1.3 批量合并多个文件
python
import os
import pandas as pd
# 合并目录下所有CSV
data_dir = "data/"
dfs = []
for filename in os.listdir(data_dir):
if filename.endswith(".csv"):
filepath = os.path.join(data_dir, filename)
df = pd.read_csv(filepath, encoding="utf-8-sig")
df["来源文件"] = filename # 标记来源
dfs.append(df)
merged = pd.concat(dfs, ignore_index=True)
print(f"合并 {len(dfs)} 个文件,共 {len(merged)} 行")
merged.to_csv("merged_all.csv", index=False, encoding="utf-8-sig")
二、横向合并(merge)
2.1 四种合并方式
python
df_products = pd.DataFrame({
"商品ID": ["P001", "P002", "P003", "P004"],
"商品名": ["手机", "电脑", "耳机", "键盘"],
})
df_prices = pd.DataFrame({
"商品ID": ["P001", "P002", "P003", "P005"],
"价格": [3999, 6999, 299, 199],
})
# 内连接(交集)------ 最常用
inner = pd.merge(df_products, df_prices, on="商品ID", how="inner")
print("内连接(交集):")
print(inner)
# 左连接(保留左表所有行)
left = pd.merge(df_products, df_prices, on="商品ID", how="left")
print("\n左连接:")
print(left)
# 右连接(保留右表所有行)
right = pd.merge(df_products, df_prices, on="商品ID", how="right")
print("\n右连接:")
print(right)
# 外连接(并集)
outer = pd.merge(df_products, df_prices, on="商品ID", how="outer")
print("\n外连接:")
print(outer)
2.2 多列关联
python
df1 = pd.DataFrame({
"城市": ["北京", "北京", "上海"],
"品类": ["手机", "电脑", "手机"],
"销量": [100, 80, 120],
})
df2 = pd.DataFrame({
"城市": ["北京", "北京", "上海"],
"品类": ["手机", "电脑", "手机"],
"均价": [3999, 6999, 4299],
})
result = pd.merge(df1, df2, on=["城市", "品类"])
print(result)
2.3 列名不同时的合并
python
df1 = pd.DataFrame({"product_id": ["P001", "P002"], "name": ["手机", "电脑"]})
df2 = pd.DataFrame({"item_id": ["P001", "P002"], "price": [3999, 6999]})
result = pd.merge(df1, df2, left_on="product_id", right_on="item_id")
print(result)
三、join(索引合并)
python
df1 = pd.DataFrame({"销量": [100, 80]}, index=["手机", "电脑"])
df2 = pd.DataFrame({"价格": [3999, 6999]}, index=["手机", "电脑"])
# 基于索引合并
result = df1.join(df2)
print(result)
四、数据重塑
4.1 宽表 → 长表(melt)
python
df_wide = pd.DataFrame({
"城市": ["北京", "上海", "广州"],
"手机": [100, 120, 80],
"电脑": [80, 90, 60],
"耳机": [200, 150, 180],
})
# 宽表转长表
df_long = pd.melt(
df_wide,
id_vars=["城市"], # 保留的列
value_vars=["手机", "电脑", "耳机"], # 要展开的列
var_name="品类", # 展开后的列名
value_name="销量", # 值的列名
)
print(df_long)
4.2 长表 → 宽表(pivot)
python
# 长表转宽表
df_wide2 = df_long.pivot(
index="城市",
columns="品类",
values="销量",
).reset_index()
print(df_wide2)
4.3 stack / unstack
python
# 多级索引操作
result = df.groupby(["城市", "品类"])["销量"].sum()
print(result)
# unstack:把最后一个索引变成列
wide = result.unstack(fill_value=0)
print(wide)
# stack:把列变成索引
long = wide.stack().reset_index(name="销量")
print(long)
五、实战:多数据源整合
python
import pandas as pd
# 1. 读取多个爬虫数据文件
products = pd.read_csv("products.csv", encoding="utf-8-sig")
reviews = pd.read_csv("reviews.csv", encoding="utf-8-sig")
prices = pd.read_csv("price_history.csv", encoding="utf-8-sig")
# 2. 合并商品信息和价格
product_prices = pd.merge(
products,
prices.groupby("商品ID").agg(最新价格=("价格", "last"), 均价=("价格", "mean")),
on="商品ID",
how="left",
)
# 3. 合并评论统计
review_stats = reviews.groupby("商品ID").agg(
评论数=("评论ID", "count"),
平均评分=("评分", "mean"),
)
product_full = pd.merge(product_prices, review_stats, on="商品ID", how="left")
# 4. 填充缺失值
product_full["评论数"] = product_full["评论数"].fillna(0).astype(int)
product_full["平均评分"] = product_full["平均评分"].fillna(0)
# 5. 导出
product_full.to_csv("product_full.csv", index=False, encoding="utf-8-sig")
print(f"合并完成: {product_full.shape}")
print(product_full.head())
六、知识卡
| 方法 | 说明 |
|---|---|
| pd.concat() | 纵向/横向拼接 |
| pd.merge() | 关联合并(SQL JOIN) |
| how="inner" | 内连接(交集) |
| how="left" | 左连接 |
| how="outer" | 外连接(并集) |
| on="列名" | 关联键 |
| df.join() | 基于索引合并 |
| pd.melt() | 宽表→长表 |
| df.pivot() | 长表→宽表 |
| df.unstack() | 索引→列 |
| df.stack() | 列→索引 |
七、课后作业
必做题:
- 合并两个CSV文件(纵向拼接)
- 用merge关联商品表和价格表
- 用melt将宽表转为长表
选做题:
- 编写批量合并脚本
- 实现多数据源自动整合
有问题欢迎评论区留言,大家一起讨论!
标签:Python | Pandas | merge | concat | 数据合并 | 数据重塑 | melt