python为什么使用numpy.r_而不是连接

时间:2016-06-10 08:47:32

标签: python numpy concatenation

在这种情况下,使用像numpy.r_或numpy.c_这样的对象比使用concatenate或vstack这样的函数更好(更有效,更合适)?

我正在尝试理解程序员编写的代码:

return np.r_[0.0, 1d_array, 0.0] == 2

其中1d_array是一个数组,其值可以是0,1或2。 为什么不使用np.concatenate(例如)呢?喜欢:

return np.concatenate([[0.0], 1d_array, [0.0]]) == 2

它更具可读性,显然也是如此。

3 个答案:

答案 0 :(得分:17)

np.r_已在numpy/lib/index_tricks.py文件中实施。这是纯Python代码,没有特殊编译的东西。所以它不会比用concatenatearangelinspace写的等价物快。只有当符号符合您的思维方式和您的需求时,它才有用。

在您的示例中,它只保存将标量转换为列表或数组:

In [452]: np.r_[0.0, np.array([1,2,3,4]), 0.0]
Out[452]: array([ 0.,  1.,  2.,  3.,  4.,  0.])

错误的相同参数:

In [453]: np.concatenate([0.0, np.array([1,2,3,4]), 0.0])
...
ValueError: zero-dimensional arrays cannot be concatenated

使用添加的[]

进行更正
In [454]: np.concatenate([[0.0], np.array([1,2,3,4]), [0.0]])
Out[454]: array([ 0.,  1.,  2.,  3.,  4.,  0.])

hstack通过[atleast_1d(_m) for _m in tup]传递所有参数来处理这个问题:

In [455]: np.hstack([0.0, np.array([1,2,3,4]), 0.0])
Out[455]: array([ 0.,  1.,  2.,  3.,  4.,  0.])

因此,至少在简单的情况下,它与hstack最相似。

但是当你想要使用范围

时,r_的真正用处就出现了
np.r_[0.0, 1:5, 0.0]
np.hstack([0.0, np.arange(1,5), 0.0])
np.r_[0.0, slice(1,5), 0.0]

r_允许您使用索引中使用的:语法。那是因为它实际上是一个具有__getitem__方法的类的实例。 index_tricks多次使用此编程技巧。

他们被其他的哨声吹响了

使用imaginary步骤,使用np.linspace展开切片而不是np.arange

np.r_[-1:1:6j, [0]*3, 5, 6]

产生

array([-1. , -0.6, -0.2,  0.2,  0.6,  1. ,  0. ,  0. ,  0. ,  5. ,  6. ])

文档中有更多详细信息。

我在https://stackoverflow.com/a/37625115/901925

中为许多切片做了一些时间测试

答案 1 :(得分:5)

我也对这个问题感兴趣,并比较了

的速度
numpy.c_[a, a]
numpy.stack([a, a]).T
numpy.vstack([a, a]).T
numpy.column_stack([a, a])
numpy.concatenate([a[:,None], a[:,None]], axis=1)

对于任何输入向量a都执行相同的操作。这是我找到的(使用perfplot):

enter image description here

对于较小的数字,numpy.concatenate是赢家,较大的(约3000)stack / vstack

情节是用

创建的
import numpy
import perfplot

perfplot.show(
    setup=lambda n: numpy.random.rand(n),
    kernels=[
        lambda a: numpy.c_[a, a],
        lambda a: numpy.stack([a, a]).T,
        lambda a: numpy.vstack([a, a]).T,
        lambda a: numpy.column_stack([a, a]),
        lambda a: numpy.concatenate([a[:, None], a[:, None]],axis=1)
        ],
    labels=['c_', 'stack', 'vstack', 'column_stack', 'concat'],
    n_range=[2**k for k in range(19)],
    xlabel='len(a)',
    )

答案 2 :(得分:3)

您需要的所有解释:

https://sourceforge.net/p/numpy/mailman/message/13869535/

我发现最相关的部分是:

"""
For r_ and c_ I'm summarizing, but effectively they seem to be doing
something like:

r_[args]:
    concatenate( map(atleast_1d,args),axis=0 )

c_[args]:
    concatenate( map(atleast_1d,args),axis=1 )

c_ behaves almost exactly like hstack -- with the addition of range
literals being allowed.

r_ is most like vstack, but a little different since it effectively
uses atleast_1d, instead of atleast_2d.  So you have
>>> numpy.vstack((1,2,3,4))
array([[1],
       [2],
       [3],
       [4]])
but
>>> numpy.r_[1,2,3,4]
array([1, 2, 3, 4])
"""