查找大型键集:字典与NumPy数组

时间:2016-04-15 16:37:33

标签: python arrays numpy dictionary iteration

我有一组非常大的(200k +)键/值对,我需要检索非常大(有时是全部)的值。显而易见的方法是使用字典

 values = {lookup.get(key) for key in key_set}

这在我的代码中变得非常耗时,我想知道是否有更快的方法来实现NumPy数组。我一直在尝试使用包含两列和n行的数组,以便对任何单独的键使用:

value = lookup_array[lookup_array[:,0] == key, 1]

但我不知道如何在没有昂贵的迭代的情况下将其扩展到许多密钥。我看过了:

values = lookup_array[np.in1d(lookup_array[:,0], key_set), 1]

但这似乎也很耗时。

有没有其他方法可以快速大量查找非连续值而无需迭代?

3 个答案:

答案 0 :(得分:3)

如果某些特殊条件适用,您可以使用NumPy索引作为字典查找的快速替代方法。

  • 键必须是整数

  • 你有足够的内存来创建一个NumPy数组,其大小与 您希望查找的最大键值(以便所有键对应于数组中的有效索引。)

想法是使用

lookup_array = np.empty((M,), dtype=values.dtype)
lookup_array[keys] = values
result = lookup_array[key_set]

而不是

result = {lookup_dict.get(key) for key in key_set}

例如,

import numpy as np
import pandas as pd

def using_dict(lookup_dict, key_set):
    return {lookup_dict.get(key) for key in key_set}

def using_array(lookup_array, key_set):
    return lookup_array[key_set]

def using_pandas(df, key_set):
    return df.loc[df['a'].isin(key_set)]

M = 10**6
N = 2*10**5
K = 10**4
keys = np.random.randint(M, size=(N,))
values = np.random.random((N,))
lookup_dict = dict(zip(keys, values))
lookup_array = np.empty((M,), dtype=values.dtype)
lookup_array[keys] = values
df = pd.DataFrame(np.column_stack([keys, values]), columns=list('ab'))
key_set = np.random.choice(keys, size=(K,))

这是上述方法的时间基准(使用IPython):

In [25]: %timeit using_array(lookup_array, key_set)
10000 loops, best of 3: 22.4 µs per loop

In [26]: %timeit using_dict(lookup_dict, key_set)
100 loops, best of 3: 3.73 ms per loop

In [24]: %timeit using_pandas(df, key_set)
10 loops, best of 3: 38.9 ms per loop

答案 1 :(得分:3)

这是np.searchsorted -

的方法
lookup_array

这假定np.searchsorted的键在第一列中排序。如果不是这种情况,您可以将可选的分拣机参数与return render(request,"home.html") 一起使用。

答案 2 :(得分:0)

加载字典这个庞大的内存有点不好,然后增加了查找的开销。如果这是一个数据结构,那么您经常使用数据库引擎。如果你不喜欢SQL,有KEY / VALUE数据库。它们针对查找进行了高度优化。