在纯Python中,您可以非常轻松地逐列增长矩阵:
data = []
for i in something:
newColumn = getColumnDataAsList(i)
data.append(newColumn)
NumPy的数组没有append函数。 hstack
函数不适用于零大小的数组,因此以下内容不起作用:
data = numpy.array([])
for i in something:
newColumn = getColumnDataAsNumpyArray(i)
data = numpy.hstack((data, newColumn)) # ValueError: arrays must have same number of dimensions
所以,我的选择是要么在适当的条件下删除初始化inive:
data = None
for i in something:
newColumn = getColumnDataAsNumpyArray(i)
if data is None:
data = newColumn
else:
data = numpy.hstack((data, newColumn)) # works
...或者使用Python列表并稍后转换为数组:
data = []
for i in something:
newColumn = getColumnDataAsNumpyArray(i)
data.append(newColumn)
data = numpy.array(data)
两种变体看起来都有点尴尬。有更好的解决方案吗?
答案 0 :(得分:18)
NumPy实际上有一个追加功能,似乎可以做你想要的,例如,
import numpy as NP
my_data = NP.random.random_integers(0, 9, 9).reshape(3, 3)
new_col = NP.array((5, 5, 5)).reshape(3, 1)
res = NP.append(my_data, new_col, axis=1)
如果您添加另一行,例如
,您的第二个片段(hstack)将起作用my_data = NP.random.random_integers(0, 9, 16).reshape(4, 4)
# the line to add--does not depend on array dimensions
new_col = NP.zeros_like(my_data[:,-1]).reshape(-1, 1)
res = NP.hstack((my_data, new_col))
hstack
给出与concatenate((my_data, new_col), axis=1)
相同的结果,我不确定他们如何比较性能。
虽然这是你问题最直接的答案,但我应该提一下,通过数据源循环来通过追加来填充目标,而在python中,这不是惯用的NumPy。原因如下:
初始化NumPy数组是相对昂贵的,并且使用这种传统的python模式,你会在每次循环迭代时产生或多或少的成本(即,每个附加到NumPy数组的成本大致相同)初始化一个不同大小的新数组。)
因此,NumPy中用于将列迭代添加到2D阵列的常见模式是初始化空目标数组一次(或预先分配具有所有这些的单个2D NumPy数组空列)通过设置所需的列向偏移量(索引)连续填充这些空列 - 显示比解释更容易:
>>> # initialize your skeleton array using 'empty' for lowest-memory footprint
>>> M = NP.empty(shape=(10, 5), dtype=float)
>>> # create a small function to mimic step-wise populating this empty 2D array:
>>> fnx = lambda v : NP.random.randint(0, 10, v)
在OP中填充NumPy数组,除了每次迭代只是在连续的列式偏移处重新设置M的值
>>> for index, itm in enumerate(range(5)):
M[:,index] = fnx(10)
>>> M
array([[ 1., 7., 0., 8., 7.],
[ 9., 0., 6., 9., 4.],
[ 2., 3., 6., 3., 4.],
[ 3., 4., 1., 0., 5.],
[ 2., 3., 5., 3., 0.],
[ 4., 6., 5., 6., 2.],
[ 0., 6., 1., 6., 8.],
[ 3., 8., 0., 8., 0.],
[ 5., 2., 5., 0., 1.],
[ 0., 6., 5., 9., 1.]])
当然,如果您事先不知道阵列的大小应该是多少 只需创建一个比你需要的更大的一个并修剪'未使用'部分 当你完成填充它
>>> M[:3,:3]
array([[ 9., 3., 1.],
[ 9., 6., 8.],
[ 9., 7., 5.]])
答案 1 :(得分:4)
通常在创建NumPy数组时不会继续调整其大小。您对第三种解决方案不满意吗?如果它是一个非常大的矩阵/数组,那么在开始赋值之前可能值得分配数组:
x = len(something)
y = getColumnDataAsNumpyArray.someLengthProperty
data = numpy.zeros( (x,y) )
for i in something:
data[i] = getColumnDataAsNumpyArray(i)
答案 2 :(得分:3)
hstack可以在零大小的数组上运行:
import numpy as np
N = 5
M = 15
a = np.ndarray(shape = (N, 0))
for i in range(M):
b = np.random.rand(N, 1)
a = np.hstack((a, b))
答案 3 :(得分:1)
通常,重新分配NumPy阵列是很昂贵的 - 所以你的第三个解决方案确实是最好的性能。
但是我认为hstack
会做你想要的 - 提示出现在错误信息中,
ValueError:数组必须具有相同数量的维度
我猜测newColumn有两个维度(而不是一维向量),因此您需要数据也有两个维度...例如data = np.array([[]])
- 或者将newColumn作为一维向量(一般来说,如果事情是1D,最好将它们保持在NumPy中1D,因此广播等工作得更好)。在这种情况下,使用np.squeeze(newColumn)
和hstack
或vstack
应该与原始数据定义一起使用。