
1. 理解 pd.concat 与 pd.merge 的选择
在 pandas 中,pd.merge 和 pd.concat 都是用于组合 dataframe 的强大工具,但它们的设计理念和应用场景有所不同。
- pd.merge: 主要用于执行数据库风格的连接操作(如内连接、左连接、右连接、外连接),它通过指定一个或多个键列(on, left_on, right_on)来匹配两个 DataFrame 中的行。当需要基于列值进行复杂匹配时,pd.merge 是首选。
- pd.concat: 主要用于沿着某个轴(行或列)堆叠或连接 DataFrame。当 axis=0 时,它将 DataFrame 堆叠起来(行连接);当 axis=1 时,它将 DataFrame 横向连接(列连接),此时它会尝试根据它们的索引进行对齐。
有时,出于性能、内存管理或特定数据处理逻辑的考虑,我们可能希望使用 pd.concat 来实现类似 pd.merge 的功能,尤其是在合并基于日期时间等精确匹配的列时。通过将合并键设置为 DataFrame 的索引,pd.concat 可以在索引级别进行高效对齐。
2. 核心策略:基于索引的横向合并
当使用 pd.concat 进行横向合并(axis=1)时,其核心思想是将作为合并键的列提升为 DataFrame 的索引。这样,pd.concat 就能利用索引的高效查找机制来对齐数据。这个过程通常包含三个关键步骤:
- set_index(): 将用于合并的列设置为 DataFrame 的索引。
- pd.concat(..., axis=1, join='inner'): 对已设置索引的 DataFrame 列表执行横向连接。join='inner' 参数确保只保留所有 DataFrame 中索引共同存在的部分,这等同于 pd.merge 的内连接。
- reset_index(): 合并完成后,将索引重新转换回普通的列,以便后续处理或保存。
3. 示例:使用 pd.concat 合并日期时间 DataFrame
假设我们有三个 DataFrame:ads_hour、ads 和 advertising,它们包含日期时间信息,我们需要将它们进行合并。
原始数据模拟:
import pandas as pd
# 模拟数据
data_ads_hour = {'Date': ['2023-01-01 10:00:00', '2023-01-01 11:00:00', '2023-01-02 12:00:00'],
'Impressions': [100, 120, 150]}
ads_hour = pd.DataFrame(data_ads_hour)
data_ads = {'Time': ['2023-01-01 10:00:00', '2023-01-01 11:00:00', '2023-01-03 13:00:00'],
'Clicks': [10, 15, 20]}
ads = pd.DataFrame(data_ads)
data_advertising = {'TV': ['2023-01-01 10:00:00', '2023-01-01 11:00:00', '2023-01-02 12:00:00'],
'Spend': [500, 600, 700]}
advertising = pd.DataFrame(data_advertising)
print("原始 ads_hour:\n", ads_hour)
print("\n原始 ads:\n", ads)
print("\n原始 advertising:\n", advertising)使用 pd.concat 进行合并:
# 1. 确保所有用于合并的日期时间列为 datetime 类型
ads_hour['Date'] = pd.to_datetime(ads_hour['Date'], errors='coerce')
ads['Time'] = pd.to_datetime(ads['Time'], errors='coerce')
advertising['TV'] = pd.to_datetime(advertising['TV'], errors='coerce')
# 2. 第一次合并:ads_hour 和 ads
# 目标:将 ads_hour 的 'Date' 列与 ads 的 'Time' 列进行合并
merged_ads_hour_ads = pd.concat(
[ads_hour.set_index('Date'), ads.set_index('Time')], # 将合并键设置为索引










