Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用这个使用Numpy构建的集合字典来提高性能?_Python_Numpy_Dictionary_Set_Hashtable - Fatal编程技术网

Python 如何使用这个使用Numpy构建的集合字典来提高性能?

Python 如何使用这个使用Numpy构建的集合字典来提高性能?,python,numpy,dictionary,set,hashtable,Python,Numpy,Dictionary,Set,Hashtable,假设我们有1000万只袜子,每只袜子都有颜色sockcolor[i],存储在drawer[i]中。 我想数一数这20个抽屉里每一个都有多少种不同的颜色 为此,我使用了一个包含集合的字典(集合在引擎盖下使用了一个哈希表,可以方便地计算唯一的元素) 下面的代码可以工作,但速度相当慢(对于1000万只袜子来说大约10秒) 我们如何使用Numpy技术(矢量化?)或避免for循环来加速此计算? import numpy as np N = 10*1000*1000 drawer = np.random.r

假设我们有1000万只袜子,每只袜子都有颜色
sockcolor[i]
,存储在
drawer[i]
中。 我想数一数这20个抽屉里每一个都有多少种不同的颜色

为此,我使用了一个包含集合的字典(集合在引擎盖下使用了一个哈希表,可以方便地计算唯一的元素)

下面的代码可以工作,但速度相当慢(对于1000万只袜子来说大约10秒)

我们如何使用Numpy技术(矢量化?)或避免
for
循环来加速此计算?

import numpy as np
N = 10*1000*1000
drawer = np.random.randint(0, 20, N)            # 20 drawers
sockcolor = np.random.randint(0, 100*1000, N)   # 100k different colors
d = {}

for i, k in enumerate(drawer):
    if k not in d:  # can be simplified with collections.defaultdict but no gain here
        d[k] = set()
    d[k].add(sockcolor[i])

for k, s in d.items():
    print(k, len(s))
输出:

16 99323
7 99330
0 99339
17 99364
14 99272
12 99303
11 99334
6 99362
19 99287
10 99282
4 99280
18 99325
3 99316
15 99303
5 99280
13 99357
2 99328
9 99290
1 99293
8 99293

你的慢是因为没有使用序列的内置功能。仅对单个袜子重复一次。相反,为抽屉指定袜子颜色(而不是单个袜子的索引)。然后根据每个抽屉的内容制作一个集合:一个批发操作,而不是一个增量的
集合。添加
,这对于您的目的来说是相对缓慢的。

您的缓慢是因为没有使用序列的内置功能。仅对单个袜子重复一次。相反,为抽屉指定袜子颜色(而不是单个袜子的索引)。然后从每个抽屉的内容中创建一个集合:一个批发操作,而不是一个增量的
集合。添加
,这对于您的目的来说相对较慢。

您基本上已经有了从抽屉到袜子颜色的映射,但它们是随机的,您希望按抽屉编号来组织它们

最简单的方法是首先按抽屉编号对它们进行排序:

drawer_sort = np.argsort(drawer)
drawer = drawer[drawer_sort]
sockcolor = sockcolor[drawer_sort]
现在它们已排序,无需查找抽屉编号重复项,您只需找到抽屉编号更改的索引,以形成范围,即:

changes, = np.where(drawer[1:]-drawer[:-1])
starts = np.concatenate([[0], changes+1])
ends = np.concatenate([changes, [len(drawer)]])
现在,您可以创建字典:

result = {drawer[start]: sockcolor[start:end] for start, end in zip(starts, ends)}
这样,在Python中完成的唯一迭代就是最后一行,如果有少量不同的
drawer
值(在您的例子中不超过20),那么这将非常快

结果仍然可以有重复的
sockcolor
值,但这在numpy中很容易解决:

result = {drawer: np.unique(sockcolors) for drawer, sockcolors in result.items()}

基本上你已经有了从抽屉到袜子颜色的映射,但它们是随机的,你想按抽屉编号来组织它们

最简单的方法是首先按抽屉编号对它们进行排序:

drawer_sort = np.argsort(drawer)
drawer = drawer[drawer_sort]
sockcolor = sockcolor[drawer_sort]
现在它们已排序,无需查找抽屉编号重复项,您只需找到抽屉编号更改的索引,以形成范围,即:

changes, = np.where(drawer[1:]-drawer[:-1])
starts = np.concatenate([[0], changes+1])
ends = np.concatenate([changes, [len(drawer)]])
现在,您可以创建字典:

result = {drawer[start]: sockcolor[start:end] for start, end in zip(starts, ends)}
这样,在Python中完成的唯一迭代就是最后一行,如果有少量不同的
drawer
值(在您的例子中不超过20),那么这将非常快

结果仍然可以有重复的
sockcolor
值,但这在numpy中很容易解决:

result = {drawer: np.unique(sockcolors) for drawer, sockcolors in result.items()}

numpy
不适用于集合和字典。你不能用一个简单的向量来组织你的数据吗?@zvone这里的集合被用作重复数据消除的工具,但是为什么要使用
numpy
?这里没有什么真正的好处。@zvone因为我的数据在我的实际用例中来自numpy数组,所以我希望避免将其转换为常规python列表,因为它不会添加任何内容。
numpy
不适用于集合和字典。你不能用一个简单的向量来组织你的数据吗?@zvone这里的集合被用作重复数据消除的工具,但是为什么要使用
numpy
?这里并没有真正的好处。@zvone,因为我的数据来自实际用例中的numpy数组,所以我希望避免将其转换为常规python列表,因为它不会添加任何内容。