小能豆

将链接数据框与其他数据框一起使用的更快方法-Python

py

我有两个与下面类似的数据框:

import pandas as pd

num1 = ["1111 2222", "3333", "4444 5555 6666", "7777 8888", "9999"]
num2 = ["A1", "A2", "A3", "A4", "A5"] 
linkage = pd.DataFrame({"num1":num1, "num2":num2})
num1 = ["2222", "3333", "5555", "8888", "9999"]
num2 = ['none', 'none', 'none', 'none', 'none']
df = pd.DataFrame({"num1":num1, "num2":num2})

连锁:

num1            num2 
1111 2222       A1 
3333            A2 
4444 5555 6666  A3 
7777 8888       A4 
9999            A5 

数据:

num1   num2
2222   none
3333   none
5555   none
8888   none
9999   none

我想根据第二个数据框中的“num1”值是否是链接数据框中的“num1”值之一,将链接数据框中的“num2”值放置在第二个数据框中。我目前拥有的代码是:

df.num2 = [linkage.num2[i] for y in df.num1 for i, x in enumerate(linkage.num1) if y in x]

这就是我想要的:

num1   num2
2222   A1
3333   A2
5555   A3
8888   A4
9999   A5

但是数据框越大,代码运行速度就越慢。CPU times: total: 516 ms Wall time: 519 ms有没有更好的使用链接数据框的方法?


阅读 5

收藏
2024-11-20

共1个答案

小能豆

为了提高效率,避免使用 for 循环并加速匹配操作,您可以利用 pandasmergestr.contains 方法,结合 apply 进行矢量化处理。这种方法可以避免手动遍历数据框,从而显著提高性能。

优化方案

我们将利用 apply 方法在 dfnum1 列中匹配 linkage 中的 num1,然后将相应的 num2 值映射到 df 中。

优化后的代码:

import pandas as pd

# 创建数据框
num1 = ["1111 2222", "3333", "4444 5555 6666", "7777 8888", "9999"]
num2 = ["A1", "A2", "A3", "A4", "A5"]
linkage = pd.DataFrame({"num1": num1, "num2": num2})

num1 = ["2222", "3333", "5555", "8888", "9999"]
num2 = ['none', 'none', 'none', 'none', 'none']
df = pd.DataFrame({"num1": num1, "num2": num2})

# 定义函数:根据df中的num1值查找linkage中的num2
def get_num2_from_linkage(x):
    # 遍历linkage,检查num1是否包含x,返回对应的num2
    for i, linkage_row in linkage.iterrows():
        if str(x) in linkage_row['num1']:
            return linkage_row['num2']
    return 'none'  # 如果没有匹配的值,返回默认值

# 使用apply应用函数
df['num2'] = df['num1'].apply(get_num2_from_linkage)

# 打印结果
print(df)

解释:

  • 我们定义了一个 get_num2_from_linkage 函数,用来遍历 linkage 数据框,检查 df['num1'] 中的每个值是否包含在 linkage['num1'] 的字符串中。
  • apply 函数将 get_num2_from_linkage 应用到 df['num1'] 上,从而填充 df['num2']
  • 对于每个 df['num1'] 中的值,函数会返回相应的 linkage['num2'] 值。

输出结果:

    num1 num2
0   2222   A1
1   3333   A2
2   5555   A3
3   8888   A4
4   9999   A5

性能优化:

这种方法将避免循环中逐个查找并填充,而是使用 apply 对数据框进行矢量化处理,通常效率会比手动遍历 for 循环高得多。

如果你的数据非常庞大,str.contains 可以进一步优化为 merge 方法,假设你已经根据 num1linkage 进行了拆分,或者将其转化为一个更高效的数据结构(例如哈希表)。

使用 merge 优化(如果数据量极大时):

对于大数据框,merge 操作可能会更有效。你可以将 linkage 中的 num1 列拆分成单独的行来实现一个高效的联接。

# 拆分linkage['num1']中的多个值,生成新的行
linkage_expanded = linkage.set_index('num1').apply(lambda row: row.num2.split(' '), axis=1).explode().reset_index()
linkage_expanded.columns = ['num1', 'num2']

# 通过merge连接
df = df.merge(linkage_expanded, on='num1', how='left')

# 打印结果
print(df)

这种方法会通过 merge 操作高效地将匹配的值放入 df 中,同时处理每个 num1 值的多个匹配项。

2024-11-20