1、NumPy数组对象

NumPy中的 ndarray 是一个多维数组对象,该对象由两部分组成:

实际的数据;

描述这些数据的元数据;

大部分的数组操作仅仅修改元数据部分,而不改变底层的实际数据。

 ndarray 支持更高的维度的数组。

NumPy数组一般是同质的(但有一种特殊的数组类型例外,它是异质的),即数组中的所有元素类型必须是一致的。这样有一个好处:如果我们知道数组中的元素均为同一类型,该数组所需的存储空间就很容易确定下来。

与Python中一样,NumPy数组的下标也是从 0 开始的。数组元素的数据类型用专门的对象表示。

2、np.arange()创建一维数组

# coding=utf-8
import numpy as np

#NumPy创建0~4的数组
a = np.arange(5)
print("a的值为:",a)

#查看a的数据类型
print("a的类型为:",a.dtype)

#输出a的向量的维度
print("a的向量的维度为:",a.shape)

输出:

a的值为: [0 1 2 3 4]
a的类型为: int32
a的向量的维度为: (5,)

 这是一个包含5个元素的向量,取值分别为0~4的整数。

使用32位的Python,得到的结果是 int32。

数组的 shape 属性返回一个元组(tuple),元组中的元素即为NumPy数组每一个维度上的大小。

上面例子中的数组是一维的,因此元组中只有一个元素。

3、创建多维数组

# coding=utf-8
import numpy as np

#创建一个二维数组
#将 arange 函数创建的数组作为列表元素,把这个列表作为参数传给 array 函数,从而创建了一个2×2的数组
m = np.array([np.arange(2),np.arange(2)])
print("m的值为:",m)

print("m的类型为:",m.dtype)

print("m的向量维度为:",m.shape)

 输出为:

m的值为: [[0 1]
 [0 1]]
m的类型为: int32
m的向量维度为: (2, 2)

 array 函数可以依据给定的对象生成数组。给定的对象应是类数组,如Python中的列表。在上面的例子中,我们传给 array 函数的对象是一个NumPy数组的列表。像这样的类数组对象是array 函数的唯一必要参数,其余的诸多参数均为有默认值的可选参数。

4、选取数组元素

# coding=utf-8
import numpy as np

#创建二维数组,注意外层还有一个中括号,否则无法解析类型
a = np.array([[1,2],[3,4]])
'''
1 2
3 4
'''
print(a[0,0], end='')
print(a[0,1])
print(a[1,0], end='')
print(a[1,1])

注意查看数据时,并不是a[0][0]这样,而是a[0,0]这样。

输出为:

12
34

5、NumPy 数据类型

Python支持的数据类型有整型、浮点型以及复数型,但这些类型不足以满足科学计算的需求,因此NumPy添加了很多其他的数据类型。在实际应用中,我们需要不同精度的数据类型,它们占用的内存空间也是不同的。在NumPy中,大部分数据类型名是以数字结尾的,这个数字表示其在内存中占用的位数。

bool
用一位存储的布尔类型(值为 TRUE 或 FALSE )
inti
由所在平台决定其精度的整数(一般为 int32 或 int64 )
int8
整数,范围为128至127
int16
整数,范围为32 768至32 767
int32
整数,范围为2 31 至2 31 1
int64
整数,范围为2 63 至2 63 1
uint8
无符号整数,范围为0至255
uint16
无符号整数,范围为0至65 535
uint32
无符号整数,范围为0至2 32 1
uint64
无符号整数,范围为0至2 64 1
float16
半精度浮点数(16位):其中用1位表示正负号,5位表示指数,10位表示尾数
float32
单精度浮点数(32位):其中用1位表示正负号,8位表示指数,23位表示尾数
float64 或 float 双精度浮点数(64位):其中用1位表示正负号,11位表示指数,52位表示尾数
complex64
复数,分别用两个32位浮点数表示实部和虚部
complex128 或 complex 复数,分别用两个64位浮点数表示实部和虚部

 在NumPy中,许多函数的参数中可以指定数据类型,通常这个参数是可选的。

6、数据类型对象

#数据类型对象可以给出单个数组元素在内存中占用的字节数 print(a.dtype.itemsize)

7、 动手实践:创建自定义数据类型

# coding=utf-8
import numpy as np

#自定义商品库存的数据类型(商品名称、商品个数、商品价格)
t = np.dtype([('name',str,40),('numitems',int),('price',float)])

#输出类型
print(t)

#查看某个字段的数据类型
print(t['name'])

items = np.array([('小猪佩奇',20,3.5),('白酒',30,80.5),('LOL俄洛依皮肤',1,210.5)])

#没有指定数据类型,默认价格为浮点数类型
print(items)

#指定数据类型
items2 = np.array([('小猪佩奇',20,3.5),('白酒',30,80.5),('LOL俄洛依皮肤',1,210.5)],dtype=t)
print(items2)

 输出为:

[('name', '<U40'), ('numitems', '<i4'), ('price', '<f8')]
<U40
[['小猪佩奇' '20' '3.5']
 ['白酒' '30' '80.5']
 ['LOL俄洛依皮肤' '1' '210.5']]
[('小猪佩奇', 20,    3.5) ('白酒', 30,   80.5) ('LOL俄洛依皮肤',  1,  210.5)]

我们创建了一种自定义的异构数据类型,该数据类型包括一个用字符串记录的名字、一个用整数记录的数字以及一个用浮点数记录的价格。

8、一维数组的索引和切片

# coding=utf-8
import numpy as np

#创建0~8的数组
a = np.arange(9)

#用下标 3 ~ 7 来选取元素 3 ~ 6
print(a[3:7])

#也可以用下标 0 ~ 7 ,以 2 为步长选取元素
print(a[:7:2])

#和Python中一样,我们也可以利用负数下标翻转数组
print(a[::-1])

输出为:

[3 4 5 6]
[0 2 4 6]
[8 7 6 5 4 3 2 1 0]

 9、多维数组的索引和切片

# coding=utf-8
import numpy as np

#用 arange 函数创建一个数组并改变其维度,使之变成一个三维数组
#reshape 函数的作用是改变数组的“形状”,也就是改变数组的维度,其参数为一个正整数元组,分别指定数组在每个维度上的大小。
a = np.arange(24).reshape(2,3,4)

#查看各维度
print(a.shape)

#多维数组 b 中有 0 ~ 23 的整数,共 24 个元素,是一个2×3×4的三维数组
#我们可以形象地把它看做一个两层楼建筑,每层楼有12个房间,并排列成3行4列。
print(a)

#我们可以用三维坐标来选定任意一个房间,即楼层、行号和列号。例如,选定第1层楼、第1行、第1列的房间(也可以说是第0层楼、第0行、第0列,这只是习惯问题)
print(a[0,0,0])

#如果我们不关心楼层,也就是说要选取所有楼层的第1行、第1列的房间,那么可以将第1个下标用英文标点的冒号 : 来代替
print(a[:,0,0])

#我们还可以这样写,选取第1层楼的所有房间
print(a[0,:,:])

#多个冒号可以用一个省略号( ... )来代替,因此上面的代码等价于
print(a[0, ...])

#进而可以选取第1层楼、第2排的所有房间
print(a[0,1])

#再进一步,我们可以在上面的数组切片中间隔地选定元素
print(a[0,1,::2])

#如果要选取所有楼层的位于第2列的房间,即不指定楼层和行号,用如下代码即可
print(a[...,1])

#类似地,我们可以选取所有位于第2行的房间,而不指定楼层和列号:
print(a[:,1])

#如果要选取第1层楼的所有位于第2列的房间,在对应的两个维度上指定即可
print(a[0,:,1])

#如果要选取第1层楼的最后一列的所有房间,使用如下代码
print(a[0,:,-1])

#如果要反向选取第1层楼的最后一列的所有房间,使用如下代码
print(a[0,::-1,-1])

#在该数组切片中间隔地选定元素
print(a[0,::2,-1])

#如果在多维数组中执行翻转一维数组的命令,将在最前面的维度上翻转元素的顺序,在我们的例子中将把第1层楼和第2层楼的房间交换
print(a[::-1])

输出为:

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

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
0
[ 0 12]
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[4 5 6 7]
[4 6]
[[ 1  5  9]
 [13 17 21]]
[[ 4  5  6  7]
 [16 17 18 19]]
[1 5 9]
[ 3  7 11]
[11  7  3]
[ 3 11]
[[[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]

 [[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]]

9、改变数组的维度 

用 ravel 、 flatten 、 reshape 和 resize 函数对NumPy数组的维度进行修改

# coding=utf-8
import numpy as np

#创建数据并标识维度
a = np.arange(24).reshape(2,3,4)

print(a)

#ravel函数将数组展平,不过不分配内存,只是起到显示的作用
print(a.ravel())

#flatten函数将数组展平,与ravel函数功能相同,不过, flatten 函数会请求分配内存来保存结果,而 ravel 函数只是返回数组的一个视图(view)
print(a.flatten())

#用元组设置维度,除了可以使用 reshape 函数,我们也可以直接用一个正整数元组来设置数组的维度
a.shape = (6,4)
print(a)

# transpose转置矩阵
print(a.transpose())

# resize 和 reshape 函数的功能一样,但 resize 会直接修改所操作的数组
a.resize(2,12)
print(a)

输出为:

[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]
 [16 17 18 19]
 [20 21 22 23]]
[[ 0  4  8 12 16 20]
 [ 1  5  9 13 17 21]
 [ 2  6 10 14 18 22]
 [ 3  7 11 15 19 23]]
[[ 0  1  2  3  4  5  6  7  8  9 10 11]
 [12 13 14 15 16 17 18 19 20 21 22 23]]

 10、数组的组合

NumPy数组有水平组合、垂直组合和深度组合等多种组合方式,我们将使用 vstack 、dstack 、 hstack 、 column_stack 、 row_stack 以及 concatenate 函数来完成数组的组合。

# coding=utf-8
import numpy as np

a = np.arange(9).reshape(3,3)
print(a)

b = a * 2
print(b)
print()
'''
1、水平组合
将 ndarray 对象构成的元组作为参数,传给hstack 函数
'''
print("水平组合方法一:")
print(np.hstack((a,b)))
#也可以用 concatenate 函数来实现同样的效果
print("水平组合方法二:")
print(np.concatenate((a,b),axis = 1))
print()

'''
2、垂直组合
垂直组合同样需要构造一个元组作为参数,只不过这次的函数变成了vstack
'''
print("垂直组合方法一:")
print(np.vstack((a,b)))
#同样,我们将 concatenate 函数的 axis 参数设置为0即可实现同样的效果。这也是 axis 参数的默认值
print("垂直组合方法二:")
print(np.concatenate((a,b),axis = 0))
print()

'''
3、深度组合
将相同的元组作为参数传给 dstack 函数,即可完成数组的深度组合。
所谓深度组合,就是将一系列数组沿着纵轴(深度)方向进行层叠组合。
举个例子,有若干张二维面内的图像点阵数据,我们可以将这些图像数据沿纵轴方向层叠在一起,这就形象地解释了什么是深度组合。
'''
print("垂直组合方法:")
print(np.dstack((a,b)))
print()

'''
4、列组合
column_stack 函数对于一维数组将按列方向进行组合
'''
print("列组合:")
oned = np.arange(2)
print(oned)
twice_oned = 2 * oned
print(twice_oned)
print(np.column_stack((oned,twice_oned)))
#而对于二维数组, column_stack 与 hstack 的效果是相同的
print(np.column_stack((a,b)))
#我们可以用 == 运算符来比较两个NumPy数组
print(np.column_stack((a,b)) == np.hstack((a,b)))

'''
5、行组合
 row_stack对于两个一维数组,将直接层叠起来组合成一个二维数组。
'''
print("行组合:")
print(np.row_stack((oned,twice_oned)))
#对于二维数组, row_stack 与 vstack 的效果是相同的
print(np.row_stack((a,b)))

结果:

[[0 1 2]
 [3 4 5]
 [6 7 8]]
[[ 0  2  4]
 [ 6  8 10]
 [12 14 16]]

水平组合方法一:
[[ 0  1  2  0  2  4]
 [ 3  4  5  6  8 10]
 [ 6  7  8 12 14 16]]
水平组合方法二:
[[ 0  1  2  0  2  4]
 [ 3  4  5  6  8 10]
 [ 6  7  8 12 14 16]]

垂直组合方法一:
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 0  2  4]
 [ 6  8 10]
 [12 14 16]]
垂直组合方法二:
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 0  2  4]
 [ 6  8 10]
 [12 14 16]]

垂直组合方法:
[[[ 0  0]
  [ 1  2]
  [ 2  4]]

 [[ 3  6]
  [ 4  8]
  [ 5 10]]

 [[ 6 12]
  [ 7 14]
  [ 8 16]]]

列组合:
[0 1]
[0 2]
[[0 0]
 [1 2]]
[[ 0  1  2  0  2  4]
 [ 3  4  5  6  8 10]
 [ 6  7  8 12 14 16]]
[[ True  True  True  True  True  True]
 [ True  True  True  True  True  True]
 [ True  True  True  True  True  True]]
行组合:
[[0 1]
 [0 2]]
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 0  2  4]
 [ 6  8 10]
 [12 14 16]]

 11、数组的分割

NumPy数组可以进行水平、垂直或深度分割,相关的函数有 hsplit 、 vsplit 、 dsplit 和split 。

我们可以将数组分割成相同大小的子数组,也可以指定原数组中需要分割的位置。

# coding=utf-8
import numpy as np
a = np.arange(9).reshape(3,3)

print(a)

print("水平分割:")
#下面的代码将把数组沿着水平方向分割为3个相同大小的子数组
print(np.hsplit(a,3))
#调用 split 函数并在参数中指定参数 axis=1 ,结果一样
print(np.split(a,3,axis = 1))
print()

#vsplit 函数将把数组沿着垂直方向分割
print("垂直分割:")
print(np.vsplit(a,3))
#同样,调用 split 函数并在参数中指定参数 axis=0 ,也可以得到同样的结果
print(np.split(a,3,axis = 0))
print()

#dsplit 函数将按深度方向分割数组
print("深度分割")
c = np.arange(27).reshape(3,3,3)
print(c)
print(np.dsplit(c,3))

结果为:

[[0 1 2]
  [3 4 5]
  [6 7 8]]
 水平分割:
 [array([[0],
        [3],
        [6]]), array([[1],
        [4],
        [7]]), array([[2],
        [5],
        [8]])]
 [array([[0],
        [3],
        [6]]), array([[1],
        [4],
        [7]]), array([[2],
        [5],
        [8]])]垂直分割:
 [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]
 [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]深度分割
 [[[ 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]]]
 [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]]])]


 

 12、数组的属性

# coding=utf-8
import numpy as np

a = np.arange(24).reshape(2,12)

print(a)

#ndim 属性,给出数组的维数,或数组轴的个数
print("a的维度为:",a.ndim)

# size 属性,给出数组元素的总个数
print("a的元素个数为:",a.size)

#itemsize 属性,给出数组中的每个元素在内存中所占的字节数
print("a的元素占用内存字节数:",a.itemsize)

#整个数组所占的存储空间,可以用 nbytes 属性来查看。这个属性的值其实就是 itemsize 和 size 属性值的乘积
print("a所有元素所占存储空间:",a.nbytes)

# flat 属性将返回一个 numpy.flatiter 对象,这是获得 flatiter 对象的唯一方式
# 我们无法访问 flatiter 的构造函数。
# 这个所谓的“扁平迭代器”可以让我们像遍历一维数组一样去遍历任意的多维数组
b = np.arange(4).reshape(2,2)
print(b)
f = b.flat
for item in f:
    print(item,end='')

print()
#还可以用 flatiter 对象直接获取一个数组元素
print(a.flat[2])
#获取多个元素
print(a.flat[[1,3]])
#flat 属性是一个可赋值的属性。对 flat 属性赋值将导致整个数组的元素都被覆盖
b.flat = 7
print(b)
b.flat[[1,3]] = 1
print(b)

输出为:

[[ 0  1  2  3  4  5  6  7  8  9 10 11]
  [12 13 14 15 16 17 18 19 20 21 22 23]]
 a的维度为: 2
 a的元素个数为: 24
 a的元素占用内存字节数: 4
 a所有元素所占存储空间: 96
 [[0 1]
  [2 3]]
 0123
 2
 [1 3]
 [[7 7]
  [7 7]]
 [[7 1]
  [7 1]]

 13、数组转换成列表

c = np.arange(4)
#将NumPy数组转换成Python列表
c.tolist()
print(c)
#astype函数可以在转换的时候指定数据类型
c.astype(int)
print(c)

输出:

[0 1 2 3]
 [0 1 2 3]