Pandas中的区间交集

6

更新5:

这个功能已经作为pandas 20.1的一部分发布了(在我的生日上:])

更新4:

PR已合并!

更新3:

PR已转移到此处

更新2:

看起来这个问题可能有助于重新打开pandas中IntervalIndex的PR

更新:

我不再遇到这个问题,因为我现在实际上是从AB查询重叠范围,而不是从B中落在A范围内的点,这是一个完整的区间树问题。虽然我没有一个好的答案,但我不会删除这个问题,因为我认为它仍然是一个有效的问题。

问题陈述

我有两个数据帧。

在数据框 A 中,两个整数列组合在一起表示一个区间。
在数据框 B 中,一个整数列表示一个位置。
我想进行一种类似于连接的操作,以便将每个点分配到其所属的区间中。
区间很少但偶尔重叠。如果一个点落在重叠区域内,它应该被分配到两个区间中。大约一半的点不会落在区间内,但几乎每个区间都至少有一个点落在其范围内。

我的想法

我最初打算从pandas中导出我的数据,然后使用intervaltreebanyan或者可能是bx-python,但后来我发现了这个gist。原来shoyer在里面提出的想法从未被纳入到pandas中,但这让我想到了——可能可以在pandas内部完成这个任务,而且由于我希望这段代码尽可能快地运行,所以我不想在最后一刻才从pandas中导出数据。我也有一种感觉,这可以通过bins和pandas的cut函数实现,但我对pandas完全是新手,所以我需要一些指导!谢谢!

注释

可能相关? Pandas DataFrame按变量长度分组重叠间隔


你需要发布你的样本数据框和期望的输出样本。 - Ted Petrou
我该如何发布数据框?它非常宽且高,我感觉已经提供了重要信息。如果您需要具体名称,它们是A.txStartA.txEnd表示区间,B.tss表示点。它们都是相当大的整数。 - Alex Lenail
发布绝对最少的数据,以产生能解决您问题的答案。这意味着您需要使用最少数量的列创建模拟完全与您遇到的情况相同的虚假数据。 - Ted Petrou
2个回答

3

这个功能是作为pandas 20.1的一部分发布的。


请问您能否发布一个链接? - user3521099

2

使用pyranges回答该问题,它基本上是在pandas中添加了生物信息学内容。

设置:

import numpy as np
np.random.seed(0)
import pyranges as pr

a = pr.random(int(1e6))
# +--------------+-----------+-----------+--------------+
# | Chromosome   | Start     | End       | Strand       |
# | (category)   | (int32)   | (int32)   | (category)   |
# |--------------+-----------+-----------+--------------|
# | chr1         | 8830650   | 8830750   | +            |
# | chr1         | 9564361   | 9564461   | +            |
# | chr1         | 44977425  | 44977525  | +            |
# | chr1         | 239741543 | 239741643 | +            |
# | ...          | ...       | ...       | ...          |
# | chrY         | 29437476  | 29437576  | -            |
# | chrY         | 49995298  | 49995398  | -            |
# | chrY         | 50840129  | 50840229  | -            |
# | chrY         | 38069647  | 38069747  | -            |
# +--------------+-----------+-----------+--------------+
# Stranded PyRanges object has 1,000,000 rows and 4 columns from 25 chromosomes.
# For printing, the PyRanges was sorted on Chromosome and Strand.

b = pr.random(int(1e6), length=1)
# +--------------+-----------+-----------+--------------+
# | Chromosome   | Start     | End       | Strand       |
# | (category)   | (int32)   | (int32)   | (category)   |
# |--------------+-----------+-----------+--------------|
# | chr1         | 52110394  | 52110395  | +            |
# | chr1         | 122640219 | 122640220 | +            |
# | chr1         | 162690565 | 162690566 | +            |
# | chr1         | 117198743 | 117198744 | +            |
# | ...          | ...       | ...       | ...          |
# | chrY         | 45169886  | 45169887  | -            |
# | chrY         | 38863683  | 38863684  | -            |
# | chrY         | 28592193  | 28592194  | -            |
# | chrY         | 29441949  | 29441950  | -            |
# +--------------+-----------+-----------+--------------+
# Stranded PyRanges object has 1,000,000 rows and 4 columns from 25 chromosomes.
# For printing, the PyRanges was sorted on Chromosome and Strand.

执行:

result = a.join(b, strandedness="same")
# +--------------+-----------+-----------+--------------+-----------+-----------+--------------+
# | Chromosome   | Start     | End       | Strand       | Start_b   | End_b     | Strand_b     |
# | (category)   | (int32)   | (int32)   | (category)   | (int32)   | (int32)   | (category)   |
# |--------------+-----------+-----------+--------------+-----------+-----------+--------------|
# | chr1         | 227348436 | 227348536 | +            | 227348516 | 227348517 | +            |
# | chr1         | 18901135  | 18901235  | +            | 18901191  | 18901192  | +            |
# | chr1         | 230131576 | 230131676 | +            | 230131636 | 230131637 | +            |
# | chr1         | 84829850  | 84829950  | +            | 84829903  | 84829904  | +            |
# | ...          | ...       | ...       | ...          | ...       | ...       | ...          |
# | chrY         | 44139791  | 44139891  | -            | 44139821  | 44139822  | -            |
# | chrY         | 51689785  | 51689885  | -            | 51689859  | 51689860  | -            |
# | chrY         | 45379140  | 45379240  | -            | 45379215  | 45379216  | -            |
# | chrY         | 37469479  | 37469579  | -            | 37469576  | 37469577  | -            |
# +--------------+-----------+-----------+--------------+-----------+-----------+--------------+
# Stranded PyRanges object has 16,153 rows and 7 columns from 24 chromosomes.
# For printing, the PyRanges was sorted on Chromosome and Strand.

df = result.df
#       Chromosome      Start        End Strand    Start_b      End_b Strand_b
# 0           chr1  227348436  227348536      +  227348516  227348517        +
# 1           chr1   18901135   18901235      +   18901191   18901192        +
# 2           chr1  230131576  230131676      +  230131636  230131637        +
# 3           chr1   84829850   84829950      +   84829903   84829904        +
# 4           chr1  189088140  189088240      +  189088163  189088164        +
# ...          ...        ...        ...    ...        ...        ...      ...
# 16148       chrY   38968068   38968168      -   38968124   38968125        -
# 16149       chrY   44139791   44139891      -   44139821   44139822        -
# 16150       chrY   51689785   51689885      -   51689859   51689860        -
# 16151       chrY   45379140   45379240      -   45379215   45379216        -
# 16152       chrY   37469479   37469579      -   37469576   37469577        -
# 
# [16153 rows x 7 columns]

虽然这并不是对 OP 问题的一般解决方案,但对于某些人来说似乎相当有用,比如我自己:P你能大致说明它是如何工作的吗? - Aku

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接