【问题标题】:python why use numpy.r_ instead of concatenatepython为什么使用numpy.r_而不是连接
【发布时间】:2016-10-11 03:53:27
【问题描述】:

在哪种情况下,使用诸如 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

它更具可读性,显然它做同样的事情。

【问题讨论】:

标签: python numpy concatenation


【解决方案1】:

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

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):

对于较小的数字,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(22)],
    xlabel="len(a)",
    logx=True,
    logy=True,
)

【讨论】:

  • np._rperfplot :)
【解决方案2】:

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. ])

文档中有更多详细信息。

我对@9​​87654321@中的许多切片进行了一些时间测试

【讨论】:

    【解决方案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])
    """
    

    【讨论】:

    • 您至少应该描述该页面的内容,以防超链接中断。
    • @dodell 够公平
    • 我认为r_c_vstackhstack 的比较具有误导性,甚至是错误的。在1,2,3,4 的情况下,4 个操作分别产生形状 (4,)、(1,4)、(4,1)、(4,)。在这个简单的例子中,r_hstack 产生相同的东西,c_vstack 是彼此的转置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-22
    • 2011-10-31
    • 2013-01-04
    • 2010-09-30
    • 2012-07-27
    • 1970-01-01
    • 2013-01-06
    相关资源
    最近更新 更多