Numpy:将1D数组作为2D数组获取而无需重塑

5

我需要将多个数组按行堆叠在一起,这些数组具有相同的行数(尽管使用时行数可能会变化),但列数不同。然而,其中一些数组只有一列,例如:

array = np.array([1,2,3,4,5])

这提供了

#array.shape = (5,)

但我希望将该形状识别为二维数组,例如:
#array.shape = (5,1)

所以hstack可以将它们组合起来。我的当前解决方案是:
array = np.atleast_2d([1,2,3,4,5]).T
#array.shape = (5,1)

我在想,是否有更好的方法来做这件事?

array = np.array([1,2,3,4,5]).reshape(len([1,2,3,4,5]), 1)

如何更好?请注意,我使用 [1,2,3,4,5] 只是为了让示例更加具体。在实践中,它将是一个更大的列表,作为参数传递给函数。谢谢!

4个回答

5

请查看 hstackvstack 的代码。它们中的一个或两个会将参数通过 atleast_nd 传递。这是一种完全可接受的重塑数组的方式。

其他一些方法:

arr = np.array([1,2,3,4,5]).reshape(-1,1)  # saves the use of len()
arr = np.array([1,2,3,4,5])[:,None]  # adds a new dim at end
np.array([1,2,3],ndmin=2).T  # used by column_stack

hstackvstack 的转换方式:

arrs = [atleast_1d(_m) for _m in tup]
[atleast_2d(_m) for _m in tup]

测试数据:

a1=np.arange(2)
a2=np.arange(10).reshape(2,5)
a3=np.arange(8).reshape(2,4)

np.hstack([a1.reshape(-1,1),a2,a3])
np.hstack([a1[:,None],a2,a3])
np.column_stack([a1,a2,a3])

结果:

array([[0, 0, 1, 2, 3, 4, 0, 1, 2, 3],
       [1, 5, 6, 7, 8, 9, 4, 5, 6, 7]])

如果事先不知道哪些数组是1d的,那么使用column_stack是最简单的方法。其他方法需要一个小函数,在应用重塑之前测试维度。

Numpy: use reshape or newaxis to add dimensions


有趣,我之前并不知道这两种方法。我会进行一些定时测试来看看哪种方法表现最佳,但是这两种方法似乎都比我之前的方法更自然。谢谢! - Taaam
我添加了一个链接到最近相关的SO问题。 - hpaulj
最新版本已添加了一个更通用的“堆栈”。 - hpaulj

1
如果我理解您的意图正确,您希望将一个形状为(N,)的数组转换为一个形状为(N,1)的数组,以便可以应用np.hstack:
In [147]: np.hstack([np.atleast_2d([1,2,3,4,5]).T, np.atleast_2d([1,2,3,4,5]).T])
Out[147]: 
array([[1, 1],
       [2, 2],
       [3, 3],
       [4, 4],
       [5, 5]])

在这种情况下,您可以使用避免重新塑造数组并改用 np.column_stack
In [151]: np.column_stack([[1,2,3,4,5], [1,2,3,4,5]])
Out[151]: 
array([[1, 1],
       [2, 2],
       [3, 3],
       [4, 4],
       [5, 5]])

谢谢,实际上我正在与scikit-learn一起使用它们,并且它们在内部使用hstack,因此我确实需要它们是面向行的。 - Taaam

1

我跟随Ludo的工作,并将v的大小从5改为10000。我在我的PC上运行了代码,结果显示至少使用2d似乎是更有效的方法。

import numpy as np
import timeit

v = np.arange(10000)

print('atleast2d:',timeit.timeit(lambda:np.atleast_2d(v).T))
print('reshape:',timeit.timeit(lambda:np.array(v).reshape(-1,1)))  # saves the use of len()
print('v[:,None]:', timeit.timeit(lambda:np.array(v)[:,None]))  # adds a new dim at end
print('np.array(v,ndmin=2).T:', timeit.timeit(lambda:np.array(v,ndmin=2).T))  # used by column_stack

结果是:

这里放结果

atleast2d: 1.3809496470021259
reshape: 27.099974197000847
v[:,None]: 28.58291715100131
np.array(v,ndmin=2).T: 30.141663907001202

我的建议是,在处理短向量时使用[:None],而在你的向量变得更长时使用np.atleast_2d。


0

只是为了补充hpaulj的答案。我对这四种方法的速度有些好奇。获胜者是在1d数组末尾添加列的方法。

这是我运行的内容:

import numpy as np
import timeit

v = [1,2,3,4,5]

print('atleast2d:',timeit.timeit(lambda:np.atleast_2d(v).T))
print('reshape:',timeit.timeit(lambda:np.array(v).reshape(-1,1)))  # saves the use of len()
print('v[:,None]:', timeit.timeit(lambda:np.array(v)[:,None]))  # adds a new dim at end
print('np.array(v,ndmin=2).T:', timeit.timeit(lambda:np.array(v,ndmin=2).T))  # used by column_stack

结果如下:

atleast2d: 4.455070924214851
reshape: 2.0535152913971615
v[:,None]: 1.8387219828073285
np.array(v,ndmin=2).T: 3.1735243063353664

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接