《Python数据分析》一2.6 处理数组形状

2.6 处理数组形状

前面,我们学习过reshape()函数,实际上,除了数组形状的调整外,数组的扩充也是一个经常碰到的乏味工作。比如,可以想像一下将多维数组转换成一维数组时的情形。下面的代码就是用来干这件事情的,它取自本书代码包中的shapemanipulation.py文件:

import numpy as np

# Demonstrates multi dimensional arrays slicing.
#
# Run from the commandline with
#
# python shapemanipulation.py
print "In: b = arange(24).reshape(2,3,4)"
b = np.arange(24).reshape(2,3,4)

print "In: b"
print b
#Out:
#array([[[ 0, 1, 2, 3],
#     [ 4, 5, 6, 7],
#     [ 8, 9, 10, 11]],
#
#    [[12, 13, 14, 15],
#     [16, 17, 18, 19],
#     [20, 21, 22, 23]]])

print "In: b.ravel()"
print b.ravel()
#Out:
#array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 
14, 15, 16,
#    17, 18, 19, 20, 21, 22, 23])

print "In: b.flatten()"
print b.flatten()
#Out:
#array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 
14, 15, 16,
#     17, 18, 19, 20, 21, 22, 23])

print "In: b.shape = (6,4)"
b.shape = (6,4)

print "In: b"
print b
#Out:
#array([[ 0, 1, 2, 3],
#     [ 4, 5, 6, 7],
#     [ 8, 9, 10, 11],
#     [12, 13, 14, 15],
#     [16, 17, 18, 19],
#     [20, 21, 22, 23]])

print "In: b.transpose()"
print b.transpose()
#Out:
#array([[ 0, 4, 8, 12, 16, 20],
#     [ 1, 5, 9, 13, 17, 21],
#     [ 2, 6, 10, 14, 18, 22],
#     [ 3, 7, 11, 15, 19, 23]])

print "In: b.resize((2,12))"
b.resize((2,12))

print "In: b"
print b
#Out:
#array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
#     [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]])
可以利用以下函数处理数组的形状。

拆解:可以用ravel()函数将多维数组变成一维数组,代码如下:
  In: b
  Out:
  array([[[ 0, 1, 2, 3],
       [ 4, 5, 6, 7],
       [ 8, 9, 10, 11]],
      [[12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23]]])
  In: b.ravel()
  Out:
  array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
  13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23])

拉直(Flatten):flatten()函数的名字取得非常贴切,其功能与ravel()相同。可是,flatten()返回的是真实的数组,需要分配新的内存空间;而ravel()函数返回的只是数组的视图。这意味着,我们可以像下面这样直接操作数组:
 

 In: b.flatten()
  Out:
  array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
  13, 14, 15, 16,
      17, 18, 19, 20, 21, 22, 23])

用元组指定数组形状:除reshape()函数外,还可以用元组来轻松定义数组的形状,如下所示:

 In: b.shape = (6,4)
  In: b
  Out:
  array([[ 0, 1, 2, 3],
      [ 4, 5, 6, 7],
      [ 8, 9, 10, 11],
      [12, 13, 14, 15],
      [16, 17, 18, 19],
      [20, 21, 22, 23]])

可见,上述代码直接改变了数组的形状。这样,我们就得到了一个6×4的数组。
转置:在线性代数中,矩阵的转置操作非常常见。转置是一种数据变换方法,对于二维表而言,转置就意味着行变成列,同时列变成行。转置也可以通过下列代码完成:
 

 In: b.transpose()
  Out:
  array([[ 0, 4, 8, 12, 16, 20],
      [ 1, 5, 9, 13, 17, 21],
      [ 2, 6, 10, 14, 18, 22],
      [ 3, 7, 11, 15, 19, 23]])

调整大小:函数resize()的作用类似于reshape(),但是会改变所作用的数组:

In: b.resize((2,12))
  In: b
  Out:
  array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
      [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]])

2.6.1 堆叠数组

从深度看,数组既可以横向叠放,也可以竖向叠放。为此,可以使用vstack()、dstack()、hstack()、column_stack()、row_stack()和concatenate()等函数。在此之前,我们先要建立某些数组(以下代码取自本书代码包中的stacking.py文件):

In: a = arange(9).reshape(3,3)
In: a
Out:
array([[0, 1, 2],
     [3, 4, 5],
     [6, 7, 8]])
In: b = 2 * a
In: b
Out:
array([[ 0, 2, 4],
     [ 6, 8, 10],
     [12, 14, 16]])

就像前面所说的,可以用下列技术来堆放数组。

水平叠加:先介绍水平叠加方式,即用元组确定ndarrays数组的形状,然后交由hstack()函数来码放这些数组。具体如下所示:

 In: hstack((a, b))
  Out:
  array([[ 0, 1, 2, 0, 2, 4],
      [ 3, 4, 5, 6, 8, 10],
      [ 6, 7, 8, 12, 14, 16]])

用concatenate()函数也能达到同样的效果,代码如下所示:

In: concatenate((a, b), axis=1)
  Out:
  array([[ 0, 1, 2, 0, 2, 4],
      [ 3, 4, 5, 6, 8, 10],
      [ 6, 7, 8, 12, 14, 16]])

水平叠加过程的示意图如图2-1所示:

垂直叠加:使用垂直叠加方法时,先要构建一个元组,然后将元组交给vstack()函数来码放数组,代码如下所示:
 

In: vstack((a, b))
  Out:
  array([[ 0, 1, 2],
      [ 3, 4, 5],
      [ 6, 7, 8],
      [ 0, 2, 4],
      [ 6, 8, 10],
      [12, 14, 16]])

当参数axis置0时,concatenate()函数也会得到同样的效果。实际上,这是该参数的缺省值,代码如下所示:

 

 In: concatenate((a, b), axis=0)
  Out:
  array([[ 0, 1, 2],
      [ 3, 4, 5],
      [ 6, 7, 8],
      [ 0, 2, 4],
      [ 6, 8, 10],
      [12, 14, 16]])

垂直叠加过程的示意图如图2-2所示。

深度叠加:除此之外,还有一种深度叠加方法,这要用到dstack()函数和一个元组。这种方法是沿着第三个坐标轴(纵向)的方向来叠加一摞数组。举例来说,可以在一个图像数据的二维数组上叠加另一幅图像的数据,代码如下所示:
 

In: dstack((a, b))
  Out:
  array([[[ 0, 0],
       [ 1, 2],
       [ 2, 4]],
      [[ 3, 6],
       [ 4, 8],
       [ 5, 10]],
      [[ 6, 12],
       [ 7, 14],
       [ 8, 16]]])

列式堆叠:column_stack()函数以列方式对一维数组进行堆叠。代码如下所示:
 

 In: oned = arange(2)
  In: oned
  Out: array([0, 1])
  In: twice_oned = 2 * oned
  In: twice_oned
  Out: array([0, 2])
  In: column_stack((oned, twice_oned))
  Out:
  array([[0, 0],
      [1, 2]])

用这种方法堆叠二维数组时,过程类似于hstack()函数,代码如下所示:
 

 In: column_stack((a, b))
  Out:
  array([[ 0, 1, 2, 0, 2, 4],
      [ 3, 4, 5, 6, 8, 10],
      [ 6, 7, 8, 12, 14, 16]])
  In: column_stack((a, b)) == hstack((a, b))
  Out:
  array([[ True, True, True, True, True, True],
      [ True, True, True, True, True, True],
      [ True, True, True, True, True, True]], 
  dtype=bool)

是的,你猜得没错!我们用==运算符对两个数组进行了比对。
行式堆叠:同时,NumPy自然也有以行方式对数组进行堆叠的函数,这个用于一维数组的函数名为row_stack(),它将数组作为行码放到二维数组中,代码如下所示:
 

In: row_stack((oned, twice_oned))
  Out:
  array([[0, 1],
      [0, 2]])

对于二维数组,row_stack()函数相当于vstack()函数,如下所示:
 

In: row_stack((a, b))
  Out:
  array([[ 0, 1, 2],
      [ 3, 4, 5],
      [ 6, 7, 8],
      [ 0, 2, 4],
      [ 6, 8, 10],
      [12, 14, 16]])
  In: row_stack((a,b)) == vstack((a, b))
  Out:
  array([[ True, True, True],
      [ True, True, True],
      [ True, True, True],
      [ True, True, True],
      [ True, True, True],
      [ True, True, True]], dtype=bool)

2.6.2 拆分NumPy数组

可以从纵向、横向和深度方向来拆分数组,相关函数有hsplit()、vsplit()、dsplit()和split()。我们既可以把数组分成相同形状的数组,也可以从规定的位置开始切取数组。下面对相关函数逐个详解。

横向拆分:对于一个3×3数组,可以沿着横轴方向将其分解为3部分,并且各部分的大小和形状完全一致,代码(它取自本书代码包中的splitting.py文件)如下所示:
 

In: a
  Out:
  array([[0, 1, 2],
      [3, 4, 5],
      [6, 7, 8]])
  In: hsplit(a, 3)
  Out:
  [array([[0],
      [3],
      [6]]),
  array([[1],
      [4],
      [7]]),
  array([[2],
      [5],
      [8]])]

这相当于调用了参数axis=1的split()函数:
 

In: split(a, 3, axis=1)
  Out:
  [array([[0],
      [3],
      [6]]),
  array([[1],
      [4],
      [7]]),
  rray([[2],
      [5],
      [8]])]

纵向拆分:vsplit()函数将沿着纵轴方向分解数组。
 

In: vsplit(a, 3)
  Out: [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 
  8]])]

当参数axis=0时,split()函数也会沿着纵轴方向分解数组,如下所示:
 

In: split(a, 3, axis=0)
  Out: [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 
  8]])]

深向拆分:dsplit()函数会沿着深度方向分解数组。下面以秩为3的数组为例进行说明:
 

In: c = arange(27).reshape(3, 3, 3)
  In: c
  Out:
  array([[[ 0, 1, 2],
       [ 3, 4, 5],
       [ 6, 7, 8]],
      [[ 9, 10, 11],
       [12, 13, 14],
       [15, 16, 17]],
      [[18, 19, 20],
       [21, 22, 23],
       [24, 25, 26]]])
  In: dsplit(c, 3)
  Out:
  [array([[[ 0],
       [ 3],
       [ 6]],
      [[ 9],
       [12],
       [15]],
      [[18],
       [21],
       [24]]]),
  array([[[ 1],
       [ 4],
       [ 7]],
      [[10],
       [13],
       [16]],
      [[19],
       [22],
       [25]]]),
  array([[[ 2],
       [ 5],
       [ 8]],
      [[11],
       [14],
       [17]],
      [[20],
       [23],
       [26]]])]

2.6.3 NumPy数组的属性

下面举例说明NumPy数组各种属性的详细用法。注意,下面的示例代码取自本书代码包中的arrayattributes2.py文件:

import numpy as np

# Demonstrates ndarray attributes.
#
# Run from the commandline with
#
# python arrayattributes2.py
b = np.arange(24).reshape(2, 12)
print "In: b"
print b
#Out:
#array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
#    [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]])

print "In: b.ndim"
print b.ndim
#Out: 2

print "In: b.size"
print b.size
#Out: 24

print "In: b.itemsize"
print b.itemsize
#Out: 8

print "In: b.nbytes"
print b.nbytes
#Out: 192

print "In: b.size * b.itemsize"
print b.size * b.itemsize
#Out: 192

print "In: b.resize(6,4)"
print b.resize(6,4)
print "In: b"
print b
#Out:
#array([[ 0, 1, 2, 3],
#    [ 4, 5, 6, 7],
#     [ 8, 9, 10, 11],
#     [12, 13, 14, 15],
#     [16, 17, 18, 19],
#     [20, 21, 22, 23]])

print "In: b.T"
print b.T
#Out:
#array([[ 0, 4, 8, 12, 16, 20],
#     [ 1, 5, 9, 13, 17, 21],
#     [ 2, 6, 10, 14, 18, 22],
#     [ 3, 7, 11, 15, 19, 23]])

print "In: b.ndim"
print b.ndim
#Out: 1

print "In: b.T"
print b.T
#Out: array([0, 1, 2, 3, 4])

print "In: b = array([1.j + 1, 2.j + 3])"
b = np.array([1.j + 1, 2.j + 3])

print "In: b"
print b
#Out: array([ 1.+1.j, 3.+2.j])

print "In: b.real"
print b.real
#Out: array([ 1., 3.])

print "In: b.imag"
print b.imag
#Out: array([ 1., 2.])

print "In: b.dtype"
print b.dtype
#Out: dtype('complex128')

print "In: b.dtype.str"
print b.dtype.str
#Out: '<c16'

print "In: b = arange(4).reshape(2,2)"
b = np.arange(4).reshape(2,2)

print "In: b"
print b
#Out: 

#array([[0, 1],
#     [2, 3]])

print "In: f = b.flat"
f = b.flat

print "In: f"
print f
#Out: <numpy.flatiter object at 0x103013e00>

print "In: for it in f: print it"
for it in f:
 print it
#0
#1
#2
#3

print "In: b.flat[2]"
print b.flat[2]
#Out: 2

print "In: b.flat[[1,3]]"
print b.flat[[1,3]]
#Out: array([1, 3])

print "In: b"
print b
#Out:
#array([[7, 7],
#     [7, 7]])

print "In: b.flat[[1,3]] = 1"
b.flat[[1,3]] = 1
print "In: b"
print b
#Out:
#array([[7, 1],
#    [7, 1]])

除shape和dtype属性外,ndarray类型的属性还很多,下面逐一列出。

ndim属性存储的是维度的数量,下面举例说明:
 

In: b
  Out:
  array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
      [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]])
  In: b.ndim
  Out: 2

size属性用来保存元素的数量,用法如下所示:
 

In: b.size
  Out: 24

itemsize属性可以返回数组中各个元素所占用的字节数,代码如下所示:

In: b.itemsize
  Out: 8

如果想知道存储整个数组所需的字节数量,可以求助于nbytes属性。这个属性的值正好是itemsize属性值和size属性值之积。
 

In: b.nbytes
  Out: 192
  In: b.size * b.itemsize
  Out: 192

T属性的作用与transpose()函数相同,下面举例说明:
 

In: b.resize(6,4)
  In: b
  Out:
  array([[ 0, 1, 2, 3],
      [ 4, 5, 6, 7],
      [ 8, 9, 10, 11],
      [12, 13, 14, 15],
      [16, 17, 18, 19],
      [20, 21, 22, 23]])
  In: b.T
  Out:
  array([[ 0, 4, 8, 12, 16, 20],
      [ 1, 5, 9, 13, 17, 21],
      [ 2, 6, 10, 14, 18, 22],
      [ 3, 7, 11, 15, 19, 23]])

如果数组的秩(rank)小于2,那么所得只是一个数组的视图:

In: b.ndim
  Out: 1
  In: b.T
  Out: array([0, 1, 2, 3, 4])

对于NumPy来说,复数用j表示,下面举例说明如何用复数生成一个数组:
 

In: b = array([1.j + 1, 2.j + 3])
  In: b
  Out: array([ 1.+1.j, 3.+2.j])

real属性将返回数组的实部;当数组元素全为实数时,就返回数组本身,如下 所示:
 

In: b.real
  Out: array([ 1., 3.])

i``mag属性存放的是数组的虚部。
 

In: b.imag
  Out: array([ 1., 2.])

如果数组含有复数,那么它的数据类型将自动变为复数类型,如下所示:
 

 In: b.dtype
  Out: dtype('complex128')
  In: b.dtype.str
  Out: '<c16'

flat属性可返回一个numpy.flatiter对象,这是获得flatiter对象的唯一方法,但我们无法访问flatiter的构造函数。可以使用flat的迭代器来遍历数组,就像遍历“胖”数组那样,代码如下所示:
 

In: b = arange(4).reshape(2,2)
  In: b
  Out:
  array([[0, 1],
      [2, 3]])
  In: f = b.flat
  In: f
  Out: <numpy.flatiter object at 0x103013e00>
  In: for item in f: print item
   .....:
  0
  1
  2
  3

当然,取得flatiter对象的元素也不难,如下所示:
 

In: b.flat[2]
  Out: 2

此外,还可以请求多个元素,如下所示:
 

 In: b.flat[[1,3]]
  Out: array([1, 3])

同时,还可以给flat属性赋值。不过,需要注意的是,这个值将会覆盖整个数组内所有元素的值,下面举例说明:
 

 In: b.flat = 7
  In: b
  Out:
  array([[7, 7],
      [7, 7]])

此外,还可以返回指定的元素,代码如下:
 

 In: b.flat[[1,3]] = 1
  In: b
  Out:
  array([[7, 1],
      [7, 1]])

图2-3是对ndarray各种属性的一个小结。

2.6.4 数组的转换

可以把NumPy数组转换成Python列表,使用tolist()函数(详见本书代码包中的arrayconversion.py文件)即可。下面简单解释一下:

转换成列表:
 

 In: b
  Out: array([ 1.+1.j, 3.+2.j])
  In: b.tolist()
  Out: [(1+1j), (3+2j)]

astype()函数可以把数组元素转换成指定类型,代码如下所示:
 

 In: b
  Out: array([ 1.+1.j, 3.+2.j])
  In: b.astype(int)
  /usr/local/bin/ipython:1: ComplexWarning: Casting complex 
  values to real discards the imaginary part
   #!/usr/bin/python
  Out: array([1, 3])
  In: b.astype('complex')
  Out: array([ 1.+1.j, 3.+2.j])

提示:
  当complex类型转换成int类型时,虚部将被丢弃。另外,还需要将数据类型的名称以字符串的形式传递给astype()函数。
上述代码没有显示警告信息,因为这次使用的是正确的数据类型。

时间: 2024-10-27 14:18:22

《Python数据分析》一2.6 处理数组形状的相关文章

《Python数据分析》一第2章 NumPy数组2.1 NumPy数组对象

第2章 NumPy数组 Python数据分析在前面部分,我们已经安装了NumPy和几个关键Python程序库,并动手编写了一些代码.在本章中,我们将正式步入NumPy数组的世界,带领大家一起学习NumPy和数组的知识.阅读本章后,你会对NumPy数组及其相关函数有个基本了解. 本章涉及的主题如下所示. 数据类型. 数组类型. 类型转换. 创建数组. 索引. 花式索引. 切片(Slicing). 处理数组的形状. 2.1 NumPy数组对象 NumPy中的多维数组称为ndarray,它有两个组成部

《Python数据分析》一导读

前 言 Python数据分析"数据分析是Python的杀手锏." --佚名 数据分析在自然科学.生物医学和社会科学领域有着悠久的历史.目前,如雷贯耳的大数据虽然尚没有严格的定义,但是它对数据分析工作的影响是毋庸置疑的.下面列举几个与大数据相关的趋势. 世界人口持续增长. 越来越多的数据被搜集和存储. 电脑芯片集成的晶体管数量不可能无限增长. 政府.科学界.工业界和个人对数据洞察力的需求与日俱增. 随着数据科学的炒作,数据分析也呈现流行之势.与数据科学类似,数据分析也致力于从数据中提取有

《Python数据分析与挖掘实战》一2.3 Python数据分析工具

2.3 Python数据分析工具 Python本身的数据分析功能不强,需要安装一些第三方扩展库来增强它的能力.本书用到的库有Numpy.Scipy.Matplotlib.Pandas.Scikit-Learn.Keras和Gensim等,下面将对这些库的安装和使用进行简单的介绍. 如果读者安装的是Anaconda发行版,那么它已经自带了以下库:Numpy.Scipy.Mat-plotlib.Pandas和Scikit-Learn. 本章主要是对这些库进行简单的介绍,在后面的章节中,会通过各种案例

numpy-大家谁能看懂这段代码?python数据分析的,求赐教!谢谢

问题描述 大家谁能看懂这段代码?python数据分析的,求赐教!谢谢 1.lines = [line.split('t') for line in open('路径/a.txt')] 2.# file colums 3.num=len(lines[0]) 4.# file rows 5.n=len(lines) 6.df = [[float(x) for x in line] for line in lines[1:]] 7.result=[] 8.import numpy 9.npdata=n

《Python数据分析与挖掘实战》一2.5 小结

2.5 小结 本章主要对Python进行简单介绍,包括软件安装.使用入门及相关注意事项和Python数据分析及挖掘相关工具箱.由于Python包含多个领域的扩展库,而且扩展库的功能也相当丰富,本章只介绍与数据分析及数据挖掘相关的一小部分,包括高维数组.数值计算.可视化.机器学习.神经网络和语言模型等.这些扩展库里面包含的函数在后续章节中会进行实例分析,通过在Python平台上完成实际案例来掌握数据分析和数据挖掘的原理,培养读者应用数据分析和挖掘技术解决实际问题的能力.

《Python数据分析》一第1章 Python程序库入门1.1 本书用到的软件

第1章 Python程序库入门 Python数据分析首先浏览一下http://www.xmind.net/m/WvfC/页面,从这里可以找到一幅描绘数据分析软件的脑图.很明显,我们不会在本章中安装本书所需的所有软件,而是介绍如何在不同的操作系统上面安装NumPy.SciPy.matplotlib和IPython,同时考察一些使用NumPy库的简单代码. NumPy是一个基础性的Python库,为我们提供了常用的数值数组和函数. SciPy是Python的科学计算库,对NumPy的功能进行了扩充,

python使用append合并两个数组的方法

  这篇文章主要介绍了python使用append合并两个数组的方法,涉及Python中append方法的使用技巧,需要的朋友可以参考下 本文实例讲述了python使用append合并两个数组的方法.分享给大家供大家参考.具体如下: ? 1 2 3 4 5 6 7 lista = [1,2,3] listb = [4,5,6] mergedlist =[] for elem in lista: mergedlist.append(elem) for elem in listb: mergedli

python数据分析时出现RunTimeError

问题描述 python数据分析时出现RunTimeError 我在做<Python fo Data Analysis>第8章地震危机数据处理的时候出现了以下错误信息,希望有大神帮忙分析一下. RuntimeError Traceback (most recent call last) <ipython-input-15-b85854eb74f4> in <module>() 80 cat_data = data[data['category_%s' % code] ==

《Python数据分析与挖掘实战》一第2章 Python数据分析简介

第2章 Python数据分析简介 Python是一门简单易学且功能强大的编程语言.它拥有高效的高级数据结构,并且能够用简单而又高效的方式进行面向对象编程.Python优雅的语法和动态类型,再结合它的解释性,使其在许多领域成为编写脚本或开发应用程序的理想语言. 要认识Python,首先得明确一点,Python是一门编程语言!这就意味着,原则上来说,它能够完成Matlab能够做的所有事情(因为大不了从头开始编写),而且在大多数情况下,同样功能的Python代码会比Matlab代码更加简洁.易懂:另一