此操作需要尽可能快地应用为包含数百万个元素的实际数组。这是问题的简单版本。
所以,我有一个随机的唯一整数数组(通常是数百万个元素)。
totalIDs = [5,4,3,1,2,9,7,6,8 ...]
我有另一个数组(通常是成千上万)独特的整数,我可以创建一个掩码。
subsampleIDs1 = [5,1,9]
subsampleIDs2 = [3,7,8]
subsampleIDs3 = [2,6,9]
...
我可以使用numpy来做
mask = np.in1d(totalIDs,subsampleIDs,assume_unique = True)
然后我可以使用掩码提取我想要的另一个数组的信息(比如第0列包含我想要的那个)。
variable = allvariables [mask] [:,0]
现在假设两个数组中的ID都是唯一的,有没有办法显着提高速度。构建与数百万个ID(totalIDs)匹配的几千个点(subsampleIDs)的掩码需要很长时间。
我想过要经历一次并写出一个索引的二进制文件(以加快未来的搜索)。
for i in range(0,3):
mask = np.in1d(totalIDs,subsampleIDs,assume_unique=True)
index[mask] = i
其中X在subsampleIDsX中。然后我可以这样做:
for i in range(0,3):
if index[i] == i:
rowmatch = i
break
variable = allvariables[rowmatch:len(subsampleIDs),0]
正确?但这也很慢,因为循环中有一个条件可以找到它第一次匹配的时间。有没有更快的方法来查找数字首次出现在有序数组中,因此条件不会减慢循环?
答案 0 :(得分:3)
我建议你在Pandas中使用DataFrame。 DataFrame的索引是totalID,您可以通过以下方式选择subsampleID:df.ix[subsampleIDs]
。
首先创建一些测试数据:
import numpy as np
N = 2000000
M = 5000
totalIDs = np.random.randint(0, 10000000, N)
totalIDs = np.unique(totalIDs)
np.random.shuffle(totalIDs)
v1 = np.random.rand(len(totalIDs))
v2 = np.random.rand(len(totalIDs))
subsampleIDs = np.random.choice(totalIDs, M)
subsampleIDs = np.unique(subsampleIDs)
np.random.shuffle(subsampleIDs)
然后将数据转换为DataFrame:
import pandas as pd
df = pd.DataFrame(data = {"v1":v1, "v2":v2}, index=totalIDs)
df.ix[subsampleIDs]
DataFrame使用哈希表将索引映射到它的位置,速度非常快。
答案 1 :(得分:1)
这种索引通常最好使用DB(具有适当的列索引)来执行。
另一个想法是将totalIDs
排序一次,作为预处理阶段,并实现您自己的in1d
版本,这样可以避免对所有内容进行排序。 in1d
的numpy实现(至少在我安装的版本中)非常简单,并且应该易于复制和修改。
编辑:
或者,更好的是,使用桶排序(或基数排序)。这应该给你O(N + M),N是totalIDs
的大小,M是sampleIDs
的大小(通过改变桶的数量你可以玩的常数的倍数)。在这里,你可以只将totalIDs
拆分为一个桶,这样就可以得到一个漂亮的O(N + M1 + M2 + ...)。
不幸的是,我不知道一个笨拙的实现,但我确实找到了这个:http://en.wikipedia.org/wiki/Radix_sort#Example_in_Python