当前位置: 首页 > 面试题库 >

在pandas中按范围加入/合并的最佳方法

霍财
2023-03-14
问题内容

我经常通过使用范围条件将熊猫用于合并(联接)。

例如,如果有2个数据框:

A (A_id,A_value)

B (B_id,B_low,B_high,B_name)

它们很大,大小大致相同(假设每个记录有2M条)。

我想在A和B之间进行内部联接,因此A_value将在B_low和B_high之间。

使用SQL语法将是:

SELECT *
FROM A,B
WHERE A_value between B_low and B_high

那真的很容易,简短而有效。

同时,在熊猫中,唯一的方法(不使用我发现的循环)是通过在两个表中创建一个虚拟列,对其进行联接(等同于交叉联接),然后过滤掉不需要的行。这听起来很繁复:

A['dummy'] = 1
B['dummy'] = 1
Temp = pd.merge(A,B,on='dummy')
Result = Temp[Temp.A_value.between(Temp.B_low,Temp.B_high)]

我所拥有的另一种解决方案是通过使用B[(x>=B.B_low) & (x<=B.B_high)]掩码在A值上的每个值上应用B上的搜索功能,但这听起来效率也不高,可能需要优化索引。

有没有更优雅和/或更有效的方法来执行此操作?


问题答案:

设置
考虑数据帧AB

A = pd.DataFrame(dict(
        A_id=range(10),
        A_value=range(5, 105, 10)
    ))
B = pd.DataFrame(dict(
        B_id=range(5),
        B_low=[0, 30, 30, 46, 84],
        B_high=[10, 40, 50, 54, 84]
    ))

A

   A_id  A_value
0     0        5
1     1       15
2     2       25
3     3       35
4     4       45
5     5       55
6     6       65
7     7       75
8     8       85
9     9       95

B

   B_high  B_id  B_low
0      10     0      0
1      40     1     30
2      50     2     30
3      54     3     46
4      84     4     84

numpy
简单的 方法是使用numpy广播。
我们找的每一个实例A_value大于或等于B_low,而在同一时间A_value小于或等于B_high

a = A.A_value.values
bh = B.B_high.values
bl = B.B_low.values

i, j = np.where((a[:, None] >= bl) & (a[:, None] <= bh))

pd.DataFrame(
    np.column_stack([A.values[i], B.values[j]]),
    columns=A.columns.append(B.columns)
)

   A_id  A_value  B_high  B_id  B_low
0     0        5      10     0      0
1     3       35      40     1     30
2     3       35      50     2     30
3     4       45      50     2     30

为了解决评论并提供类似于左联接的内容,我添加A不匹配的部分。

pd.DataFrame(
    np.column_stack([A.values[i], B.values[j]]),
    columns=A.columns.append(B.columns)
).append(
    A[~np.in1d(np.arange(len(A)), np.unique(i))],
    ignore_index=True, sort=False
)

    A_id  A_value  B_id  B_low  B_high
0      0        5   0.0    0.0    10.0
1      3       35   1.0   30.0    40.0
2      3       35   2.0   30.0    50.0
3      4       45   2.0   30.0    50.0
4      1       15   NaN    NaN     NaN
5      2       25   NaN    NaN     NaN
6      5       55   NaN    NaN     NaN
7      6       65   NaN    NaN     NaN
8      7       75   NaN    NaN     NaN
9      8       85   NaN    NaN     NaN
10     9       95   NaN    NaN     NaN


 类似资料:
  • 问题内容: 假设我有两个这样的DataFrame: 我想合并它们,所以我尝试这样的事情: 我很开心 但是我正在尝试使用join方法,我被认为这是非常相似的。 我得到这个: 我想念什么? 问题答案: 我总是在索引上使用: 通过在以下各列上使用,可以具有相同的功能:

  • 在我的Java web应用程序中,我确实生成了一个报告,每个客户都检测到一个页面。 我已经创建了一个JasperReport,如果客户列表超过1个,我想连接生成的报告。 这是我的代码: 我想获取合并的PDF,但我找不到在ByteArrayOutputStream中导出JasperPrint列表的功能。 有什么建议吗?

  • 问题内容: 我有一个像这样的模板: 我得到下面的输出: 我想渲染如下: 我无法摆脱最后一个逗号来制作有效的json。还是可能以某种方式将完整的范围块发送到某些自定义联接功能? 问题答案: 这是一个如何使用模板的示例,但是如果要生成JSON,我强烈建议使用第二种方法。 坚持使用模板 由于您在地图上范围很广,因此您无法(简单地)做到这一点。如果是切片,则可以检查index变量(例如:Go模板除去ran

  • 我是Android Native编码(Kotlin / Jetpack Compose)的新手,在AS3移动应用程序编码(OOP)方面有着悠久的背景。我喜欢遵循相同的路径,并将可组合代码分解为更小的块,OOP,使其易于维护。 例如,这是主活动: 并撰写主页: 文件夹结构 问题: 我是否可以/应该在主可组合项(即MakeHome)中分配变量,然后从子可组合项访问这些变量 例如,在MakeHomeBd

  • 问题内容: 问题答案: Mysql作为关键字的分隔符使用反引号“`”,而不是方括号(例如sql server)

  • 问题内容: 我有一个带有4列的(example-)数据框: 我现在想将B,C和D列合并/合并到新的E列,如本例所示: 我在这里发现了一个非常类似的问题,但这在A列的末尾添加了合并的列B,C和D: 感谢帮助。 问题答案: 选项1 使用和 选项2 使用分配和 选项3 最近,我喜欢第3个选项。 使用