当前位置: 移动技术网 > IT编程>脚本编程>Python > 荐 NumPy 快速入门:数组对象,数组属性,花式索引等基础介绍

荐 NumPy 快速入门:数组对象,数组属性,花式索引等基础介绍

2020年07月12日  | 移动技术网IT编程  | 我要评论
NumPy 快速入门:数组对象,数组属性,花式索引等基础介绍1、NumPy 简介:2、ndarray 数组对象:3、创建数组:4、数组的数据类型:5、数组的结构:6、数组的简单计算:7、数组切片与索引:8、数组的组合与切割:1、NumPy 简介:NumPy (Numerical Python的简称)是高性能科学计算和数据分析的基础包,是想利用 Python 进行数据分析人士必须了解的模块之一。由于各种原因 NumPy 模块并不是 Python 的标准模块,故需安装使用:pip install n

1、NumPy 简介:

NumPy (Numerical Python的简称)是高性能科学计算和数据分析的基础包,是想利用 Python 进行数据分析人士必须了解的模块之一。

由于各种原因 NumPy 模块并不是 Python 的标准模块,故需安装使用:

pip install numpy

导入 NumPy 模块时通常约定写成:

import numpy as np

numpy 主要功能:

  1. 提供 ndarray 对象:具有矢量算数运算和复杂广播能力的多维数组;
  2. 提供了许多可对数组对象直接运算的标准数学函数,而无需编写循环;
  3. 提供了用于读写磁盘数据的工具及用于操作内存映射文件的工具;
  4. 提供了线性代数、随机生成及傅里叶变换功能;
  5. 用于集成由 C 、C++、Fortran 等语言编写的代码的工具。

2、ndarray 数组对象:

ndarray 是指 NumPy 中的N维数组对象,是一个快速而灵活地大数据集容器。

3、创建数组:

array 函数: 可接收一切序列对象(包括其他数组对象),然后产生一个新的 NumPy 数组。

numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
参数 含义
object 数组或嵌套的数列
dtype 数组元素的数据类型,可选
copy 对象是否需要复制,可选
order 创建数组的样式,C为行方向,F为列方向,A为任意方向(默认)
subok 默认返回一个与基类类型一致的数组
ndmin 指定生成数组的最小维度

简单示例:

import numpy as np  # 导入模块,后面示例不再写

data = [6,7.5,8,0,1]
arr1 = np.array(data)
print(arr1)  # [6.  7.5  8.  0.  1. ]

接收一个嵌套序列:

data2 = [[1,2,3,4],[5,6,7,8]]
arr2 = np.array(data2)
print(arr2)
'''
[[1 2 3 4]
 [5 6 7 8]]
'''

解析: 除非设置数据类型(数据类型稍后会详细介绍),或者 array 函数会根据传入的序列选择适合的数据类型。

如,在上面 arr1 中,传入的列表中有 7.5 浮点数,所以创建的 arr1 数组类型为浮点型。

查看创建的数组数据类型:

print(arr1.dtype)  # float64
print(arr2.dtype)  # int32 或 int64 ,和安装的 Python 版本有关

其他创建数组的方法:

在这里插入图片描述
zeros 函数: 创建全 0 数组

# 创建一维数组
print(np.zeros(10))  # [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
# 创建多维数组
print(np.zeros((3,6)))  
'''
[[0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0.]]
'''

empty 函数:

print(np.empty((2,3,2)))
'''
[[[8.74e-322 0.00e+000]
  [0.00e+000 0.00e+000]
  [0.00e+000 0.00e+000]]

 [[0.00e+000 0.00e+000]
  [0.00e+000 0.00e+000]
  [0.00e+000 0.00e+000]]]
'''

arange 函数: 是 Python 内置函数 range 的数组版

# arange 函数
print(np.arange(15))  
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14]

eye 函数: 创建一个单位矩阵

print(np.eye(3,3))
'''
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
'''

4、数组的数据类型:

NumPy 的一个数组对象里所有的数据都是同质的,即数组内 数据类型一致

在这里插入图片描述
在这里插入图片描述
设置、查看数组对象数据类型:

arr3 = np.array([1,2,3],dtype=np.float)
arr4 = np.array([1,2,3],dtype=np.int)
print(arr3.dtype,arr4.dtype) 
# 打印结果
# float64 int32

转换数组数据类型:

arr5 = np.array([1,2,3,4,5])
print(arr5.dtype)  # int32
float_arr5 = arr5.astype(np.float)
print(float_arr5.dtype)  # float64

注:astype 会创建一个新的数组对象

自定义数据类型:

NumPy 也提供了自定义数组对象的数据类型方法。自定义数据类型是一种异构数据类型,可以当做记录一行数据的结构。
如:创建一个存储商店库存信息的数据类型,该库存信息有:商品名称、库存数量、商品价格。

# 创建数据类型
my_type = np.dtype([('name',np.str,40),('numitems',np.int),('price',np.float)])
print(my_type)  # [('name', '<U40'), ('numitems', '<i4'), ('price', '<f8')]

# 创建数组
my_array = np.array([('DVD',42,3.14),('Butter',13,2.72)],dtype= my_type)

# 查看数组数据类型
print(my_array.dtype)
# [('name', '<U40'), ('numitems', '<i4'), ('price', '<f8')]

5、数组的结构:

数组对象的结构指的是数组的维度、轴的概念。

查看数组结构:

b = np.arange(24)
print(b.shape) # (24,)

改变数组结构:

reshape 方法:生成一个新的数组对象。

c = b.reshape(2,3,4)  # 改变数组维度
print(c)
'''
[[[ 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(c.shape)  # (2, 3, 4)

resize 方法: 原位改变数组结构。

g = np.arange(6)
print(g.shape)  # (6,)
g.resize(2,3)  # 会在原位修改数组结构
print(g)
'''
[[0 1 2]
 [3 4 5]]
'''
print(g.shape)  # (2, 3)

注:reshape 方法和 resize 都可改变数组维度,但是 reshape 改变数组结构时,会产生一个新的数组对象;而 resize 则是直接修改原数组的维度。

数组的转置:

arr3 = np.arange(6).reshape(2,3)
print(arr3)
'''
[[0 1 2]
 [3 4 5]]
'''
arr4 = arr3.transpose()
print(arr4)
'''
[[0 3]
 [1 4]
 [2 5]]
'''

6、数组的简单计算:

NumPy 数组对象与 Python 原生序列最显著的区别之一就是在对序列中的数据执行批量运算,数组对象进行批量运算时,不需要编写循环可直接进行计算,及数组的矢量化

这样也令其在大量数据计算时,运行效率明显提升。

数组与标量之间的运算:

arr6 = np.array([[1,2,3],[4,5,6]],dtype=float)
print(arr6)
'''
[[1. 2. 3.]
 [4. 5. 6.]]
'''
# 加法
print(arr6 + 2)
'''
[[3. 4. 5.]
 [6. 7. 8.]]
'''

# 乘法:
print(arr6*0.5)
'''
[[0.5 1.  1.5]
 [2.  2.5 3. ]]
'''

数组与数组之间的运算:

大小相同的数组之间的任何算术运算都会讲运算应用到元素级:

# 减法
print(arr6-arr6)
'''
[[0. 0. 0.]
 [0. 0. 0.]]
'''
# 乘法
print(arr6*arr6)
'''
[[ 1.  4.  9.]
 [16. 25. 36.]]
'''

7、数组切片与索引:

一维数组的切片与索引:

arr7 = np.arange(10)
print(arr7)  # [0 1 2 3 4 5 6 7 8 9]
print(arr7[5]) # 5
print(arr7[5:8])  # [5 6 7]

以上操作的结果和 Python 列表切片索引操作现象一致。

切片赋值操作:

对一个切片对象赋值:

arr7[0] = 10
print(arr7)
# [10  1  2  3  4  5  6  7  8  9]

对切片组赋值:

arr7[5:8] = 12
print(arr7)
# [10  1  2  3  4 12 12 12  8  9]

注:当将一个标量值给一个切片时,该值会自动传播到整个选取,这是和Python列表切片最重要的区别 !

arr_slice = arr7[5:8]
arr_slice[1] = 12345
print(arr7)  
# [    0     1     2     3     4    12 12345    12     8     9]

arr_slice[:] = 64
print(arr7) # [ 0  1  2  3  4 64 64 64  8  9]

这是因为NumPy的设计目的是处理大数据,如要将数据多次复制(创建新的对象),会产生非常大的性能和内存问题。

高维数组的索引及切片:

二维数组:

arr2d = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(arr2d[2])  # [7 8 9]

# 以下两种方式效果一致
print(arr2d[0][2]) # 3
print(arr2d[0,2])  # 3

三维数组:

arr3d = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
print(arr3d)
print(arr3d.shape)  # (2, 2, 3)
'''
一个 2 x 2 x 3 数组
[[[ 1  2  3]
  [ 4  5  6]]

 [[ 7  8  9]
  [10 11 12]]]
'''

print(arr3d[0])
'''
[[1 2 3]
 [4 5 6]]
'''

标量值和数组都可被赋值给切片对象,如:

old_value = arr3d[0].copy() # 复制数组对象
arr3d[0] = 42
print(arr3d)
'''
[[[42 42 42]
  [42 42 42]]

 [[ 7  8  9]
  [10 11 12]]]
'''
arr3d[0] = old_value
print(arr3d)
'''
[[[ 1  2  3]
  [ 4  5  6]]

 [[ 7  8  9]
  [10 11 12]]]
'''
print(arr3d[1,0]) # [7 8 9]

布尔值切片:

这也是和 Python 原序列切片很大的不同之处,如:

先建立一个布尔序列:

names = np.array(['bob','joe','will','bob','will','joe','joe'])
# 数组的比较运算也是矢量化的,会产生一个布尔型数组
print(names == 'bob') 
# [ True False False  True False False False]

用布尔序列对数组进行切片操作:

data = np.random.rand(7,4) # 生成一些正态分布的随机数据
print(data)
'''
[[0.64831166 0.53764074 0.05100258 0.86194823]
 [0.75817438 0.68161727 0.23507438 0.06506362]
 [0.31393836 0.3548072  0.52740244 0.07263428]
 [0.03731951 0.3401235  0.25695301 0.08632226]
 [0.84201383 0.54950122 0.38923988 0.77718169]
 [0.14664734 0.59178141 0.62562549 0.2584329 ]
 [0.03764809 0.1270825  0.39032711 0.09212854]]
'''
# 布尔型数组可用于数组索引
print(data[names == 'bob'])
'''
[[0.64831166 0.53764074 0.05100258 0.86194823]
 [0.03731951 0.3401235  0.25695301 0.08632226]]
'''

注:布尔型数组的长度必须和被索引的轴长度一致。

布尔型数组也可以跟切片、整数混合使用:

print(data[names == 'bob', 2:])
'''
[[0.05100258 0.86194823]
 [0.25695301 0.08632226]]
'''
print(data[names == 'bob',3])
'''
[0.86194823 0.08632226]
'''

注意以下的一种用法:

# 将data中的所有小于0.5的值设置为0
data[data<0.5] = 0
print(data)
'''
[[0.64831166 0.53764074 0.         0.86194823]
 [0.75817438 0.68161727 0.         0.        ]
 [0.         0.         0.52740244 0.        ]
 [0.         0.         0.         0.        ]
 [0.84201383 0.54950122 0.         0.77718169]
 [0.         0.59178141 0.62562549 0.        ]
 [0.         0.         0.         0.        ]]
'''

这在实现筛选数据功能上非常方便!

花式索引:

花式索引:NumPy术语,指利用整数数组进行索引,如:

arr9 = np.empty((8,4))
for i in range(8):
    arr9[i] = i

print(arr9)
'''
[[0. 0. 0. 0.]
 [1. 1. 1. 1.]
 [2. 2. 2. 2.]
 [3. 3. 3. 3.]
 [4. 4. 4. 4.]
 [5. 5. 5. 5.]
 [6. 6. 6. 6.]
 [7. 7. 7. 7.]]
'''

print(arr9[[4,3,0,6]])
'''
[[4. 4. 4. 4.]
 [3. 3. 3. 3.]
 [0. 0. 0. 0.]
 [6. 6. 6. 6.]]
'''

使用负数会从末尾开始选取行:

print(arr9[[-1,-3,-7]])
[[7. 7. 7. 7.]
 [5. 5. 5. 5.]
 [1. 1. 1. 1.]]
'''

多个花式索引结合:

arr10 = np.arange(32).reshape((8,4))
print(arr10)
'''
[[ 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 27]
 [28 29 30 31]]
'''

print(arr10[[1,5,7,2],[0,3,1,2]]) # [ 4 23 29 10]

print(arr10[[1,5,7,2]][:,[0,3,1,2]])
'''
[[ 4  7  5  6]
 [20 23 21 22]
 [28 31 29 30]
 [ 8 11  9 10]]
'''

注:花式索引和切片不一样,它总是将数据复制到新数组中。

8、数组的组合与切割:

水平组合:

a1 = np.arange(9).reshape(3,3)
a2 = a1 * 2
a3 = np.hstack((a1,a2))
print(a3)
'''
[[ 0  1  2  0  2  4]
 [ 3  4  5  6  8 10]
 [ 6  7  8 12 14 16]]
'''

使用 concatenate 函数进行水平组合

a4 = np.concatenate((a1,a2),axis=1)
print(a4)
'''
[[ 0  1  2  0  2  4]
 [ 3  4  5  6  8 10]
 [ 6  7  8 12 14 16]]
'''

垂直组合:

# 垂直组合
a5 = np.vstack((a1,a2))
print(a5)
'''
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 0  2  4]
 [ 6  8 10]
 [12 14 16]]
'''
# 使用 concatenate 函数进行垂直组合
a6 = np.concatenate((a1,a2),axis=0)
print(a6)
'''
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 0  2  4]
 [ 6  8 10]
 [12 14 16]]
'''

深度组合:

a7 = np.dstack((a1,a2))
print(a7)
'''
[[[ 0  0]
  [ 1  2]
  [ 2  4]]

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

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

注:深度组合,改变了数组的维度。

print(a1.shape,a2.shape,a7.shape)  
# (3, 3) (3, 3) (3, 3, 2)

列组合:

# 列组合
b1 = np.arange(2)
b2 = b1 * 2
b3 = np.column_stack((b1,b2))
print(b3)
'''
[[0 0]
 [1 2]]
'''
# 注意一维数组的列组合与水平组合的区别
b4 = np.hstack((b1,b2))
print(b4)
'''
[0 1 0 2]
'''
# 对于二维数组,列组合与水平组合效果相同
b5 = np.column_stack((a1,a2))
print(b5)
'''
[[ 0  1  2  0  2  4]
 [ 3  4  5  6  8 10]
 [ 6  7  8 12 14 16]]
'''

注:对于二维数组,列组合与水平组合效果相同。

行组合:

# 行组合
b6 = np.row_stack((b1,b2))
print(b6)
'''
[[0 1]
 [0 2]]
'''
# 同样需注意一维数组的行组合与垂直组合的区别
# 对于二维数组,行组合与垂直组合效果一致
b6 = np.row_stack((a1,a2))
print(b6)
'''
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 0  2  4]
 [ 6  8 10]
 [12 14 16]]
'''

数组分割:

对应数组的组合,也包括数组的水平分割、垂直分割、深度分割。

c1 = np.arange(9).reshape(3,3)
print(c1)
'''
[[0 1 2]
 [3 4 5]
 [6 7 8]]
'''

# 水平分割
c2 = np.hsplit(c1,3)
print(c2)
'''
[array([[0],
       [3],
       [6]]), array([[1],
       [4],
       [7]]), array([[2],
       [5],
       [8]])]
'''
print(type(c2)) # 获得一个包含数组的列表
# <class 'list'>
# split 函数进行水平分割
c3 = np.split(c1,3,axis=1)
print(c3)
'''
[array([[0],
       [3],
       [6]]), array([[1],
       [4],
       [7]]), array([[2],
       [5],
       [8]])]
'''

# 垂直分割
c4 = np.vsplit(c1,3)
print(c4)
'''
[array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]
'''
# 同样也可以用 split 函数实现垂直分割
c5 = np.split(c1,3,axis=0)
print(c5)  # [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]

# 深度分割
d1 = np.arange(27).reshape(3,3,3)
print(d1)
'''
[[[ 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]]]
'''
print(d1.shape)  # (3, 3, 3)

d2 = np.dsplit(d1,3)
print(d2)
'''
[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]]])]
'''
for d_ in d2:
    print(d_.shape)

# 深度分割将一个 3x3x3 数组切割为一个包含3个 3x3x1 数组的列表
'''
(3, 3, 1)
(3, 3, 1)
(3, 3, 1)
'''

9、数组的属性:

ndim 获取数组维度或轴个数:

e1 = np.arange(24).reshape(2,12)
print(e1)
'''
[[ 0  1  2  3  4  5  6  7  8  9 10 11]
 [12 13 14 15 16 17 18 19 20 21 22 23]]
'''
# ndim 获取数组维度或轴个数
print(e1.ndim)  # 2

size 获取数组元素总个数:

print(e1.size)  # 24

itemsize 获取数组中元素在内存中所占字节数:

print(e1.itemsize)  # 4

nbytes 获取数组对象所占储存空间:

print(e1.nbytes)  # 96

注:总是等于 itemsize 值与 size 值的乘积。

flat 获取数组对象的扁平迭代器(flatiter):

e2 = np.arange(9).reshape(3,3)
print(e2)
'''
[[0 1 2]
 [3 4 5]
 [6 7 8]]
'''
e_flat = e2.flat # 这是获取 flatiter 对象的唯一方式
print(e_flat)  # <numpy.flatiter object at 0x000000000A1306C0>

for item in e_flat:
    print(item,end=',')
# 0,1,2,3,4,5,6,7,8,

结尾:

以上就是本篇博客全部内容,感谢阅读。

本文地址:https://blog.csdn.net/zhouz92/article/details/107250364

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网