Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4586910
  • 博文数量: 1214
  • 博客积分: 13195
  • 博客等级: 上将
  • 技术积分: 9105
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
个人简介

C++,python,热爱算法和机器学习

文章分类

全部博文(1214)

文章存档

2021年(13)

2020年(49)

2019年(14)

2018年(27)

2017年(69)

2016年(100)

2015年(106)

2014年(240)

2013年(5)

2012年(193)

2011年(155)

2010年(93)

2009年(62)

2008年(51)

2007年(37)

分类: Python/Ruby

2015-01-06 11:48:02

原文地址:

在 Numpy 的使用过程中,我们常常需要从原数组中提取部分信息或将原数组拼凑成一个高维的数组,这些操作根本上来说都是希望基于原数组得到一个维度不同的数组。 下面对一些常用方法进行总结。

降低维度

比如我们希望从一个二维数组中抽出某些列,可以这样:

In [45]:
a = np.arange(12).reshape(4,3) a 
Out[45]:
array([[ 0, 1, 2],
 [ 3, 4, 5],
 [ 6, 7, 8],
 [ 9, 10, 11]])
In [46]:
b = np.array([True, False, True, False]) a[b,:] 
Out[46]:
array([[0, 1, 2],
 [6, 7, 8]])

利用 ndarray 的 broadcasting 机制,我们可以直接写成

In [47]:
a[b] 
Out[47]:
array([[0, 1, 2],
 [6, 7, 8]])

b 也可以不用与第一维的长度匹配,缺失部分默认为 False

In [48]:
b = np.array([True, False, True]) a[b,:] 
Out[48]:
array([[0, 1, 2],
 [6, 7, 8]])

需要注意的是 b 必須也是一个 ndarray,否则 numpy 不会将其当作一个 mask 数组,而是当作 index 数组,比如

In [49]:
b = [True, False, True, False] a[b], a[b,:] 
Out[49]:
(array([[3, 4, 5],
 [0, 1, 2],
 [3, 4, 5],
 [0, 1, 2]]),
 array([[3, 4, 5],
 [0, 1, 2],
 [3, 4, 5],
 [0, 1, 2]]))

上例中 numpy 将 True 和 False 直接当作 1 和 0 来处理。其实用 index 数组同样可达到 mask 数组的效果

In [50]:
b = [0, 2] a[b,:] 
Out[50]:
array([[0, 1, 2],
 [6, 7, 8]])

总结一下,只有布尔型的 ndarray 才能当作 mask 数组提取数值。下面列举一些高维的例子:

In [51]:
a = np.arange(16).reshape((2,2,4)) a 
Out[51]:
array([[[ 0, 1, 2, 3],
 [ 4, 5, 6, 7]],

 [[ 8, 9, 10, 11],
 [12, 13, 14, 15]]])
In [52]:
b = np.array([[True, False], [True, False]]) a[b,:] 
Out[52]:
array([[ 0, 1, 2, 3],
 [ 8, 9, 10, 11]])

这等价于在前两维指定坐标

In [53]:
a[[0,1], [0, 0], :] 
Out[53]:
array([[ 0, 1, 2, 3],
 [ 8, 9, 10, 11]])
In [54]:
a[b.nonzero()] 
Out[54]:
array([[ 0, 1, 2, 3],
 [ 8, 9, 10, 11]])

增加维度

有两种常用方法可以用于增加数组维度,一是使用 index 数组(必须是 ndarray 类型),二是借助 newaxis,这里只讨论第二种方法,因为其简单直观。

比如我们希望将两个二维数组在一个新的维度上拼接成一个三维数组,我们可以先利用 newaxis 构建出这个维度,然后再使用 concatenate,vstack, hstack 等方法。

In [55]:
a = np.array([[1,2],[3,4]]) b = np.array([[5,6],[7,8]]) a_ = a[..., np.newaxis] b_ = b[..., np.newaxis] c = np.concatenate((a_, b_), 2) c 
Out[55]:
array([[[1, 5],
 [2, 6]],

 [[3, 7],
 [4, 8]]])

注意: concatenate vstack hstack 等方法并不能修改数组本身的维度。

假设我们想要在第一维之前插入新维度,可以更简单地写成:

In [56]:
c = np.array([a, b]) c 
Out[56]:
array([[[1, 2],
 [3, 4]],

 [[5, 6],
 [7, 8]]])

当然如果觉得 newaxis 麻烦,可以先用上面的方法增加新维度,然后再将其从第一维移至想要的位置:

In [57]:
np.rollaxis(c,0,3) 
Out[57]:
array([[[1, 5],
 [2, 6]],

 [[3, 7],
 [4, 8]]])

注意: np.rollaxis 这个函数设计得极其糟糕,它的第二个参数为需要调整位置的轴,第三个参数为目标位置。如果当前位置等于目标位置,函数不作任何操作,否则当前轴将被调整至紧邻目标位置的前一位置处,np.rollaxis(x,n,n+1) 都是没有实际效果的写法。

总结

  • 减少维度主要通过在数组的某些维度中选取符合条件的元素,具体可采用 index 或 mask 数组。
  • 增加维度主要通过 np.newaxis 或直接构建新数组并结合 rollaxis
  • rollaxis sucks
阅读(8776) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~