我有两个与下面类似的数据框:
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有没有更好的使用链接数据框的方法?
CPU times: total: 516 ms
Wall time: 519 ms
为了提高效率,避免使用 for 循环并加速匹配操作,您可以利用 pandas 的 merge 和 str.contains 方法,结合 apply 进行矢量化处理。这种方法可以避免手动遍历数据框,从而显著提高性能。
for
pandas
merge
str.contains
apply
我们将利用 apply 方法在 df 的 num1 列中匹配 linkage 中的 num1,然后将相应的 num2 值映射到 df 中。
df
num1
linkage
num2
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
df['num1']
linkage['num1']
df['num2']
linkage['num2']
num1 num2 0 2222 A1 1 3333 A2 2 5555 A3 3 8888 A4 4 9999 A5
这种方法将避免循环中逐个查找并填充,而是使用 apply 对数据框进行矢量化处理,通常效率会比手动遍历 for 循环高得多。
如果你的数据非常庞大,str.contains 可以进一步优化为 merge 方法,假设你已经根据 num1 对 linkage 进行了拆分,或者将其转化为一个更高效的数据结构(例如哈希表)。
对于大数据框,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 值的多个匹配项。