代码之家  ›  专栏  ›  技术社区  ›  Boris Gorelik

“克隆”行或列向量

  •  111
  • Boris Gorelik  · 技术社区  · 15 年前

    有时,将行或列向量“克隆”到矩阵非常有用。通过克隆,我的意思是转换行向量,例如

    [1,2,3]
    

    成矩阵

    [[1,2,3]
     [1,2,3]
     [1,2,3]
    ]
    

    或列向量,如

    [1
     2
     3
    ]
    

    进入之内

    [[1,1,1]
     [2,2,2]
     [3,3,3]
    ]
    

    在Matlab或Octave中,这很容易做到:

     x = [1,2,3]
     a = ones(3,1) * x
     a =
    
        1   2   3
        1   2   3
        1   2   3
    
     b = (x') * ones(1,3)
     b =
    
        1   1   1
        2   2   2
        3   3   3
    

    我想麻木地重复这个,但没有成功

    In [14]: x = array([1,2,3])
    In [14]: ones((3,1)) * x
    Out[14]:
    array([[ 1.,  2.,  3.],
           [ 1.,  2.,  3.],
           [ 1.,  2.,  3.]])
    # so far so good
    In [16]: x.transpose() * ones((1,3))
    Out[16]: array([[ 1.,  2.,  3.]])
    # DAMN
    # I end up with 
    In [17]: (ones((3,1)) * x).transpose()
    Out[17]:
    array([[ 1.,  1.,  1.],
           [ 2.,  2.,  2.],
           [ 3.,  3.,  3.]])
    

    为什么第一种方法(在[16]中)不起作用?有没有一种方法可以更优雅地用Python来完成这项任务?

    8 回复  |  直到 6 年前
        1
  •  60
  •   Peter    15 年前

    这是一种优雅的、蟒蛇式的方法:

    >>> array([[1,2,3],]*3)
    array([[1, 2, 3],
           [1, 2, 3],
           [1, 2, 3]])
    
    >>> array([[1,2,3],]*3).transpose()
    array([[1, 1, 1],
           [2, 2, 2],
           [3, 3, 3]])
    

    问题在于 [16] 似乎转置对数组没有影响。你可能想要一个矩阵:

    >>> x = array([1,2,3])
    >>> x
    array([1, 2, 3])
    >>> x.transpose()
    array([1, 2, 3])
    >>> matrix([1,2,3])
    matrix([[1, 2, 3]])
    >>> matrix([1,2,3]).transpose()
    matrix([[1],
            [2],
            [3]])
    
        2
  •  232
  •   Løiten thar45    6 年前

    使用 numpy.tile :

    >>> tile(array([1,2,3]), (3, 1))
    array([[1, 2, 3],
           [1, 2, 3],
           [1, 2, 3]])
    

    或者对于重复列:

    >>> tile(array([[1,2,3]]).transpose(), (1, 3))
    array([[1, 1, 1],
           [2, 2, 2],
           [3, 3, 3]])
    
        3
  •  32
  •   tom10    15 年前

    首先要注意的是,使用numpy's 广播 操作通常不需要复制行和列。见 this this 以获取说明。

    但要做到这一点, repeat newaxis 可能是最好的方法

    In [12]: x = array([1,2,3])
    
    In [13]: repeat(x[:,newaxis], 3, 1)
    Out[13]: 
    array([[1, 1, 1],
           [2, 2, 2],
           [3, 3, 3]])
    
    In [14]: repeat(x[newaxis,:], 3, 0)
    Out[14]: 
    array([[1, 2, 3],
           [1, 2, 3],
           [1, 2, 3]])
    

    这个例子是针对行向量的,但是将它应用于列向量是很明显的。重复似乎拼写得很好,但您也可以像在示例中一样通过乘法来完成。

    In [15]: x = array([[1, 2, 3]])  # note the double brackets
    
    In [16]: (ones((3,1))*x).transpose()
    Out[16]: 
    array([[ 1.,  1.,  1.],
           [ 2.,  2.,  2.],
           [ 3.,  3.,  3.]])
    
        4
  •  8
  •   smartkevin    11 年前

    我认为在numpy中使用广播是最好的,而且速度更快。

    我做了如下比较

    import numpy as np
    b = np.random.randn(1000)
    In [105]: %timeit c = np.tile(b[:, newaxis], (1,100))
    1000 loops, best of 3: 354 µs per loop
    
    In [106]: %timeit c = np.repeat(b[:, newaxis], 100, axis=1)
    1000 loops, best of 3: 347 µs per loop
    
    In [107]: %timeit c = np.array([b,]*100).transpose()
    100 loops, best of 3: 5.56 ms per loop
    

    使用广播大约快15倍

        5
  •  5
  •   Mateen Ulhaq    8 年前

    np.broadcast_to 甚至比 np.tile 以下内容:

    x = np.arange(9)
    
    %timeit np.broadcast_to(x, (6,9))
    100000 loops, best of 3: 3.6 µs per loop
    
    %timeit np.tile(x, (6,1))
    100000 loops, best of 3: 8.4 µs per loop
    

    但最快的是@tom10的方法:

    %timeit np.repeat(x[np.newaxis, :], 6, axis=0) 
    100000 loops, best of 3: 3.15 µs per loop
    
        6
  •  2
  •   thebeancounter    8 年前

    你可以使用

    np.tile(x,3).reshape((4,3))
    

    tile将生成向量的reps

    再整形就可以得到你想要的形状

        7
  •  1
  •   Jon Deaton    6 年前

    一个干净的解决方案是使用numpy的外积函数,向量为1:

    np.outer(np.ones(n), x)
    

    给予 n 重复行。切换参数顺序以获取重复列。要获得相等数量的行和列,可以执行以下操作

    np.outer(np.ones_like(x), x)
    
        8
  •  0
  •   kibitzforu    7 年前
    import numpy as np
    x=np.array([1,2,3])
    y=np.multiply(np.ones((len(x),len(x))),x).T
    print(y)
    

    产量:

    [[ 1.  1.  1.]
     [ 2.  2.  2.]
     [ 3.  3.  3.]]