欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-05-07 16:57:51
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 版本有关

其他创建数组的方法:

荐
                                                        NumPy 快速入门:数组对象,数组属性,花式索引等基础介绍
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 的一个数组对象里所有的数据都是同质的,即数组内 数据类型一致

荐
                                                        NumPy 快速入门:数组对象,数组属性,花式索引等基础介绍
荐
                                                        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