数值错误:所有输入数组的维度必须相同。

40

我遇到了关于np.append的问题。

我正在尝试使用以下代码来复制20x361矩阵n_list_converted的最后一列:

n_last = []
n_last = n_list_converted[:, -1]
n_lists = np.append(n_list_converted, n_last, axis=1)

但我遇到了错误:

ValueError: 所有的输入数组必须具有相同的维度

然而,我已经通过以下方法检查了矩阵的维度:

 print(n_last.shape, type(n_last), n_list_converted.shape, type(n_list_converted))

我得到了

(20L,) (20L, 361L)

这些维度是匹配的吗?错误在哪里?


21
尝试使用np.column_stack - Divakar
9
可以的,那么需要翻译的内容是:“它起作用了!但为什么呢?” - odo22
1
尝试使用axis=None来添加空数组。 - Timoth Dev A
5个回答

27

如果我从一个3x4的数组开始,并在轴1上连接一个3x1的数组,我将得到一个3x5的数组:

In [911]: x = np.arange(12).reshape(3,4)
In [912]: np.concatenate([x,x[:,-1:]], axis=1)
Out[912]: 
array([[ 0,  1,  2,  3,  3],
       [ 4,  5,  6,  7,  7],
       [ 8,  9, 10, 11, 11]])
In [913]: x.shape,x[:,-1:].shape
Out[913]: ((3, 4), (3, 1))

请注意,连接操作的两个输入都有2个维度。
省略冒号:x[:,-1]的形状为(3,) - 它是1维的,因此会出现错误。
In [914]: np.concatenate([x,x[:,-1]], axis=1)
...
ValueError: all the input arrays must have same number of dimensions
np.append 的代码是(在指定轴的情况下)
return concatenate((arr, values), axis=axis)

所以稍微改变语法,append 就可以使用了。它不再接受列表作为参数,而是需要两个参数。它模仿了列表的 append 语法,但不应与那个列表方法混淆。
In [916]: np.append(x, x[:,-1:], axis=1)
Out[916]: 
array([[ 0,  1,  2,  3,  3],
       [ 4,  5,  6,  7,  7],
       [ 8,  9, 10, 11, 11]])

np.hstack 首先确保所有输入都至少是一维的,然后执行连接操作:

return np.concatenate([np.atleast_1d(a) for a in arrs], 1)

因此,它需要相同的 x[:,-1:] 输入。本质上是相同的操作。

np.column_stack 也在轴1上进行连接。但首先它会将1d输入通过。

array(arr, copy=False, subok=True, ndmin=2).T

这是将(3,)数组转换为(3,1)数组的通用方法。
In [922]: np.array(x[:,-1], copy=False, subok=True, ndmin=2).T
Out[922]: 
array([[ 3],
       [ 7],
       [11]])
In [923]: np.column_stack([x,x[:,-1]])
Out[923]: 
array([[ 0,  1,  2,  3,  3],
       [ 4,  5,  6,  7,  7],
       [ 8,  9, 10, 11, 11]])

所有这些“堆栈”可能很方便,但从长远来看,了解维度和基础np.concatenate是非常重要的。还要知道如何查找此类函数的代码。我经常使用ipython ??魔法指令。

在时间测试中,np.concatenate明显更快 - 对于像这样的小数组,额外的函数调用层会产生很大的时间差异。


这对我来说似乎很疯狂。为什么numpy默认将数组定义为[m,]而不是[m,1]? - Sean
@Sean,在MATLAB中,一切都是2D(或更多),Fortran/列优先是默认设置,列向量(m,1)形状可能最自然。但是numpy是用C语言编写的Python库,用于更多的线性代数计算。np.array([1,2,3])np.array([[1],[2],[3]])更简单易打和显示。一个1D数组可以自然地映射到/从一个简单的Python数字列表。而且,使用行优先排序,主导维度是最外层的,所以(m,)更像(1,m)而不是(m,1)。但在这三种形状之间进行转换非常容易。 - hpaulj

13

(n,)和(n,1)形状不同。尝试使用[:, None]标记将向量转换为数组:

n_lists = np.append(n_list_converted, n_last[:, None], axis=1)

或者,当提取n_last时,您可以使用

n_last = n_list_converted[:, -1:]

获取一个(20, 1)数组。


8
你出现错误的原因是因为“1*n”矩阵与长度为n的数组不同。
我建议使用hstack()和vstack()。
使用方法如下:
import numpy as np
a = np.arange(32).reshape(4,8) # 4 rows 8 columns matrix.
b = a[:,-1:]                    # last column of that matrix.

result = np.hstack((a,b))       # stack them horizontally like this:
#array([[ 0,  1,  2,  3,  4,  5,  6,  7,  7],
#       [ 8,  9, 10, 11, 12, 13, 14, 15, 15],
#       [16, 17, 18, 19, 20, 21, 22, 23, 23],
#       [24, 25, 26, 27, 28, 29, 30, 31, 31]])

注意到重复的“7, 15, 23, 31”列。 同时,请注意我使用了a[:,-1:]而不是a[:,-1]。我的版本生成了一列:
array([[7],
       [15],
       [23],
       [31]])

不是一行的array([7,15,23,31])


编辑:append()速度要慢得多。请阅读此答案


np.append 比列表 .append 慢,但与 stacks 相当。它使用 np.concatenate - hpaulj
@hpaulj 所以...就像我之前说的,使用appendstack在处理两个矩阵时是相同的,但是当处理超过两个元素时,stack更好,因此stack始终_至少与_ append一样好。 - RuRo

5

你还可以通过在方括号 [ ] 中包含 (n,) 来将其转换为 (n,1)。

例如,不要使用 np.append(b,a,axis=0),而是使用 np.append(b,[a],axis=0)

a=[1,2]
b=[[5,6],[7,8]]
np.append(b,[a],axis=0)

返回值

array([[5, 6],
       [7, 8],
       [1, 2]])

反之亦然:b=[1,2]; a=[[5,6],[7,8]]; np.append([b],a,axis=0) - Davidson Lima

0

我通常使用np.row_stack((ndarray_1, ndarray_2, ..., ndarray_nth))

假设你的ndarrays确实具有相同的形状,这应该适用于你

n_last = []
n_last = n_list_converted[:, -1]
n_lists = np.row_stack((n_list_converted, n_last))

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