pandas合并操作
一、基础用法
1. merge
操作
merge
操作类似于 SQL 中的 JOIN 操作,可以根据一个或多个键将两个 DataFrame 合并。
常见参数:
left
:左边的 DataFrame。right
:右边的 DataFrame。how
:合并的方式,常用的有 ‘left’(左连接)、‘right’(右连接)、‘outer’(外连接)、‘inner’(内连接)。on
:用于连接的列名,如果两个 DataFrame 中有相同的列名,可以用on
指定。left_on
:左边 DataFrame 用于连接的列名。right_on
:右边 DataFrame 用于连接的列名。suffixes
:当合并的两个 DataFrame 中存在相同列名时,用于追加到列名的后缀,默认是 (‘_x’, ‘_y’)。
示例 1:根据单列合并
import pandas as pd
# 创建 DataFrame
df1 = pd.DataFrame({
'id': [1, 2, 3, 4],
'name': ['Alice', 'Bob', 'Charlie', 'David']
})
df2 = pd.DataFrame({
'id': [3, 4, 5, 6],
'age': [23, 34, 45, 56]
})
# 内连接(inner join)合并
result = pd.merge(df1, df2, on='id', how='inner')
print(result)
输出:
id name age
0 3 Charlie 23
1 4 David 34
示例 2:根据多列合并
# 创建 DataFrame
df3 = pd.DataFrame({
'id': [1, 2, 3, 4],
'name': ['Alice', 'Bob', 'Charlie', 'David'],
'age': [24, 27, 22, 32]
})
df4 = pd.DataFrame({
'id': [3, 4, 5, 6],
'name': ['Charlie', 'David', 'Edward', 'Fiona'],
'salary': [50000, 60000, 70000, 80000]
})
# 根据 'id' 和 'name' 列合并
result = pd.merge(df3, df4, on=['id', 'name'], how='inner')
print(result)
输出:
id name age salary
0 3 Charlie 22 50000
1 4 David 32 60000
2. join
操作
join
是专门用于基于索引合并的操作,常用于需要用 DataFrame 的索引进行连接的情况。
常见参数:
other
:要合并的 DataFrame。how
:连接方式,同merge
。on
:用于连接的列名,如果不是基于索引连接,则需要指定。lsuffix
和rsuffix
:左右重名列的后缀。
示例 3:索引合并
df5 = pd.DataFrame({
'age': [24, 27, 22, 32]
}, index=['Alice', 'Bob', 'Charlie', 'David'])
df6 = pd.DataFrame({
'salary': [50000, 60000, 70000, 80000]
}, index=['Bob', 'Charlie', 'David', 'Edward'])
# 使用 join 合并
result = df5.join(df6, how='inner')
print(result)
输出:
age salary
Bob 27 50000
Charlie 22 60000
David 32 70000
3. concat
操作
concat
用于沿一个轴(行或列)连接多个 DataFrame。与 merge
和 join
不同的是,它并不需要依据键来合并数据,而是简单地将数据拼接在一起。
常见参数:
objs
:需要连接的 DataFrame 或 Series 序列。axis
:连接方向,0 为沿着行方向(纵向),1 为沿着列方向(横向)。join
:连接方式,默认为 ‘outer’。ignore_index
:是否忽略原有的索引,重新生成新的索引。
示例 4:纵向合并
df7 = pd.DataFrame({
'name': ['Alice', 'Bob'],
'age': [24, 27]
})
df8 = pd.DataFrame({
'name': ['Charlie', 'David'],
'age': [22, 32]
})
# 使用 concat 纵向合并
result = pd.concat([df7, df8], axis=0, ignore_index=True)
print(result)
输出:
name age
0 Alice 24
1 Bob 27
2 Charlie 22
3 David 32
示例 5:横向合并
# 使用 concat 横向合并
result = pd.concat([df7, df8], axis=1)
print(result)
输出:
name age name age
0 Alice 24 Charlie 22
1 Bob 27 David 32
二、进阶用法
1. merge
1.1 使用 indicator
参数追踪合并操作
indicator
参数可以帮助你了解每一行数据在合并过程中的来源。这个功能对调试数据合并或理解合并结果非常有用。
import pandas as pd
df1 = pd.DataFrame({'id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Charlie']})
df2 = pd.DataFrame({'id': [2, 3, 4], 'age': [24, 27, 22]})
# 使用 indicator 追踪合并来源
result = pd.merge(df1, df2, on='id', how='outer', indicator=True)
print(result)
输出:
id name age _merge
0 1 Alice NaN left_only
1 2 Bob 24.0 both
2 3 Charlie 27.0 both
3 4 NaN 22.0 right_only
_merge
列显示了每一行是来自于左表(left_only
)、右表(right_only
)还是两个表都有的数据(both
)。
1.2 自定义列名后缀
当合并的 DataFrame 存在相同的列名时,suffixes
参数可以帮助你自定义合并后列名的后缀。
df1 = pd.DataFrame({'id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Charlie'], 'age': [24, 27, 22]})
df2 = pd.DataFrame({'id': [2, 3, 4], 'name': ['David', 'Edward', 'Fiona'], 'age': [30, 35, 40]})
# 使用自定义的后缀
result = pd.merge(df1, df2, on='id', how='outer', suffixes=('_left', '_right'))
print(result)
输出:
id name_left age_left name_right age_right
0 1 Alice 24.0 NaN NaN
1 2 Bob 27.0 David 30.0
2 3 Charlie 22.0 Edward 35.0
3 4 NaN NaN Fiona 40.0
2. concat
2.1 合并时忽略索引
concat
的 ignore_index
参数允许你在合并时忽略原始索引,并为结果 DataFrame 生成新的连续索引。
df3 = pd.DataFrame({'name': ['Alice', 'Bob'], 'age': [24, 27]}, index=[0, 1])
df4 = pd.DataFrame({'name': ['Charlie', 'David'], 'age': [22, 32]}, index=[2, 3])
# 使用 ignore_index 忽略原索引
result = pd.concat([df3, df4], ignore_index=True)
print(result)
输出:
name age
0 Alice 24
1 Bob 27
2 Charlie 22
3 David 32
2.2 使用 keys
参数分层级索引
当合并多个 DataFrame 时,可以使用 keys
参数创建一个分层索引,方便日后引用和处理。
df5 = pd.DataFrame({'name': ['Alice', 'Bob'], 'age': [24, 27]})
df6 = pd.DataFrame({'name': ['Charlie', 'David'], 'age': [22, 32]})
# 使用 keys 创建分层索引
result = pd.concat([df5, df6], keys=['group1', 'group2'])
print(result)
输出:
name age
group1 0 Alice 24
1 Bob 27
group2 0 Charlie 22
1 David 32
3. join
3.1 基于索引的多重合并
join
可以一次性合并多个 DataFrame,并且可以指定多种合并方式。
df7 = pd.DataFrame({'age': [24, 27, 22]}, index=['Alice', 'Bob', 'Charlie'])
df8 = pd.DataFrame({'salary': [50000, 60000, 70000]}, index=['Bob', 'Charlie', 'David'])
df9 = pd.DataFrame({'department': ['HR', 'Finance', 'IT']}, index=['Alice', 'Charlie', 'David'])
# 一次性合并多个 DataFrame
result = df7.join([df8, df9], how='outer')
print(result)
输出:
age salary department
Alice 24.0 NaN HR
Bob 27.0 50000.0 NaN
Charlie 22.0 60000.0 Finance
David NaN 70000.0 IT
4. 其它高级技巧和注意事项
4.1 数据对齐
Pandas 合并操作默认是基于标签对齐的,因此合并的 DataFrame 的索引或列名称是关键。如果你在合并过程中遇到问题,检查标签对齐是否是你想要的非常重要。
4.2 性能优化
在合并大数据集时,考虑使用 sort=False
来避免排序开销,从而提高性能。
result = pd.merge(df1, df2, on='id', how='outer', sort=False)
4.3 避免内存不足
对于非常大的数据集,合并操作可能会导致内存不足。可以使用 chunk
读取方式或 Dask 库处理大数据集。
5. 实际应用场景中的合并
5.1 时间序列数据对齐
假设你有两个不同频率的时间序列数据集,可以使用 pd.merge_asof
来进行对齐,这对处理金融数据、IoT 数据等非常有用。
df10 = pd.DataFrame({
'time': pd.to_datetime(['2021-01-01 01:00:00', '2021-01-01 02:00:00', '2021-01-01 03:00:00']),
'value': [10, 15, 20]
})
df11 = pd.DataFrame({
'time': pd.to_datetime(['2021-01-01 01:30:00', '2021-01-01 02:30:00']),
'value2': [5, 10]
})
# 使用 merge_asof 对齐
result = pd.merge_asof(df10, df11, on='time')
print(result)
输出:
time value value2
0 2021-01-01 01:00:00 10 NaN
1 2021-01-01 02:00:00 15 5.0
2 2021-01-01 03:00:00 20 10.0