如何使用另一个numpy数组填充numpy数组

8
我有一个空的numpy数组,还有另一个填充了值的数组。我想将空的numpy数组用填充后的数组填充x次。
当x = 3时,最初的空数组看起来像[[populated_array],[populated_array], [populated_array]] 其中populated_array每次都是相同的值/数组。
我尝试过这个:
a = np.empty(3)
a.fill(np.array([4,6,6,1]))

但是要注意,以下内容非常重要。
ValueError: Input object to FillWithScalar is not a scalar

and want this

[[4,6,6,1],[4,6,6,1],[4,6,6,1]]

感谢任何帮助。


您可以初始化对象数据类型数组: a = np.empty(3,dtype=object) - Divakar
6个回答

10

tilerepeat是在需要以不同方式重复一个数组时非常方便的函数:

In [233]: np.tile(np.array([4,6,6,1]),(3,1))
Out[233]: 
array([[4, 6, 6, 1],
       [4, 6, 6, 1],
       [4, 6, 6, 1]])
在处理失败时,请注意fill的文档注释:
a.fill(value)

Fill the array with a scalar value.

np.array([4,6,6,1]) 不是一个标量值。 a 被初始化为一个包含 3 个元素的 float 数组。

只要形状正确,可以对数组的元素赋值:

In [241]: a=np.empty(3)
In [242]: a[:]=np.array([1,2,3])    # 3 numbers into 3 slots
In [243]: a
Out[243]: array([ 1.,  2.,  3.])
In [244]: a=np.empty((3,4))
In [245]: a[:]=np.array([1,2,3,4])   # 4 numbers into 4 columns
In [246]: a
Out[246]: 
array([[ 1.,  2.,  3.,  4.],
       [ 1.,  2.,  3.,  4.],
       [ 1.,  2.,  3.,  4.]])

这个 fill 方法适用于对象类型的数组,但结果相当不同,应该谨慎使用:

In [247]: a=np.empty(3, object)
In [248]: a
Out[248]: array([None, None, None], dtype=object)
In [249]: a.fill(np.array([1,2,3,4]))
In [250]: a
Out[250]: array([array([1, 2, 3, 4]), array([1, 2, 3, 4]), array([1, 2, 3, 4])], dtype=object)

这个形状为(3,)的数组与其他方法生成的形状为(3,4)的数组不同。对象数组的每个元素都是指向同一对象的指针。更改a中一个元素的值会改变所有元素中的该值(因为它们是同一对象)。

In [251]: a[0][3]=5
In [252]: a
Out[252]: array([array([1, 2, 3, 5]), array([1, 2, 3, 5]), array([1, 2, 3, 5])], dtype=object)

2
我曾经认为应该有一个快捷方式来完成这个操作。另一方面,如果您能有效地使用广播和索引技巧,大多数情况下您不需要扩展数组,因此提供一个快捷方式似乎有些愚蠢... - mgilson
np.tile 可能是对 MATLAB 的 repmat 的旧版回答。它是 Python 函数,并利用编译的 repeat。使用广播技术时,它并不是那么重要。 - hpaulj

6

使用广播

vstack、tile和repeat等方法都很好,但是使用广播可以提高数倍的效率...

import numpy as np
from time import time

t = time()
for _ in xrange(10000):
    a = np.array([4,6,6,1])
    b = np.vstack((a,)*100)
print time()-t

t = time()
for _ in xrange(10000):
    a = np.array([4,6,6,1])
    b = np.tile(a,(3,1))
print time()-t

t = time()
for _ in xrange(10000):
    a = np.array([4,6,6,1])
    b = np.empty([100,a.shape[0]])
    b[:] = a
print time()-t

打印:

2.76399993896
0.140000104904
0.0490000247955

2
你可以使用 vstack 进行堆叠:
>>> a = np.array([4,6,6,1])
>>> np.vstack((a,)*3)
array([[4, 6, 6, 1],
       [4, 6, 6, 1],
       [4, 6, 6, 1]])

请注意,您经常不需要这样做...... 您可以使用numpy的广播来执行许多有趣的技巧:
>>> a = np.array([4,6,6,1])
>>> ones = np.ones((4, 4))
>>> ones * a
array([[ 4.,  6.,  6.,  1.],
       [ 4.,  6.,  6.,  1.],
       [ 4.,  6.,  6.,  1.],
       [ 4.,  6.,  6.,  1.]])

在某些情况下,您还可以使用np.newaxis...来实现一些有趣的功能。值得一提的是,建议查看numpy的索引文档以熟悉选项。

1
正如Numpy Array文档所述,第一个参数是shape,因此当你这样做时:
a = np.empty(3)

你正在创建一个三维数组(只有一维)。相反,你应该这样做:
a = np.empty([3,3])

这将创建一个由3个子数组组成的数组,每个子数组的维度为3(即3x3矩阵)。

正如Numpy填充文档所述,fill只接受数字(标量)作为参数,因此您不能使用另一个数组作为参数,而您所做的并没有正确工作:

a.fill(np.array([4,6,6,1]))

为了实现你想要做的事情,我会这样做:

a = np.array([[4,6,6,1]]*3)

希望我的评论能对您有所帮助!

0
你可以使用np.full(),如此处所述。
>>>repetitions = 3
>>>fill_array = np.array([4,6,6,1])
>>>fill_shape = np.shape(fill_array)
>>>a = np.full([*(repetitions,),*fill_shape],fill_array)
>>>a
array([[4, 6, 6, 1],
       [4, 6, 6, 1],
       [4, 6, 6, 1]])

0
重复的任务通常会被简化为矩阵或向量操作。np.outer() 可以比使用单位矩阵进行乘法或填充空数组更快地完成它:
>>>a = np.array([4,6,6,1])
>>>b = np.outer(np.ones(3, dtype=np.int), a)
>>>b
array([[4, 6, 6, 1],
       [4, 6, 6, 1],
       [4, 6, 6, 1]])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接