Numpy简介
- python标准库中的列表(list)可以当数组用,支持动态内存分配和垃圾收集,列表元素可以是任何对象,功能强大!
- 列表的缺点:
- 慢:循环时有各种下标检查和类型检查
- 占内存多:保存的是对象 指针
- NumPy的优点:
- 两大法宝:多维数组ndarray和通用函数ufunc
- 面向数值计算,速度快(内置函数逼近c语言)
- NumPy官方提供丰富的中文资源
- 如何使用Numpy等python第三方软件包?(如何开外挂?)
- 先导入再使用,没导入就没法用
- 如何导入?用import
- 被import的可以是通过conda或pip安装的包,也可以是python的path中(包括当前目录)的其它x.py文件。
# 导入名为numpy的包,命名为np
import numpy as np
多维数组ndarray对象
- 多维数组ndarray(n-dimensional array object)是NumPy的核心对象
- 它存储单一类型的多维数组,注意与列表(list)的区别
- 结构简单,功能强大
- 使用优化过的C API,速度快
ndarray对象:创建
代码语言:javascript复制# 给np.array()函数传递python序列对象
a=np.array([1,2,3,4])
b=np.array((5,6,7,8))
c=np.array([[1,2,3,4],[4,5,6,7],[7,8,9,10]])
print('a = ',a)
print('b = ',b)
print('c = ',c)
输出结果
代码语言:javascript复制# 也可以用zeros, ones, empty和full函数,创建指定大小,值为0/1/空/定数值的数组
zz=np.zeros((2,3,4))
oo=np.ones((2,3,4))
ee=np.empty((2,3,4))
ff=np.full((2,3,4),999)
print('zz = ', zz)
print('oo = ', oo)
print('ee = ', ee)
print('ff = ', ff)
# empty只分配内存,不赋值,最快。但是里面的内容是啥就不一定了!使用empty创建的ndarray,一定得初始化再使用。
输出结果
代码语言:javascript复制# 创建形状类型与a相同的数组
za = np.zeros_like(a)
oa = np.ones_like(a)
ea = np.empty_like(a)
fa = np.full_like(a,999)
ndarray对象:形状
- 数组对象的形状通过shape属性获得,返回一个描述数组各个轴的长度的元组(tuple),元组的长度等于数组的维数
- 例如:
- (3,4),表示第0轴长度为3,第1轴长度为4(三行四列)
- (2,3,4)表示第0轴长度为2,第1轴长度为3,第2轴长度为4
- 建议同学们使用第X轴的方式思考,0轴在最顶层,以此类推
- ndarray类型的对象里面,数据都是一维化之后存储在连续分配的内存中,ndarray的维度仅仅是告诉numpy如何读取而已
- 所以,可以通过改变shape属性,改变数组的形状。(注意和转置的区别!!!)
c = np.array([[[1,2,3,4],[5,6,7,8],[9,10,11,12]],[[13,14,15,16],[17,18,19,20],[21,22,23,24]]])
print(c.shape)
print(c) # 2片,3行,4列(第0轴长度为2,第1轴长度为3,第2轴长度为4)
代码语言:javascript复制# 改变数组的形状
c.shape = (2,4,3) # 注意这不是转置!!!改变形状之后,数据的顺序是不变的。
print(c.shape)
print(c)
代码语言:javascript复制# 用-1表示这一个维度的长度是自动计算的
c.shape = 3,-1
print(c.shape)
print(c)
代码语言:javascript复制# 使用reshape创建指定形状的新数组
d = c.reshape((2,3,4))
print('d.shape = ', d.shape)
print('d = ', d)
# c的形状不变
print('c.shape = ', c.shape)
代码语言:javascript复制# 改变d的元素,c的元素仍会改变!
# 完全复制建议使用copy.deepcopy()
c[0,0] = 2233
print('c = ', c)
print('d = ', d)
ndarray对象:类型
- 在读写地理数据时,ndarray的类型很重要!
- np数组如c语言一样有类型,通过dtype属性查看
- 创建数组时可以指定数据类型
- numpy支持的数据类型比python标准库支持的更加广泛
# 看看ndarray c的类型
print(c.dtype)
代码语言:javascript复制# 创建array的默认数据类型是?
a = np.array([1,2,3,4])
print(a.dtype)
b = np.array([1.0, 2.0, 3.0, 4.0])
print(b.dtype)
c = np.zeros(4)
print(c.dtype)
代码语言:javascript复制# 创建数组时指定数据类型
ai32 = np.array([1, 2, 3, 4], dtype=np.int32)
af = np.array([1, 2, 3, 4], dtype=float)
ac = np.array([1, 2, 3, 4], dtype=complex)
# 其中np.int32时numpy的数据类型;float和complex是python内置的型,会自动转换为numpy的数据类型
print(ai32.dtype)
print(af.dtype)
print(ac.dtype)
代码语言:javascript复制# 数组的类型转换
t1 = np.array([1, 2, 3, 4], dtype=np.float)
t2 = np.array([1, 2, 3, 4], dtype=np.complex)
t3 = t1.astype(np.int32)
t4 = t2.astype(np.complex64)
print(t1.dtype)
print(t2.dtype)
print(t3.dtype)
print(t4.dtype)
ndarray对象:从数列创建
- np.arange()
- 通过开始值、终值和步长来创建等差数列
- np.arange(0, 1, 0.1)
- 注意1不在数组中!
- np.linspace()
- 通过开始值、终值和元素个数创建等差数列
- np.linspace(0, 1, 10)
- np.linspace(0, 1, 10, endpoint=False)
- 可以通过endpoint参数指定是否包含终值,默认值为True,即包含终值
- np.logspace()
- 通过开始值、终值和元素个数创建等比数列
- np.logspace(0, 2, 5)
- np.logspace(0, 1, 12, base=2, endpoint=False)
- 可以通过base更改底数,默认为10
- 可以通过endpoint参数指定是否包含终值,默认值为True
# 通过开始值、终值和步长来创建等差数列
np.arange(0, 1, 0.1) # 从0开始,到1结束,步长0.1,注意1不在数组中!
代码语言:javascript复制# 通过开始值、终值和元素个数创建等差数列
np.linspace(0, 1, 10) # 从0开始,到1结束,10个元素的等差数列
# np.linspace(0, 1, 10, endpoint=False) # 可以通过endpoint参数定是否包含终值,默认值为True,即包含终值
代码语言:javascript复制# 通过开始值、终值和元素个数创建等比数列
# np.logspace(0, 2, 5) # 从0开始,到2结束,5个元素的等比数列
np.logspace(0, 1, 12, base=2, endpoint=False) # 可以通过base更改底数,默认为10
# 可以通过endpoint参数指定是否包含终值,默认值为True
ndarray对象:下标存取
- 下标方式:a[2]
- 切片方式:
- a[3:5] 包括a[3]但不包括a[5]
- a[:5] 从a[0]开始
- a[:-1] 用负数表示从后往前数
- a[1:-1:2] 第三个元素表示步长,每两个元素取一个
- a[::-1] 步长为负,整个数组顺序颠倒
- a[5:1:-2]步长为负时,开始下标必须大于结束下标
- 通过切片获取的数组是原数组的一个**“视图”,与原数组共享同一存储空间,因此修改结果数组会改变原始数组**
- 对多维数组,采用元组作为数组下标,逗号分隔
- 为了避免出现问题,请 “显式”地使用元组作为下标
- 整数元组/列表/数组,布尔数组作为下标
- 多维数组的下标元组中,也可以使用整数元组或列表、整数数组和布尔数组
- 当下标中使用这些对象时,所获得的数椐是原始数据的副本,因此修改结果数组不会改变原始数组。
x = np.arange(5,0,-1)
a = x[np.array([True, False, True, False, False])]
b = x[x>2]
c = x[[True, False, True, False, False]]
print('x = ', x)
print('a = ', a)
print('b = ', b)
print('c = ', c)
ufunc函数
- ufunc是universal function的缩写,它是一种对数组的每个元素进行运算的函数
- NumPy内置的许多ufunc函数都是用c语言实现的,速度很快
- x = np.linspace(0, 2*np.pi, 10)
- y = np.sin(x)
- t = np.sin(x, out=x)
- NumPy的数组对象支持加减乘除等操作
- 因为加减乘除操作在NumPy中使用ufunc实现,实际上是调用了ufunc
ufunc的算术运算符/比较运算符
- 算术运算符:加减乘除乘方同余...
- 比较运算符:大于小于等于不等于...
- 数组对象支持操作符,极大的方便了程序编写。但是要注意如果算式很复杂、数组很大的时候,会产生过多的中间变量,降低程序运行速度。
- 可以适当考虑多用原位操作符,例如 x = y,复杂算式多分几行,减少对中间变量的内存分配
x1 = np.array([1,2,3,4])
x2 = np.array([5,6,7,8])
y = x1 x2 # add
print(y)
ufunc函数:自定义
- 使用frompyfunc(func, nin, nout)
- 其中func是python函数,nin是func的输入参数个数,nout是func的返回值个数
- 如果ufunc输入参数有多个数组,形状不同,会自动进行广播操作
- 让所有输入数组都向其中维数最多的数组看齐,shape属性中不足的部分都通过在前面加1补齐
- 输出数组的shape属性是输入数组的shape属性的各个轴上的最大值
- 如果输入数组的某个轴的长度为1或与输出数组的对应轴的长度相同,这个数组能够用来计算,否则出错
- 当输入数组的某个轴的长度为1吋,沿着此轴运算时都用此轴上的第一组值!
# 自定义ufunc
def myfunc(x):
return x**2 1
my_ufunc = np.frompyfunc(myfunc, 1, 1)
x = np.linspace(0,10,11)
y = my_ufunc(x)
print(y)
之后我们还会分享使用Python教程,欢迎大家持续关注。