HOWTO · Pandas

将两个 Pandas 系列合并到一个 DataFrame 中

本指南演示了如何使用 pandas.concat()、pandas.merge()、DataFrame.join() 方法将两个 Pandas 系列组合或合并到一个 DataFrame 中。

本页内容

在 pandas 中,Series 是一个一维带标签数组——大致相当于带索引的一列数据。要将两个或更多 Series 合并成一个 DataFrame,请把它们传给 pandas.concat() 并设置 axis=1;每个 Series 会成为一列,列标题来自其名称。如果需要不同的语义,pandas.concat() 也可以纵向堆叠 Series,pandas.merge() 像 SQL 连接一样按索引匹配行,而 DataFrame.join() 可以把一个已命名的 Series 附加到现有的 DataFrame 上。

本教程将通过可运行的示例逐一介绍每种方法。

根据所需结果选择方法

这四种方法都会生成表格数据,但它们回答的问题不同:

  • pandas.concat([s1, s2], axis=1) 将 Series 并排排列,使每个 Series 成为新 DataFrame 的一列。
  • pandas.concat([s1, s2]) 使用默认的 axis=0,把 Series 堆叠成一个更长的 Series;将结果包在 pd.DataFrame() 中即可得到单列 DataFrame。这是 Series.append() 目前的替代方案,后者已在 pandas 2.0 中移除。
  • pandas.merge(left, right, left_index=True, right_index=True) 像 SQL 连接一样,按索引或共享键值匹配行。
  • df.join(series) 把一个已命名的 Series 添加到你已有的 DataFrame 中,并按索引对齐。

有一种行为把这些方法联系在一起:pandas 按索引对齐带标签的数据。当输入的 Series 共享同一索引时,对齐是看不见的。当索引不同时,只出现在一个输入中的标签会在合并结果中产生缺失值(NaN)。

使用 pandas.concat() 将 Series 合并为列

pandas.concat() 函数沿轴连接 pandas 对象。传入 axis=1 会把这些对象排列成列;每个 Series 的名称会成为列标题,行则按索引对齐。

运行以下示例:

本节中的代码以及显示的标签或输出仍为英文。

import pandas as pd

# Create Series by assigning names
products = pd.Series(
    ["Intel Dell Laptops", "HP Laptops", "Lenavo Laptops", "Acer Laptops"],
    name="Products",
)
dollar_price = pd.Series([350, 300, 400, 250], name="Price")
percentage_sale = pd.Series([83, 99, 84, 76], name="Sale")

# merge three pandas series as columns using pandas.concat()
df = pd.concat([products, dollar_price, percentage_sale], axis=1)
print(df)

输出:

             Products  Price  Sale
0  Intel Dell Laptops    350    83
1          HP Laptops    300    99
2      Lenavo Laptops    400    84
3        Acer Laptops    250    76

因为这三个 Series 共享默认的整数索引,所以各行按顺序对齐。如果使用 axis=0(默认值),同样的调用会把这些值堆叠成一个长 Series,而不是生成列。

使用 pandas.concat() 纵向堆叠 Series

此任务的旧版本使用 Series.append(),这是一个沿 axis=0 连接的快捷方法。该方法在 pandas 1.4 中已弃用,并在 pandas 2.0 中移除,因此现在调用它会产生 AttributeError。替代方案是 pandas.concat():把 Series 放在列表中传入,并设置 ignore_index=True 为合并后的结果重新编号。

本节中的代码以及显示的标签或输出仍为英文。

import pandas as pd

technical = pd.Series(["Pandas", "Python", "Scala", "Hadoop"])
non_technical = pd.Series(["SEO", "Graphic design", "Content writing", "Marketing"])

# stack the series and shape the result into a one-column DataFrame
df = pd.DataFrame(
    pd.concat([technical, non_technical], ignore_index=True), columns=["Skills"]
)
print(df)

输出:

            Skills
0           Pandas
1           Python
2            Scala
3           Hadoop
4              SEO
5   Graphic design
6  Content writing
7        Marketing

这里 pd.concat() 返回一个包含八个值的 Series,pd.DataFrame(..., columns=["Skills"]) 再把它整理成单列 DataFrame。如果想保留原始索引标签而不是重新编号,请去掉 ignore_index=True。

使用 pandas.merge() 按索引匹配 Series

pandas.merge() 在已命名的 Series 或 DataFrame 对象之间执行 SQL 风格的连接。由于合并后的值会成为列,每个 Series 都需要一个 name。设置 left_index=True 和 right_index=True 会告诉 pandas.merge() 按索引而不是按键列匹配行。

本节中的代码以及显示的标签或输出仍为英文。

import pandas as pd

# Create Series by assigning names
products = pd.Series(
    ["Intel Dell Laptops", "HP Laptops", "Lenavo Laptops", "Acer Laptops"],
    name="Products",
)
dollar_price = pd.Series([350, 300, 400, 250], name="Price")

# match the two series on their index labels
df = pd.merge(products, dollar_price, right_index=True, left_index=True)
print(df)

输出:

             Products  Price
0  Intel Dell Laptops    350
1          HP Laptops    300
2      Lenavo Laptops    400
3        Acer Laptops    250

默认连接方式是 how="inner",因此只出现在其中一个 Series 里的索引标签不会出现在结果中;传入 how="outer" 可保留所有标签,并用 NaN 填补空缺。如果要按值而不是按索引匹配,请先把 Series 转换为 DataFrame,再把列名传给 on。

使用 DataFrame.join() 将 Series 连接到 DataFrame

当其中一方已经是 DataFrame 时,DataFrame.join() 是最方便的选择。先用 pd.DataFrame() 转换第一个 Series,然后传入第二个 Series 调用 .join();该 Series 必须有 name,它会成为新列的标题。

本节中的代码以及显示的标签或输出仍为英文。

import pandas as pd

# Create Series by assigning names
products = pd.Series(
    ["Intel Dell Laptops", "HP Laptops", "Lenavo Laptops", "Acer Laptops"],
    name="Products",
)
dollar_price = pd.Series([350, 300, 400, 250], name="Price")

# join the price series to a DataFrame built from products
df = pd.DataFrame(products).join(dollar_price)
print(df)

输出:

             Products  Price
0  Intel Dell Laptops    350
1          HP Laptops    300
2      Lenavo Laptops    400
3        Acer Laptops    250

与 pandas.merge() 一样,DataFrame.join() 按索引对齐,但它默认使用左连接,因此调用方 DataFrame 的每一行都会保留。

回顾一下方法选择:要从相互独立的 Series 构建 DataFrame,使用带 axis=1 的 pandas.concat();要完成过去由 Series.append() 执行的堆叠任务,使用沿 axis=0 的 pandas.concat();当需要按索引或键值匹配行时,使用 pandas.merge();要把已命名的 Series 附加到已有的 DataFrame 上时,使用 DataFrame.join()。