基于多列值的重复键的两个大型 Pandas DataFrame 的条件合并/连接 - Python

2024-05-01

我来自 R,老实说,这是使用 R data.tables 在一行中完成的最简单的事情,并且对于大型数据表来说,该操作也相当快。但是我真的很难用Python实现它。前面提到的用例都不适合我的应用程序。当前的主要问题是 Python 解决方案中的内存使用情况,我将在下面解释。

问题:我有两个大型 DataFrame df1 和 df2 (每个大约 50M-100M 行),我需要根据两个条件将 df2 的两列(或 n 列)合并到 df1 :

1) df1.id = df2.id(通常合并的情况)

2) df2.value_2A

import numpy as np
import pandas as pd

df1 = pd.DataFrame({'id': [1,1,1,2,2,3], 'value_1': [2,5,7,1,3,4]})
df2 = pd.DataFrame({'id': [1,1,1,1,2,2,2,3], 'value_2A': [0,3,7,12,0,2,3,1], 'value_2B': [1,5,9,15,1,4,6,3]})

df1
Out[13]: 
   id  value_1
0   1        2
1   1        5
2   1        7
3   2        1
4   2        3
5   3        4

df2
Out[14]: 
   id  value_2A  value_2B
0   1         0         1
1   1         3         5
2   1         7         9
3   1        12        15
4   2         0         1
5   2         2         4
6   2         3         6
7   3         1         3

desired_output
Out[15]: 
   id  value_1  value_2A  value_2B
0   1        2       NaN       NaN
1   1        5       3.0       5.0
2   1        7       7.0       9.0
3   2        1       0.0       1.0
4   2        3       2.0       4.0
5   2        3       3.0       6.0
6   3        4       NaN       NaN

现在,我知道这可以通过首先以“左”方式合并 df1 和 df2 然后过滤数据来完成。但就扩展而言,这是一个可怕的解决方案。我有 50M x 50M 行,其中有多个 id 重复项。这将创建一些巨大的数据框,我必须对其进行过滤。

## This is NOT a solution because memory usage is just too large and 
## too many oprations deeming it extremely inefficient and slow at large scale

output = pd.merge(df1, df2, on='id', how='left')  ## output becomes very large in my case
output.loc[~((output['value_1'] >= output['value_2A']) & (output['value_1'] <= output['value_2B'])), ['value_2A', 'value_2B']] = np.nan
output = output.loc[~ output['value_2A'].isnull()]
output = pd.merge(df1, output, on=['id', 'value_1'], how='left')

这太低效了。我将大型数据集合并两次以获得所需的输出,并在此过程中创建大量数据帧。哎呀!

将其视为事件的两个数据帧,我试图将它们匹配在一起。也就是说,标记 df1 的事件是否已发生在 df2 的事件内。 df1 和 df2 中的每个 id 都有多个事件。 df2 的事件不是相互排斥的。条件连接确实需要在连接时发生,而不是之后。 这在 R 中很容易完成:

## in R realm ##
require(data.table)
desired_output <- df2[df1, on=.(id, value_2A <= value_1, value_2B >= value_1)] #fast and easy operation

有什么方法可以在Python中做到这一点吗?


是的。这是一个烦人的问题。我通过将左侧 DataFrame 分成块来处理这个问题。

def merge_by_chunks(left, right, condition=None, **kwargs):   
    chunk_size = 1000
    merged_chunks = []
    for chunk_start in range(0, len(left), chunk_size):
        print(f"Merged {chunk_start}            ", end="\r")
        merged_chunk = pd.merge(left=left[chunk_start: chunk_start+chunk_size], right=right, **kwargs)
        if condition is not None:
            merged_chunk = merged_chunk[condition(merged_chunk)]
        merged_chunks.append(merged_chunk)
    return pd.concat(merged_chunks)

然后您可以将条件作为函数提供。

df1 = pd.DataFrame({'id': [1,1,1,2,2,3], 'value_1': [2,5,7,1,3,4]})
df2 = pd.DataFrame({'id': [1,1,1,1,2,2,2,3], 'value_2A': [0,3,7,12,0,2,3,1], 'value_2B': [1,5,9,15,1,4,6,3]})

def condition_func(output):
    return (((output['value_1'] >= output['value_2A']) & (output['value_1'] <= output['value_2B'])))

output = merge_by_chunks(df1, df2, condition=condition_func, on='id', how='left')
merge_by_chunks(df1, output, on=['id', 'value_1'], how='left')

根据 DataFrame 的大小,它可能会非常慢,但它不会耗尽内存。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于多列值的重复键的两个大型 Pandas DataFrame 的条件合并/连接 - Python 的相关文章

  • 如何在 Matplotlib 饼图周围绘制箭头以将每个标签指向圆圈中各自的部分?

    我一直在用 Matplotlib 绘制一些图表 我有一个饼图 想要在图表周围绘制箭头 使每个标签都指向图表 我有一个例子 这是我当前的代码 import matplotlib pyplot as plt plt rcParams font
  • 为什么 dataclasses.astuple 返回类属性的深层副本?

    在下面的代码中astuple函数正在执行数据类的类属性的深层复制 为什么它不能产生与函数相同的结果my tuple import copy import dataclasses dataclasses dataclass class Dem
  • 在 Celery 任务中调用 Google Cloud API 永远不会返回

    我正在尝试拨打外部电话Google Cloud Natural Language API从一个内Celery任务 使用google cloud python包裹 问题是对 API 的调用永远不会返回 挂起 celery task def g
  • NLTK 2.0分类器批量分类器方法

    当我运行此代码时 它会抛出一个错误 我认为这是由于 NLTK 3 0 中不存在batch classify 方法 我很好奇如何解决旧版本中的某些内容在新版本中消失的此类问题 def accuracy classifier gold resu
  • Django Rest Framework 是否有第三方应用程序来自动生成 swagger.yaml 文件?

    我有大量的 API 端点编写在django rest framework并且不断增加和更新 如何创建和维护最新的 API 文档 我当前的版本是 Create swagger yaml文件并以某种方式在每次端点更改时自动生成 然后使用此文件作
  • 如何从Python中的函数返回多个值? [复制]

    这个问题在这里已经有答案了 如何从Python中的函数返回多个变量 您可以用逗号分隔要返回的值 def get name you code return first name last name 逗号表示它是一个元组 因此您可以用括号将值括
  • 使用主题交换运行多个 Celery 任务

    我正在用 Celery 替换一些自制代码 但很难复制当前的行为 我期望的行为如下 创建新用户时 应向tasks与交换user created路由键 该消息应该触发两个 Celery 任务 即send user activate email
  • python multiprocessing 设置生成进程等待

    是否可以生成一些进程并将生成进程设置为等待生成的进程完成 下面是我用过的一个例子 import multiprocessing import time import sys def daemon p multiprocessing curr
  • 在 Django Admin 中调整字段大小

    在管理上添加或编辑条目时 Django 倾向于填充水平空间 但在某些情况下 当编辑 8 个字符宽的日期字段或 6 或 8 个字符的 CharField 时 这确实是一种空间浪费 字符宽 然后编辑框最多可容纳 15 或 20 个字符 我如何告
  • Tensorboard SyntaxError:语法无效

    当我尝试制作张量板时 出现语法错误 尽管开源代码我还是无法理解 我尝试搜索张量板的代码 但不清楚 即使我不擅长Python 我这样写路径C Users jh902 Documents logs因为我正在使用 Windows 10 但我不确定
  • 矩形函数的数值傅里叶变换

    本文的目的是通过一个众所周知的分析傅里叶变换示例来正确理解 Python 或 Matlab 上的数值傅里叶变换 为此 我选择矩形函数 这里报告了它的解析表达式及其傅立叶变换https en wikipedia org wiki Rectan
  • Python 3:将字符串转换为变量[重复]

    这个问题在这里已经有答案了 我正在从 txt 文件读取文本 并且需要使用我读取的数据之一作为类实例的变量 class Sports def init self players 0 location name self players pla
  • 导入错误:没有名为flask.ext.login的模块

    我的flask login 模块有问题 我已经成功安装了flask login模块 另外 从命令提示符我可以轻松运行此脚本 不会出现错误 Python 2 7 r27 82525 Jul 4 2010 07 43 08 MSC v 1500
  • 嵌套作用域和 Lambda

    def funct x 4 action lambda n x n return action x funct print x 2 prints 16 我不太明白为什么2会自动分配给n n是返回的匿名函数的参数funct 完全等价的定义fu
  • 如何使用 Python 3 检查目录是否包含文件

    我到处寻找这个答案但找不到 我正在尝试编写一个脚本来搜索特定的子文件夹 然后检查它是否包含任何文件 如果包含 则写出该文件夹的路径 我已经弄清楚了子文件夹搜索部分 但检查文件却难倒了我 我发现了有关如何检查文件夹是否为空的多个建议 并且我尝
  • 在 Google App Engine 中,如何避免创建具有相同属性的重复实体?

    我正在尝试添加一个事务 以避免创建具有相同属性的两个实体 在我的应用程序中 每次看到新的 Google 用户登录时 我都会创建一个新的播放器 当新的 Google 用户在几毫秒内进行多个 json 调用时 我当前的实现偶尔会创建重复的播放器
  • 为什么 csv.DictReader 给我一个无属性错误?

    我的 CSV 文件是 200 Service 我放入解释器的代码是 snav csv DictReader open screennavigation csv delimiter print snav fieldnames 200 for
  • 重新分配唯一值 - pandas DataFrame

    我在尝试着assign unique值在pandas df给特定的个人 For the df below Area and Place 会一起弥补unique不同的价值观jobs 这些值将分配给个人 总体目标是使用尽可能少的个人 诀窍在于这
  • Firebase Firestore:获取文档的生成 ID (Python)

    我可以创建一个新文档 带有自动生成的 ID 并存储对其的引用 如下所示 my data key value doc ref db collection u campaigns add my data 我可以像这样访问数据本身 print d
  • 如何使用 PrimaryKeyRelatedField 更新多对多关系上的类别

    Django Rest 框架有一个主键相关字段 http www django rest framework org api guide relations primarykeyrelatedfield其中列出了我的 IDmany to m

随机推荐