pandas中的数据合并:join、merge、concate
文章目录
前言
pandas中数据合并常用到的函数是join、merge、concat
一、join的使用
从pandas代码可以看到join函数主要是由merge和cancat两个函数实现的,join代码截取部分如下:
join函数的参数有other【要合并的表】、on【合并other表的列索引或列名可以是列表】、how【合并方式,可选’left’, ‘right’, ‘outer’, ‘inner’, ‘cross’,默认为left】、 lsuffix【列名重复时,合并后左表列名使用的后缀,默认’ ‘】、rsuffix【列名重复时,合并后右表列名使用的后缀,默认’ '】、sort【True时根据合并的索引排列合并结果,False时根据how参数排序,默认False】、validate【设置合并数据类型,支持"one_to_one" or “1:1”、“one_to_many” or “1:m”、“many_to_one” or “m:1”、“many_to_many” or “m:m”】
def join(
self,
other: DataFrame | Series | Iterable[DataFrame | Series],
on: IndexLabel | None = None,
how: MergeHow = "left",
lsuffix: str = "",
rsuffix: str = "",
sort: bool = False,
validate: str | None = None,
1.1 列名不同时两个DataFrame表简单合并
当将两个行数相同的DataFrame表简单合成一张表时,直接使用join就可以,若不存在相同的列名,不需要设置参数,若存在相同的列名,需要设置 lsuffix和rsuffix参数,当两个DataFrame表行数不同时,行数缺失的位置使用NAN填充。
import pandas as pd
data_1 = pd.DataFrame([[1, 2], [4, 5]], columns=["a", "b"])
data_2 = pd.DataFrame([[7, 8], [11, 12]], columns=["c", "d"])
print("data_1:", data_1)
print("data_2:", data_2)
data_3 = data_1.join(data_2)
print("data_3:", data_3)
输出为
data_1:
a b
0 1 2
1 4 5
data_2:
c d
0 7 8
1 11 12
data_3:
a b c d
0 1 2 7 8
1 4 5 11 12
Process finished with exit code 0
当两个DataFrame表行数不同时,行数缺失的位置使用NAN填充
import pandas as pd
data_1 = pd.DataFrame([[1, 2], [4, 5], [5, 6]], columns=["a", "b"])
data_2 = pd.DataFrame([[7, 8], [11, 12]], columns=["c", "d"])
print("data_1:", data_1)
print("data_2:", data_2)
data_3 = data_1.join(data_2)
print("data_3:", data_3)
输出为
data_1:
a b
0 1 2
1 4 5
2 5 6
data_2:
c d
0 7 8
1 11 12
data_3:
a b c d
0 1 2 7.0 8.0
1 4 5 11.0 12.0
2 5 6 NaN NaN
Process finished with exit code 0
1.2 存在相同列名时两个DataFrame表简单合并
若存在相同的列名,不设置 lsuffix, rsuffix会报错
import pandas as pd
data_1 = pd.DataFrame([[1, 2], [4, 5], [5, 6]], columns=["a", "b"])
data_2 = pd.DataFrame([[7, 8], [11, 12]], columns=["a", "d"])
print("data_1:", data_1)
print("data_2:", data_2)
data_3 = data_1.join(data_2)
print("data_3:", data_3)
输出报错
ValueError: columns overlap but no suffix specified: Index(['a'], dtype='object')
设置相同列名的后缀参数,可正常执行
import pandas as pd
data_1 = pd.DataFrame([[1, 2], [4, 5], [5, 6]], columns=["a", "b"])
data_2 = pd.DataFrame([[7, 8], [11, 12]], columns=["a", "d"])
print("data_1:", data_1)
print("data_2:", data_2)
data_3 = data_1.join(data_2, lsuffix="_left", rsuffix="_right")
print("data_3:", data_3)
输出为
data_1:
a b
0 1 2
1 4 5
2 5 6
data_2:
a d
0 7 8
1 11 12
data_3:
a_left b a_right d
0 1 2 7.0 8.0
1 4 5 11.0 12.0
2 5 6 NaN NaN
Process finished with exit code 0
1.3 根据相同的列名进行数据匹配
假设想根据列名"a",匹配两个表中列名"a"相同的数据, 将两个表要匹配的列名设置为表的索引,然后使用on参数进行匹配
import pandas as pd
data_1 = pd.DataFrame([[1, 2], [4, 5], [5, 6]], columns=["a", "b"])
data_2 = pd.DataFrame([[1, 8], [11, 12]], columns=["a", "d"])
print("data_1:", data_1)
print("data_2:", data_2)
data_1.set_index("a", inplace=True)
data_2.set_index("a", inplace=True)
data_3 = data_1.join(data_2, on=["a"])
print("data_3:", data_3)
输出为:
data_1:
a b
0 1 2
1 4 5
2 5 6
data_2:
a d
0 1 8
1 11 12
data_3:
a b d
1 2 8.0
4 5 NaN
5 6 NaN
二、merge的使用
pd.merge(
left,
right,
how="inner",
on=None,
left_on=None,
right_on=None,
left_index=False,
right_index=False,
sort=True,
suffixes=("_x", "_y"),
copy=True,
indicator=False,
validate=None,
)
left:左侧的数据。
right:右侧的数据。
on:指定两个dataframe按某一列进行连接,该列必须同时出现在两个dataframe中。如果未传递且left_index和right_index为False,则DataFrame中的列的交集将被推断为连接键。
left_on:左侧DataFrame中用作连接键的列。 可以是列名,索引级名称,也可以是长度等于DataFrame长度的数组。
right_on:右侧DataFrame中用作连接键的列。 可以是列名,索引级名称,也可以是长度等于DataFrame长度的数组。
left_index:如果为True,则使用左侧DataFrame中的索引(行标签)作为其连接键的列。对于具有MultiIndex(分层)的DataFrame,级别数必须与右侧DataFrame中的连接键数相匹配。
right_index:如果为True,则使用右侧DataFrame中的索引(行标签)作为其连接键的列。对于具有MultiIndex(分层)的DataFrame,级别数必须与左侧DataFrame中的连接键数相匹配。
how:‘left’,‘right’,‘outer’或‘inner’之一。默认inner。inner是取两个dataframe的连接键列中元素的交集,outer取其并集,如果其中一个dataframe中的连接键列中不含有某元素,则该元素对应的这行数据中的其它列用NAN填充。
sort:按字典顺序通过连接键对结果DataFrame进行排序。 默认为True,设置为False将在很多情况下显着提高性能。
suffixes:用于重叠列的字符串后缀元组。 默认为(‘x’,’ y’)。也可手动指定。
copy:copy=True(默认值),merge() 函数会创建一个副本,这样原始的DataFrame对象不会受到合并操作的影响。这是为了防止意外地修改原始数据,尤其是在进行复杂的数据操作时。如果你对合并的结果进行了一些更改,原始数据不会受到影响。copy=False:如果将 copy 参数设置为 False,那么在合并操作时不会创建副本。这意味着合并的结果将直接修改原始的DataFrame对象,可能会导致数据被覆盖或修改。这种情况下需要特别小心,确保你不会意外地破坏原始数据。一般来说,推荐保留默认值 copy=True,因为这样可以确保原始数据不会受到破坏。只有在你明确知道自己在做什么,并且有充分的理由在原始数据上进行操作时,才应该考虑将 copy 设置为 False。
indicator:indicator参数来指示合并的来源,以便在结果中显示每个行的来源是来自于哪个数据集。该参数的默认值为False,但是您可以将其设置为True或一个字符串,如’left_only’、‘right_only’、‘both’或’neither’,以控制显示哪些行来自哪些数据源。
validate:validate参数是在执行合并操作之前,对合并的数据进行验证的一个选项。这个参数允许你检查合并操作是否符合特定的条件或规则,从而确保合并操作的有效性。validate参数的可选值有以下几种:
“one_to_one”:验证合并的键是否具有唯一性,即每个键在左侧DataFrame和右侧DataFrame中只出现一次。如果验证失败,会引发MergeError异常。“one_to_many”:验证合并的键在左侧DataFrame中是否唯一,但可以在右侧DataFrame中重复出现。如果验证失败,会引发MergeError异常。“many_to_one”:验证合并的键在右侧DataFrame中是否唯一,但可以在左侧DataFrame中重复出现。如果验证失败,会引发MergeError异常。“many_to_many”:不执行任何验证,允许键在两个DataFrame中都可以重复出现。
2.1 列名不同时两个DataFrame表简单合并
merge()合并时需要合并部分列,如果只是将两个表合成一个宽表可以使用concate函数,下面将会详细介绍concate使用。取两个dataframe表的并集:how=‘outer’
import pandas as pd
data_1 = pd.DataFrame([[1, 2], [4, 5], [5, 6]], columns=["a", "b"])
data_2 = pd.DataFrame([[1, 8], [11, 12]], columns=["c", "d"])
print("data_1:", data_1)
print("data_2:", data_2)
data_3 = data_1.merge(data_2, left_on='a', right_on='c', how='outer')
print("merge后:", data_3)
输出结果为:
data_1:
a b
0 1 2
1 4 5
2 5 6
data_2:
c d
0 1 8
1 11 12
merge后:
a b c d
0 1.0 2.0 1.0 8.0
1 4.0 5.0 NaN NaN
2 5.0 6.0 NaN NaN
3 NaN NaN 11.0 12.0
取两个dataframe表的交集:how=‘inner’
import pandas as pd
data_1 = pd.DataFrame([[1, 2], [4, 5], [5, 6]], columns=["a", "b"])
data_2 = pd.DataFrame([[1, 8], [11, 12]], columns=["c", "d"])
print("data_1:", data_1)
print("data_2:", data_2)
data_3 = data_1.merge(data_2, left_on='a', right_on='c', how='inner')
print("merge后:", data_3)
输出结果为:
data_1:
a b
0 1 2
1 4 5
2 5 6
data_2:
c d
0 1 8
1 11 12
merge后:
a b c d
0 1 2 1 8
left_index和right_index参数使用:
import pandas as pd
data_1 = pd.DataFrame([[1, 2], [4, 5], [5, 6]], columns=["a", "b"], index=[1, 2, 3])
data_2 = pd.DataFrame([[1, 8], [11, 12]], columns=["c", "d"], index=[2, 3])
print("data_1:", data_1)
print("data_2:", data_2)
data_3 = data_1.merge(data_2, left_index=True, right_index=True, how='inner')
print("merge后:", data_3)
输出结果为:
data_1:
a b
1 1 2
2 4 5
3 5 6
data_2:
c d
2 1 8
3 11 12
merge后:
a b c d
2 4 5 1 8
3 5 6 11 12
2.2 存在相同列名时两个DataFrame表简单合并
取两个dataframe表的并集:how=‘outer’,其中left_on表示左表要使用的索引列,right_on表示右表要使用的索引列
import pandas as pd
data_1 = pd.DataFrame([[1, 2], [4, 5], [5, 6]], columns=["a", "b"])
data_2 = pd.DataFrame([[1, 8], [11, 12]], columns=["a", "d"])
print("data_1:", data_1)
print("data_2:", data_2)
data_3 = data_1.merge(data_2, left_on='a', right_on='a', how='outer')
print("merge后:", data_3)
输出结果为:
data_1:
a b
0 1 2
1 4 5
2 5 6
data_2:
a d
0 1 8
1 11 12
merge后:
a b d
0 1 2.0 8.0
1 4 5.0 NaN
2 5 6.0 NaN
3 11 NaN 12.0
取两个dataframe表的交集:默认how=‘inner’,其中left_on表示左表要使用的索引列,right_on表示右表要使用的索引列
import pandas as pd
data_1 = pd.DataFrame([[1, 2], [4, 5], [5, 6]], columns=["a", "b"])
data_2 = pd.DataFrame([[1, 8], [11, 12]], columns=["a", "d"])
print("data_1:", data_1)
print("data_2:", data_2)
data_3 = data_1.merge(data_2, left_on="a", right_on="a")
print("merge后:", data_3)
输出结果:可以看到只输出匹配到的数据,没匹配到不会用NAN填充
data_1:
a b
0 1 2
1 4 5
2 5 6
data_2:
a d
0 1 8
1 11 12
merge后:
a b d
0 1 2 8
三、concat的使用
pd.concat(
objs,
axis=0,
join="outer",
ignore_index=False,
keys=None,
levels=None,
names=None,
verify_integrity=False,
copy=True,
)
objs: 要合并的 DataFrame、Series 或者 DataFrame/Series 列表。
axis: 整数值,用于指定合并的轴方向。axis=0 表示沿着行轴合并,axis=1 表示沿着列轴合并。
join: 字符串参数,用于指定连接方式。默认值是 ‘outer’,表示进行外连接。其他可能的值有 ‘inner’(内连接)。
ignore_index: 布尔值参数,如果设置为 True,则合并后的结果会重新生成索引,忽略原来的索引,默认值为 False。
keys: 列表或数组,用于创建层次化索引。
levels: 多层次索引的层级名列表。
sort: 布尔值参数,用于指定在连接轴上对索引进行排序,默认值为 False。
copy: 布尔值参数,如果设置为 True,则会复制合并的数据,默认值为 True。
3.1 列名不同时两个DataFrame表简单合并
axis=0,按行合并,缺失的值用NAN填充
import pandas as pd
data_1 = pd.DataFrame([[1, 2], [4, 5], [5, 6]], columns=["a", "b"])
data_2 = pd.DataFrame([[1, 8], [11, 12]], columns=["c", "d"])
print("data_1:", data_1)
print("data_2:", data_2)
data_3 = pd.concat([data_1, data_2], axis=0, ignore_index=True)
print("concat后:", data_3)
输出结果为:
data_1:
a b
0 1 2
1 4 5
2 5 6
data_2:
c d
0 1 8
1 11 12
merge后:
a b c d
0 1.0 2.0 NaN NaN
1 4.0 5.0 NaN NaN
2 5.0 6.0 NaN NaN
3 NaN NaN 1.0 8.0
4 NaN NaN 11.0 12.0
axis=1,按列合并,缺失的行值用NAN填充
import pandas as pd
data_1 = pd.DataFrame([[1, 2], [4, 5], [5, 6]], columns=["a", "b"])
data_2 = pd.DataFrame([[1, 8], [11, 12]], columns=["c", "d"])
print("data_1:", data_1)
print("data_2:", data_2)
data_3 = pd.concat([data_1, data_2], axis=1, ignore_index=False)
print("concat后:", data_3)
输出结果为:
data_1:
a b
0 1 2
1 4 5
2 5 6
data_2:
c d
0 1 8
1 11 12
concat后:
a b c d
0 1 2 1.0 8.0
1 4 5 11.0 12.0
2 5 6 NaN NaN
3.2 存在相同列名时两个DataFrame表简单合并
axis=0,按行合并,缺失的值用NAN填充
import pandas as pd
data_1 = pd.DataFrame([[1, 2], [4, 5], [5, 6]], columns=["a", "b"])
data_2 = pd.DataFrame([[1, 8], [11, 12]], columns=["a", "d"])
print("data_1:", data_1)
print("data_2:", data_2)
data_3 = pd.concat([data_1, data_2], axis=0, ignore_index=True)
print("concat后:", data_3)
输出结果为:
data_1:
a b
0 1 2
1 4 5
2 5 6
data_2:
a d
0 1 8
1 11 12
concat后:
a b d
0 1 2.0 NaN
1 4 5.0 NaN
2 5 6.0 NaN
3 1 NaN 8.0
4 11 NaN 12.0
axis=1,按列合并,缺失的行值用NAN填充
import pandas as pd
data_1 = pd.DataFrame([[1, 2], [4, 5], [5, 6]], columns=["a", "b"])
data_2 = pd.DataFrame([[1, 8], [11, 12]], columns=["a", "d"])
print("data_1:", data_1)
print("data_2:", data_2)
data_3 = pd.concat([data_1, data_2], axis=1, ignore_index=False)
print("concat后:", data_3)
输出结果为:
data_1:
a b
0 1 2
1 4 5
2 5 6
data_2:
a d
0 1 8
1 11 12
concat后:
a b a d
0 1 2 1.0 8.0
1 4 5 11.0 12.0
2 5 6 NaN NaN