将Numpy中的一维数组重塑为只有1列的二维数组

35
numpy 中,结果数组的维度在运行时会有所变化。1d 数组和只有 1 列的 2d 数组之间经常会混淆。在其中一种情况下,我可以迭代列,在另一种情况下则不能。
如何优雅地解决这个问题?为了避免代码中充斥着检查维度的 if 语句,我使用这个函数:
def reshape_to_vect(ar):
    if len(ar.shape) == 1:
      return ar.reshape(ar.shape[0],1)
    return ar

然而,这种方法感觉不太优雅且代价高昂。是否有更好的解决方案?


什么是 dtype?看起来很“结构化”。 - hpaulj
这并不重要,我只是用它作为一个例子来说明我可能会得到一维或二维数组。我的问题是如何优雅地系统地将一维数组转换为二维数组。 - DevShark
7个回答

49

最简单的方法:

ar.reshape(-1, 1)

1
最简单的方法,适用于在矩阵中添加新列时使用hstack。 - Zhannie

20

你可以做 -

ar.reshape(ar.shape[0],-1)

对于reshape的第二个输入:-1,它负责处理第二个轴上的元素数量。因此,在2D输入情况下,它不会改变数组形状;而在1D输入情况下,由于ar.shape[0]是元素的总数目,它会创建一个2D数组,并将所有元素“推”到第一轴。

样例运行

1D情况:

In [87]: ar
Out[87]: array([ 0.80203158,  0.25762844,  0.67039516,  0.31021513,  0.80701097])

In [88]: ar.reshape(ar.shape[0],-1)
Out[88]: 
array([[ 0.80203158],
       [ 0.25762844],
       [ 0.67039516],
       [ 0.31021513],
       [ 0.80701097]])

2D情况:

In [82]: ar
Out[82]: 
array([[ 0.37684126,  0.16973899,  0.82157815,  0.38958523],
       [ 0.39728524,  0.03952238,  0.04153052,  0.82009233],
       [ 0.38748174,  0.51377738,  0.40365096,  0.74823535]])

In [83]: ar.reshape(ar.shape[0],-1)
Out[83]: 
array([[ 0.37684126,  0.16973899,  0.82157815,  0.38958523],
       [ 0.39728524,  0.03952238,  0.04153052,  0.82009233],
       [ 0.38748174,  0.51377738,  0.40365096,  0.74823535]])

2
一个替代方案是:x = np.reshape(x, (len(x),-1)),这也可以处理输入为一维或二维列表的情况。 - Luca Citi
@LucaCiti 把这个变成一个独立的回答,这样我可以投赞成票。 - Doctor J
完成。感谢您的推荐。 - Luca Citi

5
为了避免需要进行重塑,如果您使用列表或连续的切片来切割一行/列,则得到的将是一个只有一行/列的二维数组。
import numpy as np
x = np.array(np.random.normal(size=(4,4)))
print x, '\n'

Result:
[[ 0.01360395  1.12130368  0.95429414  0.56827029]
 [-0.66592215  1.04852182  0.20588886  0.37623406]
 [ 0.9440652   0.69157556  0.8252977  -0.53993904]
 [ 0.6437994   0.32704783  0.52523173  0.8320762 ]] 

y = x[:,[0]]
print y, 'col vector \n'
Result:
[[ 0.01360395]
 [-0.66592215]
 [ 0.9440652 ]
 [ 0.6437994 ]] col vector 


y = x[[0],:]
print y, 'row vector \n'

Result:
[[ 0.01360395  1.12130368  0.95429414  0.56827029]] row vector 

# Slice with "running" index on a column
y = x[:,0:1]
print y, '\n'

Result:
[[ 0.01360395]
 [-0.66592215]
 [ 0.9440652 ]
 [ 0.6437994 ]] 

如果您在选择行/列的时候使用一个单一的数字,它将导致一个一维数组,这是您遇到问题的根本原因:

y = x[:,0]
print y, '\n'

Result:
[ 0.01360395 -0.66592215  0.9440652   0.6437994 ] 

4
以下是与divakar的回答类似的变体:x = np.reshape(x, (len(x),-1)),它还可以处理输入为一维或二维列表的情况。

2

将一维数组(N)转换为只有1列的二维数组(N x 1),主要有两种方法:

  1. 使用np.newaxis进行索引;
  2. 使用reshape()方法进行重塑。
x = np.array([1, 2, 3])  # shape: (3,) <- 1d

x[:, None]               # shape: (3, 1) <- 2d (single column matrix)
x[:, np.newaxis]         # shape: (3, 1) <- a meaningful alias to None

x.reshape(-1, 1)         # shape: (3, 1)

0

我问了关于dtype的问题,因为你的例子让人感到困惑。

我可以创建一个有3个元素(1d)和3个字段的结构化数组:

In [1]: A = np.ones((3,), dtype='i,i,i')
In [2]: A
Out[2]: 
array([(1, 1, 1), (1, 1, 1), (1, 1, 1)], 
      dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])

我可以通过名称访问一个字段(添加括号不会改变任何东西)

In [3]: A['f0'].shape
Out[3]: (3,)

但是如果我访问两个字段,我仍然得到一个一维数组

In [4]: A[['f0','f1']].shape
Out[4]: (3,)
In [5]: A[['f0','f1']]
Out[5]: 
array([(1, 1), (1, 1), (1, 1)], 
      dtype=[('f0', '<i4'), ('f1', '<i4')])

实际上,那些额外的括号确实很重要,如果我查看值的话。

In [22]: A['f0']
Out[22]: array([1, 1, 1], dtype=int32)
In [23]: A[['f0']]
Out[23]: 
array([(1,), (1,), (1,)], 
      dtype=[('f0', '<i4')])

如果数组是一个简单的二维数组,我仍然不明白你的形状。
In [24]: A=np.ones((3,3),int)
In [25]: A[0].shape
Out[25]: (3,)
In [26]: A[[0]].shape
Out[26]: (1, 3)
In [27]: A[[0,1]].shape
Out[27]: (2, 3)

但是,无论索引返回1d还是2d,确保数组是2d的问题,您的函数基本上是可以的。

def reshape_to_vect(ar):
    if len(ar.shape) == 1:
      return ar.reshape(ar.shape[0],1)
    return ar

你可以测试 `ar.ndim` 而不是 `len(ar.shape)`。但无论哪种方式,它都不会很耗费 - 也就是说,执行时间很短 - 不会有大的数组操作。`reshape` 不会复制数据(除非你的步幅很奇怪),因此它只是创建一个带有共享数据指针的新数组对象的成本。
看看 `np.atleast_2d` 的代码;它测试了 0 维和 1 维。在 1 维情况下,它返回 `result = ary[newaxis,:]`。它首先添加额外的轴,这是添加轴的更自然的 `numpy` 位置。你将它添加在结尾。
`ar.reshape(ar.shape[0],-1)` 是绕过 `if` 测试的巧妙方法。在小的计时测试中,它更快,但我们谈论的是微秒级别的函数调用层的影响。
`np.column_stack` 是另一个如果需要则创建列数组的函数。它使用:
 if arr.ndim < 2:
        arr = array(arr, copy=False, subok=True, ndmin=2).T

好的,我已经删除了这个例子。我本来想提供一个具体的例子,但如果它会让人感到困惑,最好不要有它。 - DevShark

0
y = np.array(12)
y = y.reshape(-1,1)
print(y.shape)

O/P:- (1, 1)

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