理解 numpy.r_() 连接的语法
Posted
技术标签:
【中文标题】理解 numpy.r_() 连接的语法【英文标题】:Understanding the syntax of numpy.r_() concatenation 【发布时间】:2013-01-06 06:00:14 【问题描述】:我在函数 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 做什么?
除了上面的链接,还有其他网站有更多关于这个功能的文档吗?
【问题讨论】:
【参考方案1】:您突出显示的段落是两个逗号分隔的整数语法,它是三个逗号分隔的语法的一个特例。一旦你理解了三个逗号分隔的语法,两个逗号分隔的语法就到位了。
您的示例中等效的三个逗号分隔的整数语法为:
np.r_['0,2,-1', [1,2,3], [4,5,6]]
为了提供更好的解释,我将上面的内容更改为:
np.r_['0,2,-1', [1,2,3], [[4,5,6]]]
上面有两部分:
逗号分隔的整数字符串
两个逗号分隔的数组
逗号分隔的数组具有以下形状:
np.array([1,2,3]).shape
(3,)
np.array([[4,5,6]]).shape
(1, 3)
换句话说,第一个“数组”是“一维”,而第二个“数组”是“二维”。
首先0,2,-1
中的2
表示每个array
都应升级,以便强制至少为2-dimensional
。由于第二个 array
已经是 2-dimensional
它不受影响。然而,第一个array
是1-dimensional
并且为了使其成为2-dimensional
np.r_
需要在其形状tuple
中添加一个1 以使其成为(1,3)
或(3,1)
。这就是0,2,-1
中的-1
发挥作用的地方。它基本上决定了额外的 1 需要放置在 array
的形状 tuple
中的位置。 -1
是默认设置,并将1
(或1s
,如果需要更多尺寸)放在形状tuple
的前面(我将在下面解释原因)。这会将第一个array's
形状tuple
转换为(1,3)
,这与第二个array's
形状tuple
相同。 0,2,-1
中的 0
表示生成的数组需要沿“0”轴连接。
由于arrays
现在都具有tuple
和(1,3)
的形状,因此连接是可能的,因为如果您在arrays
中留出连接轴(上例中的维度0,其值为1),则剩余维度相等(在这种情况下,arrays
中剩余维度的值都是 3)。如果不是这种情况,则会产生以下错误:
ValueError: 除连接轴外的所有输入数组维度必须完全匹配
现在,如果您连接两个具有(1,3)
形状的arrays
,则生成的array
将具有(1+1,3) == (2,3)
形状,因此:
np.r_['0,2,-1', [1,2,3], [[4,5,6]]].shape
(2, 3)
当0
或正整数用于逗号分隔字符串中的第三个整数时,该整数确定升级后形状tuple
中每个array's
形状元组的开始(仅适用于那些@987654365 @ 需要升级其尺寸)。例如0,2,0
意味着对于需要形状升级的arrays
,array's
原始形状tuple
应该从升级形状tuple
的维度0 开始。对于具有tuple
(3,)
形状的array
[1,2,3]
,1
将放在3
之后。这将导致形状tuple
等于(3,1)
并且您可以看到原始形状tuple
(3,)
开始于升级形状tuple
的维度0
。 0,2,1
意味着对于 [1,2,3]
,array's
形状 tuple
(3,)
应该从升级后的形状元组的维度 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)
。
现在需要使用维度 2 作为连接轴连接两个 arrays
。从每个数组的升级后的形状元组中消除维度 2 会导致两个 arrays
的元组 (1,3,1)
。由于生成的元组是相同的,因此可以连接数组并将连接的轴相加以产生(1, 3, 2+1, 1) == (1, 3, 3, 1)
。
【讨论】:
感谢您的深入了解!我从来没有完全理解这一点。【参考方案2】:'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]])
所以我们沿轴=0 连接,因此我们通常期望结果具有形状(6,)
,但由于m=2
,我们告诉r_
,形状必须至少是二维的。所以我们得到了形状(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.vstack
或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
【讨论】:
unutbu 写道“我不喜欢这种符号。”,我想知道为什么它首先是在 numeric/numarray 中引入的。通常怀疑是 matlab 兼容性,但我转换了 fortran->python 并且我不知道足够的 matlab 来确定...【参考方案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
【讨论】:
以上是关于理解 numpy.r_() 连接的语法的主要内容,如果未能解决你的问题,请参考以下文章
JAVA语法技术课第1课day01_Java基础语法&HelloWorld
Elasticsearch教程 Elasticsearch查询语法 Elasticsearch权威指南 深入理解Elasticsearch