如何在另一个更大的数组(6 亿个元素)中查找一个大数组(100 万个元素)的元素

How to find elements of a large (1 million elements) array in another larger array (600 million elements)

我有一个非常大的文件(包含 dbSNP ID),包含 100 万行,每行包含一个字符串,另一个更大的文件 (.vcf) 包含 6 亿行,每行包含 7-8 列。

我想找到小文件每一行在大文件中的第一次出现,使我的程序的暴力破解复杂度为 1,000,000 * 600,000,000 次。我想要一种更快、内存占用更少的方法来执行此操作。我是 python 中的多处理或并行编程的新手,我不确定如何在不使用任何一个的情况下解决这个问题。

我已经尝试使用 numpypandas 库对两个文件的较小子集执行类似的操作:

import numpy as np
import pandas as pd

BigFile = pd.Series(arrayOfRowsOfBiggerFile)
SmallFile = pd.Series(arrayOfRowsOfSmallerFile)
FinalList = SmallFile.map(lambda x: np.where(A==x)[0][0]).tolist()

这需要很长时间才能执行,我相信 python 多处理可以很好地处理。

如果我没理解错的话,您实际上是在执行 join 操作:您想要 VCF 中的所有行,其键(在本例中为 RSID)出现在您的 "smaller" 文件中。请在此处查看文档:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.join.html

你的代码看起来像这样:

dbsnp = pd.read_csv('path/to/dbsnp', index_col='rsid', ...)
rsids_of_interest = pd.read_csv('path/to/smaller_file', ...)

subset_of_dbsnp = dbsnp.join(rsids_of_interest, how='inner', ...)

假设您只想根据变体列表提取 .vcf 文件的子集,您可以

(1) 使用@OronNavon 建议的解决方案。它至少应该适用于较小的文件。对于更大的文件大小,它可能需要大量的计算资源,如果您可以访问集群,这就不一定是个问题。如果您 运行 在家用 PC 上安装它,您可能 运行 内存不足。您可以通过即时读取文件来解决它,但它仍然是一个缓慢的过程。此外,您可能会丢失所有 meta-data 的 .vcf header,因此如果您需要它(或 .vcf 功能),您应该单独添加它。

(2) 将 .vcf 文件拆分成块,如果需要,您可以 运行 并行。尽管它不会像它可能的那样有效,因为您只有 rsID 而不是较小文件中的位置。

(3) 使用 Plink 这是一个独立的包,但它可以完成工作 swiftly/efficiently。 (这就是我会做的。)