目录
一些重要的性质
1.Numpy库创建一个数组,创建的数组的大小是无法改变的。
2.数学中一维数据叫向量,二维数据叫做矩阵,三维数据叫做张量。在Numpy中每一个维度叫做轴。
3.可以利用多维数组的.ndim属性查看数组有几个维度,可以使用.shape()看每一个轴的长度,可以使用size来查看两个轴长度的乘积
Numpy的基本函数总结
1.np.array() ##这个函数可以创建一个多维数组对象,参数是嵌套列表。(这里一定要注意的就是这个嵌套列表一定要是能够变成数组对象)
import numpy as np a = np.array([[1, 2], [2, 3]]) print(a) output: [[1 2] [2 3]] 提示: 要想嵌套列表能够变成数组对象,一定要保证列表的维度上的每一个元素都存在, 简单的理解就是,以以上例子为例, 我可以用[[1, 2], [2, 3]],但是不可以用[[1, 2], 1, 2]。
2.np.zeros() ##这个函数创建一个全是零的多维数组对象,参数是shape对象
3.np.ones() ##这个函数创建一个全部都是1的多维数组对象,参数是一个shape对象
4.np.arange() ##这个函数创建一个一维的数组对象,参数分别是起始,结束,步长(可以是小数,这也是它优于range函数的表现)
5.np.linspace() ##这个函数和arange函数是类似的,但是参数是起始,结束,元素个数
提示:在以上五个函数当中,我们可以使用dtype=int32/int64/float64/float32等的方法来直接定义数组的类型(这有点像申明数据类型)
########
下面我对可以作为dtype参数的类型进行一个汇总:
np.int32 默认为整数,有符号32位的整型
np.int64 有符号64位的整型
np.float64 有双精度的64位的浮点型
np.float32 有单精度32位的浮点型
np.complex64 有双精度的64位的复数型
提示:这里的int64和float64可以写成int_,float_来进行代替。
########
特别注意:对于浮点数而言,存在一个inf的值和nan值,可以使用np.inf和np.nan来进行表示,其中inf表示无穷数,nan表示缺省值。
数组的基本运算和广播运算
一、基本运算
numpy对象的加减乘除运算一般来说是针对相同形状(即shape是一样的)数组的,运算相当于对应的元素直接相加减乘除。
二、广播运算
如果两个numpy对象是不同形状的(也就是shape是不相等的)也可以进行基本运算,计算常见以下几类:
1.numpy对象和一个数进行运算,这时就是这个数直接扩展为与numpy对象一样的shape后与numpy对象进行基本运算
2.当两个numpy对象运算时,numpy会自动将维度更小的数组在新的纬度上进行复制,实现相同纬度再进行逐元素的运算(这里尽量要保证维度小的数组长度和大的纬度数组的最后一个维度的长度相等。只要保证维度小的数组每个维度在大维度的数组中有对应即可)
例如小维度数组shape=(1, 2, 3),大维度数组shape=(4, 1, 2, 3),比如小维度数组为shape=(1,2),大维度数组shape=(4,2,4,4,1,2),再比如小维度数组shape=(1,2),大维度数字shape=(1, 2, 3, 4, 5)。
以下代码举例:
import numpy as np a = np.zeros((1, 2)) b = np.ones((2, 1, 2)) print(a + b) output: [[[1. 1.]] [[1. 1.]]]
特别注意:比较运算符也可以进行数组间基本运算的,这时候得到的是全是bool数的数组,这在后面的数组的索引中应用很广泛。
多维数组的索引和切片
一、索引
可以选用:来进行切片取想要的数组或者使用::进行切片,这里的:和::和列表索引完全一样用法,数组中以[a:b, c:d, e:f]来进行切片索引(其中a,b...都是随意整数,:可以换为::)
特别提醒:索引经过提取之后的新数组不受原数组影响。
import numpy as np a = np.array([[1, 2, 3], [2, 3, 4]]) print(a[0:2, 1:]) output: [[2 3] [3 4]]
二、高级索引
逻辑索引(这个是我们平常用的最多的,也是最好用的)
使用bool数组作为索引来挑选True的数组元素并生成一个新的多维数组
a=np.array([[1,2,3], [2,3,4], [3,4,5]]) # 如果想要将a中大于4的数字挑选出来那么使用下面的逻辑索引进行挑选 print(a[a>4]) # 再次提示这里a>4就会生成一个 [[False False False] [False False False] [False False True]] # 根据生成的这个bool数组将对应位置是True的挑选出来 output: [5] # 这里针对二维数组的最后一维筛选 print(a[a[:, 2]> 4]) # a[:, 2]>4得到的是一个这样的bool数组: [False False True] # 这时进行索引得到的是 output: [[3 4 5]]
特别注意:
1.如果我们逻辑索引是全部维度的数进行比较运算得到的bool数组,那么numpy就会破坏其维度将其平铺为一维的数组。
2.一般来说二维数组应用最多,如果是针对二维数组第二个维度中的数字进行比较得到的bool判断数组,那么将可以进行类似Excel筛选的功能,将某列满足条件的筛选出来同时其他列的元素跟着筛选。
3.比二维更高维的数组逻辑索引只有当除了最后一维的索引值不是:,其他维索引值都是:才可以使用,这时得到的bool判断数组维数是这个高维数组维数-1,最后索引得到的数组是一个二维数组
import numpy as np data = np.array([[[[1, 1], [2, 2], [3, 3]], [[2, 2], [3, 3], [4, 4]]], [[[4, 4], [5, 5], [6, 6]], [[6, 6], [7, 7], [8, 8]]]], dtype=np.int_) print(data[:, :, :, 0] > 5) print(data[data[:, :, :, 0] > 5]) print(data[:, :, 0, :] > 5) print(data[data[:, :, 0, :] > 5]) output: [[[False False False] [False False False]] [[False False True] [ True True True]]] [[6 6] [6 6] [7 7] [8 8]] [[[False False] [False False]] [[False False] [ True True]]] Traceback (most recent call last): File "E:\Programing\pycharm_files_python311env\流畅的python\xiaochuang.py", line 20, in <module> print(data[data[:, :, 0, :] > 5]) ~~~~^^^^^^^^^^^^^^^^^^^^^^ IndexError: boolean index did not match indexed array along dimension 2; dimension is 3 but corresponding boolean dimension is 2
花式索引
numpy还可以进行多个索引的指定选取
例如:
a=np.array([[1,2,3], [2,3,4], [3,4,5]]) print(a[[1,2], [1,2]]) # 这里是对索引为(1,1)和(2,2)的进行提取 output: [3, 5]
三、np.where
np.where的用法十分重要,如果我们读取hdf或者nc文件的时候,我们读取文件之后得到的数据集一般来说是结构相同的,这个时候如果是读nc文件可以直接用xarray库的DataArray和Dataset对象对应的索引方法。如果不是读取nc文件(当然读取nc文件有时也用到np.where()),读取其他文件的话,如果数据结构是相同的,那么我们可以通过利用例如np.where(c<1)来读取索引。
以下为例子:
import numpy as np import xarray as xr data = xr.open_dataset(r"C:\Users\lvyih\Desktop\stipple.nc") longitude = data["longitude"] latitude = data["latitude"] lon2, lat2 = np.meshgrid(longitude, latitude) print(type(lon2)) print(lon2[np.where(lat2 > 60)]) output: <class 'numpy.ndarray'> [ 0. 3.75 7.5 ... 348.75 352.5 356.25] # 这里输出一下np.where得到的索引值给大家看 print(np.where(lat2 > 60)) output: (array([ 0, 0, 0, ..., 11, 11, 11], dtype=int64), array([ 0, 1, 2, ..., 93, 94, 95], dtype=int64))
解释一下:这里我是读取了一个nc文件,通过np的meshgrid函数对longitude和latitude进行栅格化,然后根据np.where函数可以得到lat2大于60的所有索引并通过索引在lon2中找到lat2大于60的对应的数据,得到的数据是一维的已经平铺的数据。
数组的形状的变换reshape函数
提示:数组的元素是不可变的,但是数组的形状是可以变化的,可以使用reshape()对数组的形状的进行设定,reshape中的参数是每个维度的长度,其中最后一个要写的维度可以直接填写为-1表示python自动根据原数组的size计算最后一维的长度。(常用-1将数组平铺)【具体例子见下面讲解】
轴变换函数transpose函数
transpose函数是将二维或者二维以上的数组进行轴的变化,如果是二维数组不需要加参数相当于矩阵的转置,三维数组及以上维度数组需要提供参数(几维就提供几个参数,例如对三维数组提供(1, 0, 2)就相当于将这个三维数组的第0维和第1维进行转换)
提示:transpose函数变换的法则是,以三维数组提供(1,0,2)参数为例,相当于把原来在数组【1】【2】【1】位置的元素变成了在新数组的【2】【1】【1】位置。(例如【1】【2】【1】表示在第一个维度的第一个索引位置,第二个维度的第二个索引位置,第三个维度的第一个索引位置。)
多维数组的一些函数
一、假设array为一个多维数组
1.array.mean(axis=()) # mean函数是求平均值函数,axis=这个参数可以指定是针对哪个纬度进行求平均,()内的参数可以多个表示对多个维度求平均,如果不输入axis参数默认为对所有维度求平均。
提示:array.mean()求值的本质是对求的维的那一个维度的下一个维度的元素进行相加,其中求多个维度的平均值时,求平均值的顺序随意。
2.array.max(axis=()) # max函数是求最大值函数,和mean函数是一样的本质操作【如果想要绕开nan值,用nanmax函数】
3.array.min(axis=()) # min类似与max
4.array.std(axis=()) # 求标准差函数
5.array.round() # 对所有维度的元素进行四舍五入操作
6.array.astype() # astype函数可以改变array元素的数据类型而创建一个新的数组
二、假设a是多维数组,b是一个多维数组
a.dot(b) 就是数组之间的点乘运算,在二维中就是矩阵的乘法运算,在三维甚至三维以上的情况就相当于把左乘和右乘的最后两个维度进行矩阵乘积然后前面的纬度进行矩阵相乘。
例如:
a = np.random.random((2, 2, 3)) b = np.random.random((1, 3, 2)) print(a) print(b) c = a.dot(b) print(c) print(c.shape) # output: # [[[0.97435814 0.15873357 0.0339072 ] # [0.21176906 0.477657 0.02888726]] # # [[0.12952044 0.04369193 0.00348543] # [0.12679815 0.46684605 0.38734817]]] # [[[0.2771934 0.37517756] # [0.97679599 0.08696438] # [0.20338993 0.7380475 ]]] # [[[[0.43203235 0.4043866 ]] # # [[0.5311498 0.14231032]]] # # # [[[0.07928921 0.05496521]] # # [[0.56994368 0.37405214]]]] # (2, 2, 1, 2)
解释:相当于本质上还是第一个多维数组的(2,3)和第二个数组的(3,2)相乘,当取a第一个维度2的第一个元素1时,取b第一个维度1的第一个元素的时候的得到的就是最终数组的【1】【2】【1】【2】位置的模块,同理取a第一个维度2的第二个元素2取b第一个维度1的第一个元素的时候得到的就是最终数组的【2】【2】【1】【2】位置的模块。
Numpy的函数
1.np.exp() # 取指数e^ 【逐个元素操作】
2.np.log() # 取ln 【逐个元素操作】
3.np.sqrt() # 取根号 【逐个元素操作】
4.np.sin() # 取sin 【逐个元素操作】
5.np.ceil() # 向上取整 【逐个元素操作】
6.np.floor() # 向下取整 【逐个元素操作】
7.np.genfromtxt(fname,dtype=float,delimiter=None,skip_header=0) # fname表示文件路径,dtype表示引入到python程序中要变换的数据类型,delimeter为分隔符,skip_header表示跳过的行数
8.np.loadtxt(fname,dtype=float,skip_header=0) 【和genfromtxt类似,可以有效避免使用with open】
9.np.savetxt(fname, X,delimiter="") # X表示一维或者二维数组,delimiter为分隔符
10.np.fabs() # 全部取绝对值 【逐个元素操作】
一个例子
下面我将以下面的一个简单的例子来对numpy对象的基本运算,广播运算,索引进行讲解:
# -- coding:utf-8 --
import numpy as np
# 这里就可以不用with open了,可以直接用loadtxt,这可以直接避免增加行数
data = np.loadtxt(r"C:\Users\lvyih\Desktop\station_1989-2019.txt", dtype=int, skiprows=1)
summer = data[(data[:, 4] >= 6) & (data[:, 4] <= 8)]
temp = summer[:, 6].reshape(30, 92)
# 这里是该站点的夏季平均温度的逐日气候态,这里对第一个维度求平均是相当于对已经处理好的summer数据进行单日的30年数据求平均
temp_clm = temp.mean(axis=0)
print("summer daily climatology is:")
print(temp_clm)
# 以下是求解该站点的夏季平均气温的距平
temp_ano = temp - temp_clm
print("summer daily average temperature anomaly is")
print(temp_ano)
提示:
1.(data[:, 4] >=6) & (data[:, 4] <= 8)得bool判断矩阵作为data的逻辑索引以得到夏季数据,
2.reshape将summer数据变换成每一年的夏季的数据,再在axis=0求平均得到夏季平均温度的逐日气候态。
3.temp_ano=temp-temp_clm使用了广播运算,求得夏季平均气温的距平。