Pandas基础03(数据的合并操作/concat()/append()/merge())
3.4.1 数据的合并操作
3.4.1.1 使用concat()数据合并
在数据分析中,经常需要将多个数据集进行合并。Pandas 提供了一个强大的工具——pd.concat()
,用来连接两个或多个 DataFrame。这种合并操作可以是垂直合并(行合并)或水平合并(列合并)。此外,concat()
还提供了许多选项,帮助我们定制合并行为。
df1 = pd.DataFrame(np.random.randint(1, 10, (3, 4)), index=[1, 2, 3], columns=['A', 'B', 'C', 'D'])
df2 = pd.DataFrame(np.random.randint(1, 10, (3, 4)), index=[2, 3, 4], columns=['B', 'C', 'D', 'E'])
- 垂直合并:按行拼接
当希望将多个 DataFrame 垂直堆叠(即按行合并)时,可以使用 pd.concat()
,其默认的合并方式是沿着 axis=0
(即按行)。假设有两个 DataFrame df1
和 df2
,我们可以通过以下方式进行垂直合并:
# 垂直合并
result = pd.concat([df1, df2])
print(result)
输出:
# 结果不难发现对应的列索引会对齐,空缺的由NaN补齐
A B C D E
1 8.0 9 3 6 NaN
2 9.0 7 6 3 NaN
3 5.0 5 1 1 NaN
2 NaN 5 9 4 6.0
3 NaN 9 7 2 5.0
4 NaN 4 7 9 4.0
注意,合并后,df1
和 df2
的行索引是保留的。我们也可以通过设置 ignore_index=True
来重置行索引:
result = pd.concat([df1, df2], ignore_index=True)
print(result)
输出:
A B C D E
0 8.0 9 3 6 NaN
1 9.0 7 6 3 NaN
2 5.0 5 1 1 NaN
3 NaN 5 9 4 6.0
4 NaN 9 7 2 5.0
5 NaN 4 7 9 4.0
- 水平合并:按列拼接
除了按行合并,我们还可以选择按列(axis=1
)进行合并,即水平合并。这适用于当两个 DataFrame 具有相同的索引时,我们希望将它们的列进行拼接。例如:
result = pd.concat([df1, df2], axis=1)
print(result)
输出:
# 结果不难发现对应的行索引会对齐,空缺的由NaN补齐
A B C D B C D E
1 8.0 9.0 3.0 6.0 NaN NaN NaN NaN
2 9.0 7.0 6.0 3.0 5.0 9.0 4.0 6.0
3 5.0 5.0 1.0 1.0 9.0 7.0 2.0 5.0
4 NaN NaN NaN NaN 4.0 7.0 9.0 4.0
- 使用多层次索引
pd.concat()
还允许为合并的数据设置多层次索引,这对于标识数据来源非常有用。通过 keys
参数,我们可以为每个 DataFrame 指定一个标签,这样合并后的数据将包含这些标签作为层次索引。
按行合并时使用多层次索引
result = pd.concat([df1, df2], keys=['AA', 'BB'])
print(result)
输出:
A B C D E
AA 1 8.0 9 3 6 NaN
2 9.0 7 6 3 NaN
3 5.0 5 1 1 NaN
BB 2 NaN 5 9 4 6.0
3 NaN 9 7 2 5.0
4 NaN 4 7 9 4.0
按列合并时使用多层次索引
result = pd.concat([df1, df2], keys=['AA', 'BB'], axis=1)
print(result)
输出:
AA BB
A B C D B C D E
1 8.0 9.0 3.0 6.0 NaN NaN NaN NaN
2 9.0 7.0 6.0 3.0 5.0 9.0 4.0 6.0
3 5.0 5.0 1.0 1.0 9.0 7.0 2.0 5.0
4 NaN NaN NaN NaN 4.0 7.0 9.0 4.0
- 内连接与外连接
pd.concat()
默认采用外连接(join='outer'
),即保留所有的数据列并进行合并。对于存在不同列的 DataFrame,缺失的列将会填充为 NaN。可以通过设置 join='inner'
来进行内连接,即仅保留两个 DataFrame 中都存在的列。
外连接(默认)
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'B': [5, 6], 'C': [7, 8]})
# 外连接合并
result = pd.concat([df1, df2], join='outer')
print(result)
输出:
A B C D E
1 8.0 9 3 6 NaN
2 9.0 7 6 3 NaN
3 5.0 5 1 1 NaN
2 NaN 5 9 4 6.0
3 NaN 9 7 2 5.0
4 NaN 4 7 9 4.0
内连接
# 内连接合并
result = pd.concat([df1, df2], join='inner')
print(result)
输出:
B C D
1 9 3 6
2 7 6 3
3 5 1 1
2 5 9 4
3 9 7 2
4 4 7 9
3.4.1.2 使用append()数据合并
可以直接在后面追加一个二维数组
df1.append(df2)
A B C D E
1 8.0 9 3 6 NaN
2 9.0 7 6 3 NaN
3 5.0 5 1 1 NaN
2 NaN 5 9 4 6.0
3 NaN 9 7 2 5.0
4 NaN 4 7 9 4.0
3.4.1.2 使用merge()数据合并
在数据分析中,我们经常需要合并来自不同数据源的数据。Pandas 提供了一个非常强大的方法——merge()
,它可以根据某些条件将两个 DataFrame 合并在一起。我们可以通过 merge()
进行一对一、一对多、多对多等合并操作,还可以灵活地指定合并的列、使用不同的连接方式(如内连接、外连接),以及处理列名冲突等问题。
-
区别:merge与concat的区别在于,merge需要依据某一共同的行或列来进行合并使用pd.merge0合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。每一列元素的顺序不要求一致
-
1.一对一合并
当两个 DataFrame 中的键(用于合并的列)是一对一关系时,merge()
会将数据合并在一起,并根据指定的列对齐它们。
import pandas as pd
# 示例数据
df1_std = pd.DataFrame({
'id': [1, 2, 3],
'name': ['zhangsan', 'lisi', 'wangwu'],
'sex': ['man', 'woman', 'man'],
'profession_id': [1, 2, 3]
})
df2_profession = pd.DataFrame({
'profession_id': [1, 2],
'profession': ['软件工程', '人工智能']
})
# 一对一合并
result = df1_std.merge(df2_profession)
print(result)
输出:
id name sex profession_id profession
0 1 zhangsan man 1 软件工程
1 2 lisi woman 2 人工智能
-
- 一对多合并
一对多合并是指一个键值在一个 DataFrame 中是唯一的,而在另一个 DataFrame 中出现多次。merge()
方法可以自动处理这种情况,合并后的 DataFrame 中将有多行对应于相同的键。
df1_std = pd.DataFrame({
'id': [1, 2, 3],
'name': ['zhangsan', 'lisi', 'wangwu'],
'sex': ['man', 'woman', 'man'],
'profession_id': [1, 1, 2]
})
df2_profession = pd.DataFrame({
'profession_id': [1, 2],
'profession': ['软件工程', '人工智能']
})
# 一对多合并
result = df1_std.merge(df2_profession)
print(result)
输出:
id name sex profession_id profession
0 1 zhangsan man 1 软件工程
1 2 lisi woman 1 软件工程
2 3 wangwu man 2 人工智能
-
- 多对多合并
在多对多合并的场景中,两个 DataFrame 中的键都会出现多次,merge()
会将所有可能的组合合并到一个新的 DataFrame 中。
df1_std = pd.DataFrame({
'id': [1, 2, 3],
'name': ['zhangsan', 'lisi', 'wangwu'],
'sex': ['man', 'woman', 'man'],
'profession_id': [1, 1, 1]
})
df2_profession = pd.DataFrame({
'profession_id': [1, 1],
'profession': ['软件工程', '人工智能']
})
# 多对多合并
result = df1_std.merge(df2_profession)
print(result)
输出:
id name sex profession_id profession
0 1 zhangsan man 1 软件工程
1 1 zhangsan man 1 人工智能
2 2 lisi woman 1 软件工程
3 2 lisi woman 1 人工智能
4 3 wangwu man 1 软件工程
5 3 wangwu man 1 人工智能
-
- key的规范化
在合并时,如果两个 DataFrame 有多个相同的列名,或者我们希望合并使用不同的列作为键,可以通过以下几种方式来指定:
使用 on
指定要匹配的列名
df1_std = pd.DataFrame({
'id': [1, 2, 3],
'name': ['zhangsan', 'lisi', 'wangwu'],
'sex': ['man', 'woman', 'man'],
'profession_id': [1, 2, 3]
})
df2_profession = pd.DataFrame({
'profession_id': [1, 2],
'name': ['软件工程', '人工智能']
})
# 使用 'on' 指定匹配的列名
result = df1_std.merge(df2_profession, on="profession_id")
print(result)
id name sex profession_id name
0 1 zhangsan man 1 软件工程
1 2 lisi woman 2 人工智能
使用 left_on
和 right_on
指定左右 DataFrame 的列作为 key
df1_std = pd.DataFrame({
'id': [1, 2, 3],
'name': ['zhangsan', 'lisi', 'wangwu'],
'sex': ['man', 'woman', 'man'],
'profession_id': [1, 2, 3]
})
df2_profession = pd.DataFrame({
'id': [1, 2],
'name': ['软件工程', '人工智能']
})
# 使用 'left_on' 和 'right_on' 指定不同的列作为 key
result = df1_std.merge(df2_profession, left_on='profession_id', right_on='id')
print(result)
id name sex profession_id id name
0 1 zhangsan man 1 1 软件工程
1 2 lisi woman 2 2 人工智能
使用索引连接
有时希望使用 DataFrame 的索引来进行合并,可以通过 left_index=True
和 right_index=True
来指定。
df1_std = pd.DataFrame({
'id': [1, 2, 3],
'name': ['zhangsan', 'lisi', 'wangwu'],
'sex': ['man', 'woman', 'man'],
'profession_id': [1, 2, 3]
})
df2_profession = pd.DataFrame({
'profession_id': [4, 5, 6],
'name': ['软件工程', '人工智能', '计算机科学与技术']
})
# 使用索引连接
result = df1_std.merge(df2_profession, left_index=True, right_index=True)
print(result)
id name sex profession_id profession_id name
0 1 zhangsan man 1 4 软件工程
1 2 lisi woman 2 5 人工智能
2 3 wangwu man 3 6 计算机科学与技术
-
- 合并方式:内连接与外连接
在合并时,我们可以指定合并的类型,常见的有内连接(inner
)和外连接(outer
)。
5.1 内连接(inner
)
内连接只保留两个 DataFrame 中都有的行。
df1_std.merge(df2_profession, how='inner')
5.2 外连接(outer
)
外连接保留两个 DataFrame 中所有的行,对于缺失的值会填充 NaN。
df1_std.merge(df2_profession, how='outer')
-
- 列冲突处理:起别名
当合并的两个 DataFrame 中有相同的列名时,可以使用 suffixes
参数来为列名添加后缀,避免列冲突。
df1_std.merge(df2_profession, left_on='profession_id', right_on='id', how='outer', suffixes=['_df1', '_df2'])
这样,合并后的 DataFrame 将会在冲突列名后加上 _df1
和 _df2
,区分两个数据源。