Numpy 用 1 列将 1d 重塑为 2d 数组

Posted

技术标签:

【中文标题】Numpy 用 1 列将 1d 重塑为 2d 数组【英文标题】:Numpy reshape 1d to 2d array with 1 column 【发布时间】:2016-06-30 19:28:54 【问题描述】:

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 是什么?看起来structured 这无关紧要,我只是用它作为我如何最终得到 1d 或 2d 数组的示例。我的问题是关于如何系统地将一维数组优雅地转换为二维数组。 【参考方案1】:

你可以做-

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

reshape 的第二个输入:-1 负责第二个轴的元素数量。因此,对于2D 输入案例,它没有变化。对于1D 输入案例,它会创建一个2D 数组,其中所有元素都被“推”到第一个轴,因为ar.shape[0] 是元素的总数。

样本运行

一维案例:

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

二维案例:

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

【讨论】:

这个答案的一个变体是:x = np.reshape(x, (len(x),-1)),它还处理输入是一维或二维列表的情况。 @LucaCiti 将此作为单独的答案,以便我投票。 完成。感谢您的推荐。【参考方案2】:

我询问了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,)

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

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

如果数组是简单的 2d 数组,我仍然没有得到你的形状

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)

但是关于确保数组是2d的问题,不管索引返回1d还是2,你的函数基本没问题

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的代码;它测试 0d 和 1d。在第一种情况下,它返回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

【讨论】:

好的,我删除了这个例子。我试图举一个具体的例子,但如果它令人困惑,最好不要有它。【参考方案3】:

为了避免一开始就需要重新整形,如果你用列表对行/列进行切片,或者“运行”切片,你将得到一个包含一行/列的二维数组

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

最简单的方法:

ar.reshape(-1, 1)

【讨论】:

有史以来最简单的方法,在向矩阵添加新列时在 hstack 中工作【参考方案5】:

divakar 的答案的一个变体是:x = np.reshape(x, (len(x),-1)),它还处理输入是 1d 或 2d 列表的情况。

【讨论】:

【参考方案6】:
y = np.array(12)
y = y.reshape(-1,1)
print(y.shape)

O/P:- (1, 1)

【讨论】:

【参考方案7】:

从一维数组(N)到二维主要有两种方式 具有 1 列的数组 (N x 1):

    使用np.newaxis 进行索引; 使用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)

【讨论】:

以上是关于Numpy 用 1 列将 1d 重塑为 2d 数组的主要内容,如果未能解决你的问题,请参考以下文章

在 NumPy 中将 4D 数组重塑为 2D 数组背后的直觉和想法

Python将3d数组重塑为2d

如何在 NumPy 中将 HDF5 2D 数组转换为 1D?

如何将 1d numpy 数组附加到 2d numpy 数组 python

Numpy quirk:将函数应用于两个 1D 数组的所有对,以获得一个 2D 数组

如何在不使用 numpy 的情况下将 2D 列表展平为 1D? [复制]