Python NumPy 数组

2 投票
5 回答
13537 浏览
提问于 2025-04-16 21:26

我正在处理两个数组,想把它们当作一个二维数组来用。我使用了很多NumPy的向量化计算。有没有人知道我该如何填充这样的数组:

X = [1, 2, 3, 1, 2, 3, 1, 2, 3]

或者:

X = [0.2, 0.4, 0.6, 0.8, 0.2, 0.4, 0.6, 0.8, 0.2, 0.4, 0.6, 0.8, 0.2, 0.4, 0.6, 0.8]

可以忽略消息的第一部分。

我需要把两个数组填充成一个网格的形式。但是网格的大小是根据用户的需求变化的,所以我需要一个通用的形式。我今天早上一直在研究这个,最后终于得到了我想要的结果。

如果之前造成了任何困惑,我很抱歉。我的英语不是母语,有时候我很难解释清楚事情。

这是我用来完成这个工作的代码:

    myIter = linspace(1, N, N)
    for x in myIter:
        for y in myIter:
            index = ((x - 1)*N + y) - 1
            X[index] = x / (N+1)
            Y[index] = y / (N+1)

用户输入N。X和Y的长度都是N*N。

5 个回答

1

如果你想创建一些重复值的列表,可以用列表或元组的乘法来实现...

>>> import numpy
>>> numpy.array((1, 2, 3) * 3)
array([1, 2, 3, 1, 2, 3, 1, 2, 3])
>>> numpy.array((0.2, 0.4, 0.6, 0.8) * 3).reshape((3, 4))
array([[ 0.2,  0.4,  0.6,  0.8],
       [ 0.2,  0.4,  0.6,  0.8],
       [ 0.2,  0.4,  0.6,  0.8]])

感谢你更新了问题,现在更清楚了。虽然我觉得joris的回答在这种情况下是最好的(因为更容易理解),但我想指出你新发布的代码也可以这样通用化:

>>> arr = numpy.arange(1, N + 1) / (N + 1.0)
>>> X = arr[numpy.indices((N, N))[0]].flatten()
>>> Y = arr[numpy.indices((N, N))[1]].flatten()

在很多情况下,使用numpy时,可以通过numpy强大的索引系统来避免使用while循环。一般来说,当你用数组I去索引数组A时,结果会是一个和I形状相同的数组J。对于I中的每个索引iA[i]的值会被赋给J中对应的位置。例如,假设你有arr = numpy.arange(0, 9) / (9.0),你想要索引358的值。你只需要用numpy.array([3, 5, 8])作为arr的索引:

>>> arr
array([ 0.        ,  0.11111111,  0.22222222,  0.33333333,  0.44444444,
        0.55555556,  0.66666667,  0.77777778,  0.88888889])
>>> arr[numpy.array([3, 5, 8])]
array([ 0.33333333,  0.55555556,  0.88888889])

如果你想要一个二维数组呢?只需传入一个二维索引:

>>> arr[numpy.array([[1,1,1],[2,2,2],[3,3,3]])]
array([[ 0.11111111,  0.11111111,  0.11111111],
       [ 0.22222222,  0.22222222,  0.22222222],
       [ 0.33333333,  0.33333333,  0.33333333]])

>>> arr[numpy.array([[1,2,3],[1,2,3],[1,2,3]])]
array([[ 0.11111111,  0.22222222,  0.33333333],
       [ 0.11111111,  0.22222222,  0.33333333],
       [ 0.11111111,  0.22222222,  0.33333333]])

因为你不想总是手动输入这些索引,所以可以用numpy.indices来自动生成它们:

>>> numpy.indices((3, 3))
array([[[0, 0, 0],
        [1, 1, 1],
        [2, 2, 2]],

       [[0, 1, 2],
        [0, 1, 2],
        [0, 1, 2]]])

总之,这就是上面代码的工作原理。(另外还可以看看numpy.mgridnumpy.ogrid,它们提供了稍微灵活一些的索引生成器。)

由于许多numpy操作都是向量化的(也就是说,它们会应用到数组中的每个元素),你只需要找到合适的索引来完成任务——不需要使用循环。

1
print numpy.array(range(1, 4) * 3)
print numpy.array(range(1, 5) * 4).astype(float) * 2 / 10

当然可以!请把你想要翻译的内容发给我,我会帮你把它变得简单易懂。

11

你可以使用一个叫做 tile 的函数。下面是一些例子:

>>> a = np.array([0, 1, 2])
>>> np.tile(a, 2)
array([0, 1, 2, 0, 1, 2])

通过这个函数,你还可以一次性改变数组的形状,就像其他回答中提到的使用 reshape 方法一样(通过定义 'repeats' 来表示更多的维度):

>>> np.tile(a, (2, 1))
array([[0, 1, 2],
       [0, 1, 2]])

补充说明:这里还简单比较了一下内置函数 tile 和直接相乘的速度差异:

In [3]: %timeit numpy.array([1, 2, 3]* 3)
100000 loops, best of 3: 16.3 us per loop
In [4]: %timeit numpy.tile(numpy.array([1, 2, 3]), 3)
10000 loops, best of 3: 37 us per loop

In [5]: %timeit numpy.array([1, 2, 3]* 1000)
1000 loops, best of 3: 1.85 ms per loop
In [6]: %timeit numpy.tile(numpy.array([1, 2, 3]), 1000)
10000 loops, best of 3: 122 us per loop 

编辑

你在问题中给出的代码输出也可以通过以下方式实现:

arr = myIter / (N + 1)
X = numpy.repeat(arr, N)
Y = numpy.tile(arr, N)

这样你就可以避免对数组进行循环(这也是使用 numpy 的一个大优点)。最终的代码更简单(当然前提是你知道这些函数,具体可以查看 repeattile 的文档)而且运行速度更快。

撰写回答