15

我在函数r_的 numpy 文档中阅读了以下内容:

字符串整数指定沿哪个轴堆叠多个逗号分隔的数组。一个由两个逗号分隔的整数组成的字符串允许指示强制每个条目作为第二个整数进入的最小维数(要连接的轴仍然是第一个整数)。

他们举了这个例子:

>>> np.r_['0,2', [1,2,3], [4,5,6]] # concatenate along first axis, dim>=2
array([[1, 2, 3],
       [4, 5, 6]])

我不明白,字符串到底'0,2'指示 numpy 做什么?

除了上面的链接,还有其他网站有更多关于这个功能的文档吗?

4

3 回答 3

13

'n,m'告诉r_连接axis=n,并产生至少具有m维度的形状:

In [28]: np.r_['0,2', [1,2,3], [4,5,6]]
Out[28]: 
array([[1, 2, 3],
       [4, 5, 6]])

所以我们沿着axis=0连接,因此我们通常期望结果具有 shape (6,),但是因为m=2,我们告诉r_该形状必须至少是二维的。所以我们得到了 shape (2,3)

In [32]: np.r_['0,2', [1,2,3,], [4,5,6]].shape
Out[32]: (2, 3)

看看当我们增加时会发生什么m

In [36]: np.r_['0,3', [1,2,3,], [4,5,6]].shape
Out[36]: (2, 1, 3)    # <- 3 dimensions

In [37]: np.r_['0,4', [1,2,3,], [4,5,6]].shape
Out[37]: (2, 1, 1, 3) # <- 4 dimensions

您可以使用的任何操作r_也可以使用更具可读性的数组构建函数之一来完成,例如np.concatenate, np.row_stack, np.column_stack, np.hstack, np.vstackor np.dstack,尽管它可能还需要调用reshape.

即使调用了 reshape,其他函数甚至可能更快:

In [38]: %timeit np.r_['0,4', [1,2,3,], [4,5,6]]
10000 loops, best of 3: 38 us per loop
In [43]: %timeit np.concatenate(([1,2,3,], [4,5,6])).reshape(2,1,1,3)
100000 loops, best of 3: 10.2 us per loop
于 2013-01-22T21:39:29.560 回答
3

字符串 '0,2' 告诉 numpy 沿轴 0(第一个轴)连接并将元素包装在足够的括号中以确保二维数组。考虑以下结果:

for axis in (0,1):
    for minDim in (1,2,3):
        print np.r_['{},{}'.format(axis, minDim), [1,2,30, 31], [4,5,6, 61], [7,8,90, 91], [10,11, 12, 13]], 'axis={}, minDim={}\n'.format(axis, minDim)

[ 1  2 30 31  4  5  6 61  7  8 90 91 10 11 12 13] axis=0, minDim=1

[[ 1  2 30 31]
 [ 4  5  6 61]
 [ 7  8 90 91]
 [10 11 12 13]] axis=0, minDim=2

[[[ 1  2 30 31]]

 [[ 4  5  6 61]]

 [[ 7  8 90 91]]

 [[10 11 12 13]]] axis=0, minDim=3

[ 1  2 30 31  4  5  6 61  7  8 90 91 10 11 12 13] axis=1, minDim=1

[[ 1  2 30 31  4  5  6 61  7  8 90 91 10 11 12 13]] axis=1, minDim=2

[[[ 1  2 30 31]
  [ 4  5  6 61]
  [ 7  8 90 91]
  [10 11 12 13]]] axis=1, minDim=3
于 2013-01-22T21:38:31.127 回答
3

您突出显示的段落是两个逗号分隔的整数语法,它是三个逗号分隔的语法的特例。一旦你理解了三个逗号分隔的语法,两个逗号分隔的语法就到位了。

您的示例等效的三个逗号分隔的整数语法为:

np.r_['0,2,-1', [1,2,3], [4,5,6]]

为了提供更好的解释,我将上面的内容更改为:

np.r_['0,2,-1', [1,2,3], [[4,5,6]]]

上面有两个部分:

  1. 逗号分隔的整数字符串

  2. 两个逗号分隔的数组

逗号分隔的数组具有以下形状:

np.array([1,2,3]).shape
(3,)

np.array([[4,5,6]]).shape
(1, 3)

换句话说,第一个“数组”是“一维的”,而第二个“数组”是“二维的”。

首先2in0,2,-1意味着每个都array应该升级,以便它被强制至少为2-dimensional. 由于第二个array已经2-dimensional是它不受影响。然而,第一个array1-dimensional并且为了使其2-dimensional np.r_需要在其形状中添加一个 1 以tuple使其成为(1,3)or (3,1)。这就是-1in0,2,-1发挥作用的地方。它基本上决定了额外的 1 需要放置tuplearray. -1是默认值,并将1(或1s如果需要更多尺寸)放在形状的前面tuple(我将在下面进一步解释原因)。这会将第一个array's形状tuple变成(1,3)这与第二个array's形状相同tuple0in表示生成的0,2,-1数组需要沿“0”轴连接。

由于arrays现在两者都具有连接形状tuple(1,3)可能的,因为如果您将连接轴(上例中的维度 0,其值为 1)放在一边,arrays其余维度都相等(在这种情况下,剩余维度的值两者arrays都是 3)。如果不是这种情况,则会产生以下错误:

ValueError:除连接轴外的所有输入数组维度必须完全匹配

现在,如果您连接两个arrays具有形状(1,3)的结果array将具有形状(1+1,3) == (2,3),因此:

np.r_['0,2,-1', [1,2,3], [[4,5,6]]].shape
(2, 3)

0逗号分隔字符串中的第三个整数使用 a 或正整数时,该整数确定array's升级后的形状中每个形状元组的开始tuple(仅适用于arrays需要升级其维度的那些)。例如0,2,0,对于arrays要求形状升级,array's原始形状tuple应从升级形状的维度 0 开始tuple。对于array [1,2,3]它的形状tuple (3,)1将放置在3. 这将导致形状tuple等于(3,1)并且您可以看到原始形状从升级后的形状tuple (3,)的维度开始。意味着对于0tuple0,2,1[1,2,3]array'sshapetuple (3,)应该从升级后的 shape 元组的维度 1 开始。这意味着 1 需要放置在维度 0 处。生成的形状元组将是(1,3)

当逗号分隔字符串中的第三个整数使用负数时,负号后面的整数决定了原始形状元组的结束位置。当原始形状元组是(3,) 0,2,-1意味着原始形状元组应该在升级后的形状元组的最后一个维度结束,因此 1 将被放置在升级后的形状元组的维度 0 处,升级后的形状元组将是(1,3)。现在(3,)在升级后的形状元组的维度 1 处结束,这也是升级后的形状元组的最后一个维度(原始数组是[1,2,3],升级后的数组是[[1,2,3]])。

np.r_['0,2', [1,2,3], [4,5,6]]

是相同的

np.r_['0,2,-1', [1,2,3], [4,5,6]]

最后,这是一个具有更多维度的示例:

np.r_['2,4,1',[[1,2],[4,5],[10,11]],[7,8,9]].shape
(1, 3, 3, 1)

逗号分隔的数组是:

[[1,2],[4,5],[10,11]]具有形状元组(3,2)

[7,8,9]具有形状元组(3,)

两者都arrays需要升级到4-dimensional arrays. 原始array's形状元组需要从维度 1 开始。

因此,对于第一个数组,形状变为(1,3,2,1)3,2维度 1 开始,因为需要添加两个 1 才能使其4-dimensional一个 1 放置在原始形状元组之前,一个 1 放置在之后。

使用相同的逻辑,第二个数组的形状元组变为(1,3,1,1).

现在arrays需要使用维度 2 作为连接轴将两者连接起来。从每个数组的升级后的形状元组中消除维度 2 会导致(1,3,1)两者的元组arrays。由于生成的元组是相同的,因此可以连接数组并将连接的轴相加以产生(1, 3, 2+1, 1) == (1, 3, 3, 1).

于 2020-01-02T19:17:42.303 回答