Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python &引用;“克隆”;行或列向量_Python_Numpy_Linear Algebra - Fatal编程技术网

Python &引用;“克隆”;行或列向量

Python &引用;“克隆”;行或列向量,python,numpy,linear-algebra,Python,Numpy,Linear Algebra,有时,将行或列向量“克隆”到矩阵很有用。通过克隆,我指的是转换行向量,例如 [1, 2, 3] [[1], [2], [3]] 变成矩阵 [[1, 2, 3], [1, 2, 3], [1, 2, 3]] 或列向量,例如 [1, 2, 3] [[1], [2], [3]] 进入 在MATLAB或倍频程中,这很容易做到: x = [1, 2, 3] a = ones(3, 1) * x a = 1 2 3 1 2 3 1 2

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

[1, 2, 3]
[[1],
 [2],
 [3]]
变成矩阵

[[1, 2, 3],
 [1, 2, 3],
 [1, 2, 3]]
或列向量,例如

[1, 2, 3]
[[1],
 [2],
 [3]]
进入

在MATLAB或倍频程中,这很容易做到:

 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
我想在numpy重复这一点,但没有成功

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中以更优雅的方式完成此任务?

下面是一种优雅的python方式:

>>> 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]])
import numpy as np
import pandas as pd
df = pd.DataFrame({1: [1, 2, 3], 2: [4, 5, 6]})
number_repeats = 50
new_df = df.reindex(np.tile(df.index, number_repeats))
[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]])

首先请注意,对于numpy的广播操作,通常不需要复制行和列。有关说明,请参见和

但要做到这一点,也许是最好的方法

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.]])
使用:

或对于重复列:

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

我认为在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倍

np.tile(x,3).reshape((4,3))
平铺将生成向量的重复

重塑将使其成为您想要的形状

让:

>>> n = 1000
>>> x = np.arange(n)
>>> reps = 10000
零成本分配

A不占用任何额外内存。因此,这些声明是即时的:

# New axis
x[np.newaxis, ...]

# Broadcast to specific shape
np.broadcast_to(x, (reps, n))
强制分配

>>> a = np.arange(reps * n).reshape(reps, n)
>>> x_tiled = np.tile(x, (reps, 1))

>>> %timeit np.broadcast_to(x, (reps, n)) * a
17.1 ms ± 284 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

>>> %timeit x[np.newaxis, :] * a
17.5 ms ± 300 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

>>> %timeit x_tiled * a
17.6 ms ± 240 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
如果要强制内容驻留在内存中:

>>> %timeit np.array(np.broadcast_to(x, (reps, n)))
10.2 ms ± 62.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

>>> %timeit np.repeat(x[np.newaxis, :], reps, axis=0)
9.88 ms ± 52.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

>>> %timeit np.tile(x, (reps, 1))
9.97 ms ± 77.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
这三种方法的速度大致相同

计算

>>> a = np.arange(reps * n).reshape(reps, n)
>>> x_tiled = np.tile(x, (reps, 1))

>>> %timeit np.broadcast_to(x, (reps, n)) * a
17.1 ms ± 284 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

>>> %timeit x[np.newaxis, :] * a
17.5 ms ± 300 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

>>> %timeit x_tiled * a
17.6 ms ± 240 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
这三种方法的速度大致相同


结论

>>> a = np.arange(reps * n).reshape(reps, n)
>>> x_tiled = np.tile(x, (reps, 1))

>>> %timeit np.broadcast_to(x, (reps, n)) * a
17.1 ms ± 284 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

>>> %timeit x[np.newaxis, :] * a
17.5 ms ± 300 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

>>> %timeit x_tiled * a
17.6 ms ± 240 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

如果要在计算之前复制,请考虑使用“零成本分配”方法之一。您不会受到“强制分配”的性能惩罚

收益率:

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

一个干净的解决方案是使用NumPy的外积函数和一个向量:

np.outer(np.ones(n), x)
给出
n
重复行。切换参数顺序以获取重复列。要获得相同数量的行和列,可以执行以下操作

np.outer(np.ones_like(x), x)

如果您有一个pandas数据帧,并且希望保留数据类型,甚至是类别,这是一种快速的方法:

>>> 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]])
import numpy as np
import pandas as pd
df = pd.DataFrame({1: [1, 2, 3], 2: [4, 5, 6]})
number_repeats = 50
new_df = df.reindex(np.tile(df.index, number_repeats))

为了回答实际问题,现在已经发布了近十几种解决方案的方法:
x.transpose
反转
x
的形状。其中一个有趣的副作用是,如果
x.ndim==1
,转置将不起任何作用

对于来自MATLAB的人来说,这尤其令人困惑,因为所有数组都隐式地至少有两个维度。转换1D numpy数组的正确方法不是
x.transpose()
x.T
,而是

x[:, None]


从这里开始,您可以乘以1的矩阵,或者使用任何其他建议的方法,只要您尊重MATLAB和numpy之间的(细微)差异。

回到原始问题

在MATLAB或倍频程中,这很容易做到:

 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
x=[1,2,3]

a=一(3,1)*x

在numpy中,它几乎是一样的(也很容易记住):



newaxis还有一个额外的好处,即在需要复制数据之前,它不会实际复制数据。因此,如果您这样做是为了乘法或加法到另一个3x3数组,则无需重复。仔细阅读numpy广播,了解这个想法。@AFoglia-很好的观点。我更新了我的答案,指出了这一点。使用
np.repeat
np.tile
相比有什么好处?@mrglud:对于这种情况,没有什么好处。对于一个小的1D数组,它们是相似的,没有显著的区别/好处/优势/等等。我个人认为行和列克隆之间的对称性更直观,我不喜欢平铺所需的转置,但这只是一个品味问题。Mateen Ulhaq的回答还说重复更快,但这可能取决于所考虑的确切用例,尽管重复更接近C功能,因此可能会保持更快的速度。在2D中,他们有不同的行为,所以这很重要。向上投票!在我的系统中,对于10000个元素重复1000次的向量,
tile
方法比当前接受答案中的方法(使用乘法运算符方法)快19.5倍。在第二部分(“重复列”),您能否解释第二组方括号的作用,即[1,2,3]]@Ant将其制作成一个2D数组,第一个轴的长度为1(在屏幕上垂直),第二个轴的长度为3(在屏幕上水平)。然后,转置使其在第一轴上具有长度3,在第二轴上具有长度1。
(1,3)
的平铺形状将此列复制三次,这就是为什么结果行中的每一行都包含一个单独的元素。这应该是可接受的答案,因为您可以传递任何已初始化的向量,而只有在初始化向量时添加逗号,才能使用可接受的向量。谢谢我无法将其用于2d到3d解决方案:(在Matlab中,请注意使用
repmat
repmat([1 2 3],3,1)
repmat([1 2 3]),1,3)
倍频程也有
repmat
。对于那些希望使用熊猫数据帧执行类似操作的人,请检查
tile_df
(转置适用于二维数组,例如示例中的方形数组,或者当使用
将其转换为
(N,1)
-形状数组时。重塑(-1,1)
)这是非常低效的。使用
numpy.tile
,如中所示。正如Peter所说,这是Pythonic,它更倾向于可读性而不是效率。如果速度如此关键,我会质疑为什么我们首先要使用Python。你可以使用
None
索引来做同样的事情。什么是newaxis?!np.newaxis是nonepeat的别名,速度更快:5。56ms=5560