【上篇】NumPy简介

本文详细介绍了NumPy库的基础,包括安装步骤、ndarray对象的使用、数据类型、数组属性、创建数组、切片与索引(整数、布尔和花式)、广播机制,以及如何利用迭代器进行高效操作。深入理解了如何控制遍历顺序和修改数组元素,适合初学者和进阶者学习。
摘要由CSDN通过智能技术生成


1 Numpy简介

NumPy是Python的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。

NumPy用于数组计算,通常与SciPy和Matplotlib一起使用。


2 Numpy安装

从Python官网下载的Python程序,安装在电脑上后,内部的模块中没有Numpy,需要自己去安装。

在WIN10电脑打开的情况下,同时按Windows键和R键,在对话框输入cmd,按确定后打开cmd命令行,输入:

pip install numpy

通常下载较慢,安装好Numpy后的显示内容为:
在这里插入图片描述
打开Python解释器,输入下面内容

>>> import numpy as np
>>> np.eye(3)
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])

和下面的图片显示一样就是成功了。eye(4)生成的是对角矩阵:
在这里插入图片描述


3 Ndarray对象

N维数组对象ndarray,是一系列同类型数据的集合,用于存放同类型元素的多维数组。创建一个ndarray只需调用NumPy的array函数即可:

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
>>> a = np.array([1,2,3])
>>> print(a)
[1 2 3]
>>>
>>> a = np.array([[1,2],[3,4]]) # 二维数组
>>> print(a)
[[1 2]
 [3 4]]
>>>
>>> a = np.array([1,2,3],dtype=complex)
>>> print(a)
[1.+0.j 2.+0.j 3.+0.j]

ndarray对象由计算机内存的连续一维部分组成,并结合索引模式,将每个元素映射到内存块中的一个位置。内存块以行顺序或列顺序来保存元素。


4 NumPy数据类型

下表列举了常用NumPy基本类型:

名称描述
bool_布尔型数据类型(True或者False)
int_默认的整数类型(类似于C语言中的long,int32或int64)
int8字节(-128to127)
uint8无符号整数(0to255)
float16半精度浮点数,包括:1个符号位,5个指数位,10个尾数位

数据类型对象(numpy.dtype类的实例)用来描述与数组对应的内存区域是如何使用,示例代码片段:

import numpy as np

dt=np.dtype(np.int32)
print(dt)

输出:

int32

这里省略了很多内容,点击这里查看。


5 数组属性

NumPy的数组中比较重要的ndarray对象属性有:

属性说明
ndarray.ndim秩,即维度的数量
ndarray.shape数组的维度,如对于矩阵就是n行m列
ndarray.size数组元素的总个数,相当于.shape中n*m的值
ndarray.dtypendarray对象的元素类型
ndarray.itemsizendarray对象中每个元素的大小,以字节为单位
ndarray.flagsndarray对象的内存信息
ndarray.realndarray元素的实部
ndarray.imagndarray元素的虚部

示例代码如下:

import numpy as np

a=np.array([[1,2],[3,4]])
print(a.ndim)

输出:

2

ndarray.shape表示数组的维度,返回一个元组,这个元组的长度就是维度的数目,即ndim属性(秩)。比如,一个二维数组,其维度表示"行数"和"列数"。ndarray.shape可以用于调整数组大小,另外也可以使用reshape函数来调整数组大小。

>>> import numpy as np
>>>
>>> a=np.array([[1,2,3],[3,4,6]])
>>> print('数组维度如下:')
数组维度如下:
>>> print(a.shape)
(2, 3)
>>>
>>> a.shape=(3,2)
>>> print('调整为三行两列:')
调整为三行两列:
>>> print(a)
[[1 2]
 [3 3]
 [4 6]]
>>>
>>> b=a.reshape(2,3)
>>> b #又变回来了
array([[1, 2, 3],
       [3, 4, 6]])

6 创建数组

numpy.zeros创建指定大小的数组,数组元素以0来填充:

numpy.zeros(shape,dtype=float,order='C')

参数说明:

参数描述
shape数组形状
dtype数据类型,可选
order'C’用于C的行数组,或者’F’用于FORTRAN的列数组

示例代码如下:

import numpy as np

x=np.zeros((3,2)) #默认为浮点数
print(x)

输出:

[[0. 0.]
 [0. 0.]
 [0. 0.]]

numpy.ones创建指定形状的数组,数组元素以1来填充:

numpy.ones(shape,dtype=None,order='C')

示例代码如下:

import numpy as np

x=np.ones((3,2),dtype=int) #默认为浮点数,这里修改参数为int型
print(x)

输出:

[[1 1]
 [1 1]
 [1 1]]

可以从已有的数组创建ndarray数组。

>>> import numpy as np
>>>
>>> a=np.array([3,4,5])
>>> a
array([3, 4, 5])

numpy使用arange函数创建数值范围并返回ndarray对象,函数格式如下:

numpy.arange(start,stop,step,dtype)

参数说明:

参数描述
start起始值,默认为0
stop终止值(不包含该值)
step步长,默认为1
dtype返回ndarray的数据类型,如果没有提供,则会使用输入数据的类型。

示例代码如下:

>>> import numpy as np
>>>
>>> x=np.arange(5)
>>> print(x)
[0 1 2 3 4]

设置返回类型位float:

>>> import numpy as np
>>>
>>> x=np.arange(5,dtype=float)
>>> print(x)
[0. 1. 2. 3. 4.]

设置起始值、终止值及步长:

>>> import numpy as np
>>>
>>> x=np.arange(1,10,2)
>>> print(x)
[1 3 5 7 9]

numpy.linspace函数用于创建一个一维数组,数组是一个等差数列构成的,格式如下:

np.linspace(start,stop,num=50,endpoint=True,retstep=False,dtype=None)

参数说明:

参数描述
start序列的起始值
stop序列的终止值,如果endpoint为true,该值包含于数列中
num要生成的等步长的样本数量,默认为50
endpoint该值为true时,数列中包含stop值,反之不包含,默认是True。
retstep如果为True时,生成的数组中会显示间距,反之不显示。
dtypendarray的数据类型

以下实例用到三个参数,设置起始点为4,终止点为20,数列个数为5:

>>> import numpy as np
>>>
>>> x=np.linspace(4,20,5)
>>> print(x)
[ 4.  8. 12. 16. 20.]

将endpoint设为false,不包含终止值:

>>> import numpy as np
>>>
>>> x=np.linspace(4,20,4,endpoint=False)
>>> print(x)
[ 4.  8. 12. 16.]

numpy.logspace函数用于创建一个等比数列。格式如下:

np.logspace(start,stop,num=50,endpoint=True,base=10.0,dtype=None)

base参数意思是取对数的时候log的下标。

参数描述
start序列的起始值为:base的start次方,即base^start
stop序列的终止值为:base^stop。如果endpoint为true,该值包含于数列中
num要生成的等步长的样本数量,默认为50
endpoint该值为true时,数列中中包含stop值,反之不包含,默认是True。
base对数log的底数。
dtypendarray的数据类型

示例代码如下:

>>> import numpy as np
>>>
>>> x=np.logspace(1,2,num=10) #默认底数是10
>>> print(x)
[ 10.          12.91549665  16.68100537  21.5443469   27.82559402
  35.93813664  46.41588834  59.94842503  77.42636827 100.        ]

将对数的底数设置为2:

>>> import numpy as np
>>>
>>> x=np.logspace(0,9,10,base=2)
>>> print(x)
[  1.   2.   4.   8.  16.  32.  64. 128. 256. 512.]

7 切片和索引

ndarray对象的内容可以通过索引或切片来访问和修改,与Python中list的切片操作一样。ndarray数组可以基于0-n的下标进行索引,切片对象可以从原数组中切割出一个新数组。示例代码如下:

>>> import numpy as np
>>>
>>> x=np.arange(10)
>>> print(x)
[0 1 2 3 4 5 6 7 8 9]
>>> print(x[2:7])
[2 3 4 5 6]

多维数组同样适用上述索引提取方法:

>>> import numpy as np
>>>
>>> a=np.array([[1,2],[3,4],[5,6]])
>>> print('从数组索引a[1:]处开始切割')
从数组索引a[1:]处开始切割
>>> print(a[1:])
[[3 4]
 [5 6]]

NumPy除了用整数和切片的索引外,还有整数数组索引、布尔索引及花式索引。

7.1 整数数组索引

以下实例获取数组中(0,0),(1,1)和(2,0)位置处的元素。

import numpy as np

x=np.array([[1,2],[3,4],[5,6]])
y=x[[0,1,2],[0,1,0]]
print(y)

输出:

[1 4 5]

以下实例获取了4×3数组中的四个角的元素。行索引是[0,0]和[3,3],而列索引是[0,2]和[0,2]。

import numpy as np

x=np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11]])
print('原始数组为:')
print(x)
print('------')

rows=np.array([[0,0],[3,3]])
cols=np.array([[0,2],[0,2]])
y=x[rows,cols]
print('该数组的四个角元素为:')
print(y)

输出:

原始数组为:
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
------
该数组的四个角元素为:
[[ 0  2]
 [ 9 11]]

可以借助切片:与索引数组组合。如下面例子:

import numpy as np

x=np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11]])
print('原始数组为:')
print(x)
print('------')

y=x[1:3,2] #行号是1、2,不包括3,列号是2
print(y)

输出:

原始数组为:
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
------
[5 8]

7.2 布尔索引

可以通过一个布尔数组来索引目标数组:布尔索引通过布尔运算(如比较运算符)来获取符合指定条件的元素的数组。

import numpy as np

x=np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11]])
print('原始数组为:')
print(x)
print('------')

print('大于5的元素是:')
print(x[x>5])

输出:

原始数组为:
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
------
大于5的元素是:
[ 6  7  8  9 10 11]

以下实例演示如何从数组中过滤掉非复数元素:

import numpy as np

x=np.array([1,2+6j,5,3+5j])
print(x[np.iscomplex(x)])

输出:

[2.+6.j 3.+5.j]

7.3 花式索引

花式索引的名称和概念都很迷,不做详细介绍,明白怎么用就行,花式索引跟切片不一样,它总是将数据复制到新数组中。

1、传入顺序索引数组

import numpy as np

x=np.arange(32).reshape((8,4))
print('原始数组为:')
print(x)
print('------')

print(x[[4,2,1,7]])

输出:

原始数组为:
[[ 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]]
------
[[16 17 18 19]
 [ 8  9 10 11]
 [ 4  5  6  7]
 [28 29 30 31]]

2、传入倒序索引数组

import numpy as np

x=np.arange(32).reshape((8,4))
print('原始数组为:')
print(x)
print('------')

print(x[[-4,-2,-1,-7]])

输出:

原始数组为:
[[ 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]]
------
[[16 17 18 19]
 [24 25 26 27]
 [28 29 30 31]
 [ 4  5  6  7]]

3、传入多个索引数组(要使用np.ix_)

import numpy as np

x=np.arange(32).reshape((8,4))
print('原始数组为:')
print(x)
print('------')

print(x[np.ix_([1,5,7,2],[0,3,1,2])])

输出:

原始数组为:
[[ 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]]
------
[[ 4  7  5  6]
 [20 23 21 22]
 [28 31 29 30]
 [ 8 11  9 10]]

8 广播

广播(Broadcast)是numpy对不同形状(shape)的数组进行数值计算的方式,对数组的算术运算通常在相应的元素上进行。如果两个数组a和b形状相同,即满足a.shape==b.shape,那么a*b的结果就是a与b数组对应位相乘。这要求维数相同,且各维度的长度相同。

import numpy as np

a=np.array([1,2,3,4])
b=np.array([10,20,30,40])
c=a*b
print(c)

输出:

[ 10  40  90 160]

当运算中的2个数组的形状不同时,numpy将自动触发广播机制。如:

import numpy as np

x=np.array([[0,1,2],
            [3,4,5],
            [6,7,8],
            [9,10,11]])

y=np.array([1,2,3])

print(x+y)

输出:

[[ 1  3  5]
 [ 4  6  8]
 [ 7  9 11]
 [10 12 14]]

9 迭代数组

NumPy迭代器对象numpy.nditer提供了一种灵活访问一个或多个数组元素的方式。下面使用arange()函数创建一个2×3数组,并使用nditer对它进行迭代。

import numpy as np

a=np.arange(6).reshape(2,3)
print('原始数组为:')
print(a)
print('------')
print('迭代输出元素:')
for x in np.nditer(a):
    print(x,end=',')

输出:

原始数组为:
[[0 1 2]
 [3 4 5]]
------
迭代输出元素:
0,1,2,3,4,5,

以上实例的顺序是和数组内存布局一致的,这样做是为了提升访问的效率,默认是行序优先。这反映了默认情况下只需访问每个元素,而无需考虑其特定顺序。可以通过迭代上述数组的转置来看到这一点,并与以C顺序访问数组转置的copy方式做对比,如下实例:

import numpy as np

a=np.arange(6).reshape(2,3)
print('原始数组为:')
print(a)
print('------')

for x in np.nditer(a.T):
    print(x,end=',')
print('\n------')
for x in np.nditer(a.T.copy(order='C')):
    print(x,end=',')

输出:

原始数组为:
[[0 1 2]
 [3 4 5]]
------
0,1,2,3,4,5,
------
0,3,1,4,2,5,

从上述例子可以看出,a和a.T的遍历顺序是一样的,也就是他们在内存中的存储顺序也是一样的,但是a.T.copy(order=‘C’)的遍历结果是不同的,那是因为它和前两种的存储方式是不一样的,默认是按行访问。

9.1 控制遍历顺序

如下:

1、for x in np.nditer(a, order=‘F’)——Fortran order,即是列序优先;

2、for x in np.nditer(a.T, order=‘C’)——C order,即是行序优先。

import numpy as np

a=np.arange(0,60,5).reshape(3,4)
print('原始数组为:')
print(a)
print('------')

print('该数组的转置是:')
b=a.T
print(b)

print('------')
print('以C风格顺序排序')
c=b.copy(order='C')
print(c)
for x in np.nditer(c):
    print(x,end=',')

print('\n------')
print('以F风格顺序排序')
c=b.copy(order='F')
print(c)
for x in np.nditer(c):
    print(x,end=',')

输出:

原始数组为:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]
------
该数组的转置是:
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]
------
以C风格顺序排序
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]
0,20,40,5,25,45,10,30,50,15,35,55,
------
以F风格顺序排序
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]
0,5,10,15,20,25,30,35,40,45,50,55,

可以通过显式设置,来强制nditer对象使用某种顺序:

import numpy as np

b=np.arange(0,60,5).reshape(3,4)
print('原始数组为:')
print(b)
print('------')

print('以C风格顺序排序')
for x in np.nditer(c,order='C'):
    print(x,end=',')
print('\n------')

print('以F风格顺序排序')
for x in np.nditer(c,order='F'):
    print(x,end=',')

输出:

原始数组为:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]
------
以C风格顺序排序
0,20,40,5,25,45,10,30,50,15,35,55,
------
以F风格顺序排序
0,5,10,15,20,25,30,35,40,45,50,55,

9.2 修改数组中元素的值

nditer对象有另一个可选参数op_flags。默认情况下,nditer将待迭代遍历的数组视为只读对象(read-only),为了在遍历数组的同时,实现对数组元素值的修改,必须指定read-write或者write-only的模式。

import numpy as np

a=np.arange(0,60,5).reshape(3,4)
print('原始数组为:')
print(a)
print('------')

for x in np.nditer(a,op_flags=['readwrite']):
    x[...]=2*x
print('修改后的数组为:')
print(a)

输出:

原始数组为:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]
------
修改后的数组为:
[[  0  10  20  30]
 [ 40  50  60  70]
 [ 80  90 100 110]]

9.3 使用外部循环

nditer类的构造器拥有flags参数,它可以接受下列值:

参数描述
c_index可以跟踪C顺序的索引
f_index可以跟踪Fortran顺序的索引
multi_index每次迭代可以跟踪一种索引类型
external_loop给出的值是具有多个值的一维数组,而不是零维数组

在下面的实例中,迭代器遍历对应于每列,并组合为一维数组。

import numpy as np

a=np.arange(0,60,5).reshape(3,4)
print('原始数组为:')
print(a)
print('------')

print('修改后的数组为:')
for x in np.nditer(a,flags=['external_loop'],order='F'):
    print(x,end=',')

输出:

原始数组为:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]
------
修改后的数组为:
[ 0 20 40],[ 5 25 45],[10 30 50],[15 35 55],

9.4 广播迭代

如果两个数组是可广播的,nditer组合对象能够同时迭代它们。假设数组a的维度为3×4,数组b的维度为1×4,则使用以下迭代器(数组b被广播到a的大小)。

import numpy as np

a=np.arange(0,60,5).reshape(3,4)
print('第一个数组为:')
print(a)
print('------')

b=np.array([1,2,3,4],dtype=int)
print('第二个数组为:')
print(b)
print('------')

print('修改后的数组为:')
for x,y in np.nditer([a,b]):
    print('%d:%d' % (x,y),end=',')

输出:

第一个数组为:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]
------
第二个数组为:
[1 2 3 4]
------
修改后的数组为:
0:1,5:2,10:3,15:4,20:1,25:2,30:3,35:4,40:1,45:2,50:3,55:4,

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值