概述

在数据处理和分析的领域中,经常需要整合来自不同数据源的信息,以便进行更深入的分析和洞察。当这些数据源以多个DataFrame的形式存在时,关联这些DataFrame就变得至关重要。关联操作允许我们基于共同的键或索引将不同的数据集连接起来,从而创建一个更全面、更丰富的数据集。

关联多个DataFrame的目的通常是为了:

  • 整合信息:将来自不同来源但具有相关性的数据整合在一起,以便在同一视图中进行分析。
  • 消除冗余:通过合并重复的信息,减少数据中的冗余,使分析更加高效。
  • 增强分析能力:通过添加新的特征或变量,扩展分析的可能性,发现新的模式和关系。

在Python的Pandas库中,关联多个DataFrame是一个常见的任务。Pandas提供了强大的功能,使得关联操作变得简单而直观。通过使用诸如merge、concat等函数,我们可以轻松地实现内连接、外连接、左连接、右连接以及沿轴合并等多种关联方式。
关联多个DataFrame时,需要注意以下几点:

  • 键的匹配:确保用于关联的键在两个或多个DataFrame之间是匹配的,这通常涉及到数据类型和格式的一致性。
  • 缺失值的处理:关联过程中可能会产生缺失值,需要决定如何处理这些缺失值,例如填充、删除或保留。
  • 关联类型的选择:根据分析的需求和数据的特点选择合适的关联类型。不同的关联类型会产生不同的结果,并可能影响后续的分析和解释。

通过合理地关联多个DataFrame,我们可以构建出更加丰富和全面的数据集,为数据分析提供坚实的基础。无论是在学术研究、商业分析还是其他领域,关联多个DataFrame都是数据处理和分析中的关键步骤之一。
本篇我们主要介绍Dataframe的数据组合和apply的相关语法。

一、 数据组合(多个Dataframe拼接,关联)

1. concat()

concat() 是 pandas 库中用于合并两个或多个 DataFrame 对象的函数。它可以沿着一个特定的轴(行或列)将多个 DataFrame 拼接在一起,生成一个新的 DataFrame。

(1) 基础语法:

pandas.concat(objs, axis=0, join='outer', ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=False)

(2) 参数:

  • objs: 要连接的 DataFrame 或 Series 对象组成的序列或映射。
  • axis: 连接的轴,默认为 0,表示沿着行进行连接(垂直堆叠);如果为 1,则沿着列进行连接(水平堆叠)。也可传入’rows’(行)或’columns’(列)
  • join: 连接方式,默认为 ‘outer’,表示使用外连接。其他选项包括 ‘inner’,表示使用内连接,‘left’左连接,‘right’右连接。
  • ignore_index: 是否忽略现有索引并重置为新索引,默认为 False。如果为 True,则结果 DataFrame 的索引将是一个简单的整数索引。
  • keys: 用于创建分层索引的键序列或列表。例如,如果你有两个 DataFrame 并希望将它们连接在一起,同时保留每个 DataFrame 的标识,可以使用这个参数。
  • levels: 用于构造多层索引的序列列表,通常与 keys 一起使用。
  • names: 分层索引级别的名称列表。
  • verify_integrity: 如果为 True,会检查新索引是否有重复,这会增加连接操作的时间。默认为 False。
  • sort: 如果连接键不是索引,则先对数据进行排序。这个参数在较新版本的 pandas 中已被弃用,因为排序操作可能会导致性能问题。

(3) 代码实现:

  • 沿着行轴(axis=0)连接
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2'],  
                    'B': ['B0', 'B1', 'B2'],  
                    'C': ['C0', 'C1', 'C2'],  
                    'D': ['D0', 'D1', 'D2']},  
                   index=[0, 1, 2])  
  
df2 = pd.DataFrame({'A': ['A3', 'A4', 'A5'],  
                    'B': ['B3', 'B4', 'B5'],  
                    'C': ['C3', 'C4', 'C5'],  
                    'D': ['D3', 'D4', 'D5']},  
                   index=[3, 4, 5])  
  
result = pd.concat([df1, df2])
print(result)

运行结果:
在这里插入图片描述

  • 沿着列轴(axis=1)连接
result = pd.concat([df1, df2], axis=1)
print(result)

运行结果:
在这里插入图片描述

  • 忽略原始索引
result = pd.concat([df1, df2], ignore_index=True)
print(result)

运行结果:
在这里插入图片描述

  • 使用键添加层次化索引(多重索引会在下篇博客中详细介绍)
result = pd.concat([df1, df2], keys=['df1', 'df2'])
print(result)

运行结果:
在这里插入图片描述

  • 注意事项
    当连接多个 DataFrame 时,它们的列名应该是一致的,除非在连接时指定了不同的处理方式(例如,使用 join=‘inner’ 只保留共有的列)。
    如果连接的 DataFrame 具有不同的索引,并且 ignore_index 设置为 False,则结果 DataFrame 将保留这些索引,这可能导致索引不连续或重复。
    使用 keys 参数时,结果 DataFrame 将具有一个多层索引,其中外层索引由 keys 参数提供的值组成。

2. append() (新版本pandas已停用)

(1) 基本语法

DataFrame.append(other, ignore_index=False, verify_integrity=False, sort=False)

(2) 参数说明

  • other: 要追加的 DataFrame 或 Series 对象。
  • ignore_index: 是否忽略现有索引,并生成一个新的整数索引。默认为 False,意味着将保留原有索引,并可能产生重复的索引值。
  • verify_integrity: 如果为 True,则当创建新对象时检查新索引是否有重复。这可能会增加追加操作的时间。默认为 False。
  • sort: 根据列名对 DataFrame 进行排序。此参数在较新版本的 pandas 中已被弃用,因为排序操作可能会导致性能问题。

(3) 代码展示

  • 追加单个 DataFrame
import pandas as pd  
  
# 创建两个 DataFrame  
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})  
df2 = pd.DataFrame({'A': [5, 6], 'B': [7, 8]})  
  
# 使用 append 方法追加 df2 到 df1  
result = df1.append(df2, ignore_index=True)  
  
print(result)
  • 追加多个 DataFrame
python
# 创建第三个 DataFrame  
df3 = pd.DataFrame({'A': [9, 10], 'B': [11, 12]})  
  
# 使用 append 方法追加多个 DataFrame  
result = df1.append([df2, df3], ignore_index=True)  
  
print(result)
  • 忽略索引
    如果你不想保留原始索引,并希望生成一个新的整数索引,你可以设置 ignore_index=True。
python
result = df1.append(df2, ignore_index=True)
  • 注意事项
    当使用 append() 方法时,如果两个 DataFrame 的列不完全匹配,pandas 会尝试对齐它们。如果某个 DataFrame 中存在另一个 DataFrame 中没有的列,则这些列在结果 DataFrame 中将被填充为 NaN
    如果两个 DataFrame 的列名相同但数据类型不同,pandas 会尝试将它们转换为兼容的数据类型。这可能会导致数据丢失或转换,因此在进行数据追加之前,最好确保两个 DataFrame 的列具有相同的数据类型。
    append() 方法返回一个新的 DataFrame,原始 DataFrame 不会被修改。如果你希望修改原始 DataFrame,你需要将结果重新赋值给原始变量。
    append() 方法在处理大型数据集时可能不是最高效的,因为它涉及到创建一个新的 DataFrame 来存储结果。对于大型数据集,使用 pd.concat() 方法沿着行轴(axis=0)连接可能更为高效

3.merge()

merge() 是 pandas 库中用于合并两个或多个 DataFrame 的方法。这个方法基于一个或多个键(即列)将两个 DataFrame 连接起来,并将它们组合成一个新的 DataFrame。merge() 方法提供了多种合并方式,如内连接(inner join)、左连接(left join)、右连接(right join)和全外连接(outer join)。
Dataframe.merge() 是 pandas 库中用于合并两个或多个 DataFrame 的方法。这个方法基于一个或多个键(即列)将两个 DataFrame 连接起来,并将它们组合成一个新的 DataFrame。merge() 方法提供了多种合并方式,如内连接(inner join)、左连接(left join)、右连接(right join)和全外连接(outer join)。

(1) 基本语法

DataFrame.merge(right, how='inner', on=None, left_on=None, right_on=None,  
                 left_index=False, right_index=False, sort=False,  
                 suffixes=('_x', '_y'), indicator=False,  
                 validate=None)

(1) 参数说明

  • right: 要合并的另一个 DataFrame。
  • how: 合并类型,可选值有:‘left’, ‘right’, ‘outer’, ‘inner’。默认为 ‘inner’。
  • on: 用于合并的列名。必须在两个 DataFrame 中都存在。如果未设置,且 left_on 和 right_on 也未设置,则 pandas 会尝试基于两个 DataFrame 中共有的列名进行合并。
  • left_on: 左侧 DataFrame 中用于合并的列名。
  • right_on: 右侧 DataFrame 中用于合并的列名。
  • left_index: 使用左侧 DataFrame 的索引作为合并的键。默认为 False。
  • right_index: 使用右侧 DataFrame 的索引作为合并的键。默认为 False。
  • suffixes: 一个元组,用于添加到重叠列名的末尾,以区分左右两个 DataFrame 中的列。默认为 (‘_x’, ‘_y’)。
  • indicator: 如果为 True,则添加一个名为 ‘_merge’ 的列到输出 DataFrame 中,该列将包含合并操作的来源信息。
  • validate: 用于检查合并键的字符串,可选值有:“one_to_one”, “one_to_many”, “many_to_one”, “many_to_many”。

(1) 内连接(Inner Join)

当使用内连接时,只有那些在两个 DataFrame 中具有匹配键的行才会出现在结果 DataFrame 中。

import pandas as pd  
  
# 创建两个 DataFrame  
df1 = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'value1': [1, 2, 3, 4]})  
df2 = pd.DataFrame({'key': ['B', 'C', 'D', 'E'], 'value2': [5, 6, 7, 8]})  
  
# 使用 merge 方法进行内连接  
result = df1.merge(df2, on='key')  
  
print(result)

运行结果:
在这里插入图片描述

(2) 左连接(Left Join)

左连接返回左表的所有行,以及右表中匹配的行。如果右表中没有匹配的行,则结果中对应列的值将为 NaN。左连接是 merge() 方法中 how 参数设置为 ‘left’ 时的连接方式。

# 使用 merge 方法进行左连接  
result_left = df1.merge(df2, on='key', how='left')  
  
print(result_left)

运行结果:
在这里插入图片描述

(3) 右连接(Right Join)

右连接返回右表(即 merge() 方法中的第二个 DataFrame)的所有行,以及左表(第一个 DataFrame)中匹配的行。如果左表中没有匹配的行,则结果中对应列的值将为 NaN。

# 使用 merge 方法进行右连接  
result_right = df1.merge(df2, on='key', how='right')  
  
print(result_right)

运行结果:
在这里插入图片描述

(4) 全外连接(Outer Join)

全外连接返回左表和右表中的所有行。如果某一边没有匹配的行,则结果中对应列的值将为 NaN。你可以通过设置 how=‘outer’ 来实现全外连接。

# 使用 merge 方法进行全外连接  
result_outer = df1.merge(df2, on='key', how='outer')  
  
print(result_outer)

运行结果:
在这里插入图片描述

在这些示例中,我们使用了基于 ‘key’ 列的内连接、左连接、右连接和全外连接。注意,当使用外连接时,结果 DataFrame 中可能会包含带有 NaN 值的行,这些行在另一个 DataFrame 中没有匹配项。

merge() 方法非常灵活,允许你根据特定需求定制合并操作。在处理数据时,理解并正确应用不同的合并类型是至关重要的。

3.join()

DataFrame.join() 方法用于将两个 DataFrame 基于一个或多个键进行连接。与 DataFrame.merge() 方法不同,join() 默认使用索引进行连接,而不是基于列的值。但是,join() 也允许你指定一个或多个列作为连接键。

(1) 参数

  • other: DataFrame 或 Series
    要与调用DataFrame进行连接的另一个DataFrame或Series对象。
  • on: str, list of str, or array-like, optional
    用于连接的列名或列名列表。如果未指定且两个对象的索引不同,将使用索引进行连接。如果other是一个Series,并且没有指定on,那么会使用other的索引来匹配DataFrame的索引。
  • how: {‘left’, ‘right’, ‘outer’, ‘inner’}, default ‘left’
    • 连接类型。可选值包括:
    • ‘left’: 使用左侧对象的索引(或on参数指定的列)进行左连接。
    • ‘right’: 使用右侧对象的索引(或on参数指定的列)进行右连接。
    • ‘outer’: 进行全外连接,保留所有对象的索引(或on参数指定的列)。
    • ‘inner’: 进行内连接,只保留在两个对象中都有的索引(或on参数指定的列)。
  • lsuffix: str, default ‘’
    如果连接的DataFrame对象有重名的列,此后缀将添加到左侧对象的列名上,以避免冲突。
  • rsuffix: str, default ‘’
    如果连接的DataFrame对象有重名的列,此后缀将添加到右侧对象的列名上,以避免冲突。
  • keys: sequence, default None
    用于构造层次化索引的列名。如果传递,则长度必须与连接键的数量相等。

(2) 代码实现:

# 创建两个DataFrame  
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2'],  
                    'B': ['B0', 'B1', 'B2']},  
                   index=[0, 1, 2])  
  
df2 = pd.DataFrame({'C': ['C0', 'C2', 'C3'],  
                    'D': ['D0', 'D2', 'D3']},  
                   index=[0, 2, 3])  
  
# 使用索引进行左连接  
result_left = df1.join(df2)  
print(result_left)  
  
# 使用列进行连接(假设df1和df2都有一个名为'key'的列)  
df1['key'] = [0, 1, 2]  
df2['key'] = [0, 2, 3]  
result_on = df1.set_index('key').join(df2.set_index('key'))  
print(result_on)  
  
# 处理重名列  
df3 = pd.DataFrame({'A': [1, 2, 3]}, index=[0, 1, 2])  
result_suffix = df1.join(df3, lsuffix='_caller', rsuffix='_other')  
print(result_suffix)

运行结果:
在这里插入图片描述

二、apply函数(自定义函数操作Dataframe的元素)

apply函数在Pandas库中是一个非常重要的函数,它允许用户将自定义函数应用于DataFrame或Series的行或列上。以下是对apply函数的详细用法说明:

(一)、基本语法

DataFrame.apply(func, axis=0, broadcast=None, raw=False, result_type=None, args=(), **kwds)  
Series.apply(func, convert_dtype=True, args=(), **kwds)

(二)、参数说明

  • func:要应用于每行或每列的函数。这可以是一个Python内置的函数,自定义函数,或者匿名函数(lambda表达式)。
  • axis:指定函数是应用于行还是列。axis=0或axis='index’表示函数应用于每一列,而axis=1或axis='columns’表示函数应用于每一行。默认值是0,即按列操作。
  • raw:布尔值,默认为False。如果为False,则将每行或每列作为Series传递给函数;如果为True,则传递原始的ndarray对象。
  • result_type:{‘expand’, ‘reduce’, ‘broadcast’, None},默认None。这些仅对Series-to-DataFrame或DataFrame-to-Series的转换有效。
  • args和**kwds:传递给函数的其他位置和关键字参数。

(三)、代码实现

1. lambda表达式的应用

当函数逻辑比较简单的时候,可以应用lambda表达式,语法同寻常使用的lambda表达式相同

# 创建一个简单的DataFrame  
data = pd.DataFrame({'A': [-1, 2, -3, 4, -5]})  
  
# 应用函数到列'A'  ,#将小于0的值替换为10,否则替换为0:
data['A'] = data['A'].apply(lambda x: 10 if x < 0 else 0)  
print(data)

运行结果:
在这里插入图片描述

2. 传入自定义函数

  • 应用于列
    当 axis=0 或 axis=‘index’ 时,apply 函数将应用于 DataFrame 的每一列。
    注:当自定义参数为多个时,则在函数名后加 参数名 = 值
    代码如下
# 创建一个简单的 DataFrame  
df = pd.DataFrame({  
    'A': [1, 2, 3],  
    'B': [4, 5, 6],  
    'C': [7, 8, 9]  
})  
  
# 定义一个简单的函数,比如求平方  
def square(x,n):  
    return x ** n  
  
# 将函数应用于每一列  
result = df.apply(square,n=2)  
  
result

运行结果:
在这里插入图片描述

下篇内容

  • 复合索引
  • Dataframe分组语法进阶
  • Dataframe透视表
    敬请期待
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐