Python:从元组列表中创建图像的快速方法

时间:2014-01-30 11:24:14

标签: python numpy scipy

我正在做以下事情。

import numpy as np
import pylab

.....

x = np.zeros([250,200])
for tup in tups:
    x[tup[1],tup[0]] = x[tup[1],tup[0]] + 1
pylab.imshow(x)

哪里

tups = [(x1,y1),(x2,y2),....]

xiyi是整数

这适用于积分较少的tup。对于大量的点~10 ^ 6,需要几个小时。

你能想到更快的方法吗?

2 个答案:

答案 0 :(得分:1)

我可以很容易地看到一个小改进,而不是下一个:

for tup in tups:
    x[tup[1],tup[0]] = x[tup[1],tup[0]] + 1

尝试做

for tup in tups:
    x[tup[1],tup[0]] += 1

由于这会覆盖相同的内存地址,而不是创建一个新的内存点来放置'旧值+ 1'(注意:在这种情况下,这可能只会导致边际加速,但是如果你这样做的话技巧A + = B而不是C = A + B,在A和B分别是Gb的numpy ndarrays的情况下,它实际上是一个巨大的加速)

为什么你读作元组的东西?难道你不应该首先尝试将其作为一个numpy ndarray读取,而不是将其作为元组列表读取而不是更改为numpy数组?你在哪里创建那个庞大的元组列表?如果可以避免这种情况,那么只是避免使用元组列表而不是创建它而不是后来交换到一个numpy解决方案会更好吗?

编辑:所以我只是想知道你可以通过+ =得到这个加速,同时问为什么你有一个很大的元组列表,但这太长了,不能把两件事都放在评论中< / p>

另一个问题:我是否正确假设您的元组可以有多个重复?喜欢

tups = [(1,0), (2,4), (1,0), (1,2), ..., (999, 999), (992, 999)]

这样在你的结果中,除了0和1之外还会存在其他值吗?或者是你的结果数组中只存在1和0的东西?

答案 1 :(得分:1)

使用numpy,您可以将您的索引对转换为平面索引并对其进行bincount:

import numpy as np
import random

rows, cols = 250, 200
n = 1000

tups = [(random.randint(0, rows-1),
         random.randint(0, cols-1)) for _ in range(n)]

x = np.zeros((rows, cols))
for tup in tups:
    x[tup[0],tup[1]] += 1

flat_idx = np.ravel_multi_index(zip(*tups), (rows, cols))
y = np.bincount(flat_idx, minlength=rows*cols).reshape(rows, cols)

np.testing.assert_equal(x, y)

它将比任何循环解决方案快得多。