Python 中更快的 PyRanges 生成

Faster PyRanges Generation in Python

我有一个起始坐标列表,所有这些坐标都在同一染色体上,用于固定大小的特征,我正在尝试生成一个 PyRanges 对象。

我在一个包含 125 个坐标的列表上对 PyRanges 对象的生成进行了计时,它花费了大约 3.5 毫秒。这似乎比预期的要慢(这是我第一次使用这个库)所以我尝试在不同大小的列表上测量相同进程的速度

这些是性能测试的结果:

N = 1: 3.03ms
N = 10: 2.96ms
N = 100: 3.33ms
N = 125: 3.24ms
N = 200: 3.11ms
N = 500: 3.12ms
N = 10000: 6.86ms
N = 100000: 32.6ms

看起来创建 PyRanges 对象需要一个基本时间(N = 1,它仍然需要一些时间)然后,虽然时间似乎取决于特征的数量,但关系似乎并不太激烈。事实上,创建一个包含 10000 个项目的 PyRanges 对象只需要创建一个只有 10 个项目的 2 倍的时间。

这是我正在使用的代码:

chr = "chrX"
size = 10
N = 1
points = np.array([random.randint(0, 1000000) for i in range(N)])

genomic_range = pr.PyRanges(
                chromosomes= chr,
                starts = points,
                ends = points + size - 1
            )

我是不是做错了什么? 为什么 PyRange 的生成需要这个时间,即使是很少的项目?

简而言之,PyRanges 在内部使用 Pandas,这对于小输入来说非常慢


您的函数调用进入 _init which calls create_pyranges_df,它本身执行以下行:

chromosomes = pd.Series([chromosomes] * len(starts), dtype="category")

这条线在我的机器上需要 0.25 毫秒,这对于如此小的输入来说非常慢(我预计这至少要快 100 倍)。 dtype="category" 似乎是它慢的原因。

代码最慢的部分位于here:

for s in columns:
    if isinstance(s, pd.Series):
        s = pd.Series(s.values, index=idx)  # This line is executed several time
    else:
        s = pd.Series(s, index=idx)

    series_to_concat.append(s)

有 10 列和 ~0.2 毫秒来创建每个 pd.Series 对象导致 ~2 毫秒几乎什么都不做...