NumPy

NumPy两种基本对象:
ndarray:储存单一数据类型的多维数组,相当于一系列同类型数据的集合,集合中元素的索引以0下标为开始。
ufunc:是一种能够对数组每个元素进行运算的函数,运算速度非常快。
一、ndarray的创建
import numpy as np
# 输出3行4列的数组(矩阵),从内到外分别为第0轴到第3轴
data = np.arange(12).reshape(3,4)
type(data) ------ 输出数据类型:numpy.ndarray
data.ndim ------ 输出数据维度的个数,输出结果为2表示data是二维数组
data.shape ------ 输出数据维度,输出结果为(3,4)
data.reshape((2,6)) ------ 重新构造数据维度,输出结果为2行6列的矩阵
data.size ------ 输出数组元素的个数,输出结果为12
data.dtype ------ 输出数组元素的类型,输出结果为dtype('int64')

# 创建NumPy数组
data1 = np.array([1,2,3],dtype=float) ------ 创建一维数组,每个数组元素都是float类型
data2 = np.array([1,2,3],[4,5,6]) ------ 创建二维数组
data3 = np.zeros((3,4)) ------ 创建一个3行4列的全0数组
data4 = np.ones((3,4),dtype='float64') ------ 创建一个3行4列的全1数组,每个数组元素都是float类型
data5 = np.empty((3,4),np.int) ------ 创建一个3行4列的空数组,每个值都是接近于0的数
data6 = np.full(4,np.pi) ------ 创建长度为4,值全部为pi的矩阵

# 通过自定义函数产生ndarray
def func(i):
return i % 4 + 1
# fromfunction参数一接受计算函数,参数二接受数组形状,(10,)表示数组0到9
print(np.fromfunction(func,(10,))) ------ [1., 2., 3., 4., 1., 2., 3., 4., 1., 2. ]

# arange
a1 = np.arange(1,20,5) ------ 创建一个数组,数组元素从1开始到20结束,相邻元素相差5
print(data6) ------ [1,6,11,16]
a2 = np.arange(0,1,0.1)
print(data7) ------ [0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]

# linspace:在start和stop之间返回均匀间隔的数据
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)
# start:起始数字;
# stop:结束数字;
# num:数组元素个数,默认为50;
# endpoint: 若是False,则每个元素保留小数点后一位
# retstep: 如果为True则结果会给出数据间隔
# dtype: 数据类型
# axis: 0(默认)或-1
b1 = np.linspace(0,2,10)
print(b1) ------ [0. , 0.22222222, 0.44444444, 0.66666667, 0.88888889, 1.11111111, 1.33333333, 1.55555556, 1.77777778, 2. ]
b2 = np.linspace(0,2,10,endpoint=False)
print(b2) ------ [0. , 0.2, 0.4, 0.6, 0.8, 1. , 1.2, 1.4, 1.6, 1.8]
b3 = np.linspace(0,2,10,dtype=int)
print(b3) ------ [0, 0, 0, 0, 0, 1, 1, 1, 1, 2]

# logspace:创建等比数列
numpy.logspace(start, stop, num, base)
# start:起始数字;
# stop:结束数字;
# num:数组元素个数;
# base:修改基数,开始和结束默认都是10的幂;
c1 = np.logspace(0,0,10)
print(c1) ------ [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]
c2 = np.logspace(0,9,10)
print(c2) ------ [1.00000000e+00, 1.00000000e+01, 1.00000000e+02, 1.00000000e+03, 1.00000000e+04, 1.00000000e+05,1.00000000e+06, 1.00000000e+07, 1.00000000e+08, 1.00000000e+09]
c3 = np.logspace(0,9,10,base=2)
print(c3) ------ [ 1., 2., 4., 8., 16., 32., 64., 128., 256., 512.]

二、ndarray切片(同list)
>>> import numpy as np
>>> a = np.arange(10)
>>> print(a)
[0 1 2 3 4 5 6 7 8 9]
>>> print(a[5])
5
>>> print(a[3:5])
[3 4]
>>> print(a[:5])
[0 1 2 3 4]
>>> print(a[:-1])
[0 1 2 3 4 5 6 7 8]
>>> print(a[1:-1:2])
[1 3 5 7]
>>> print(a[::-1])
[9 8 7 6 5 4 3 2 1 0]
>>> print(a[5:1:-2])
[5 3]
>>> a[2:4] = 100,101
>>> a
array([ 0, 1, 100, 101, 4, 5, 6, 7, 8, 9])
# 通过切片产生一个新的数组b,b和a共享同一块数据存储空间
>>> b = a[3:7]
>>> b[2] = -10
>>> b,a
(array([101, 4, -10, 6]), array([ 0, 1, 100, 101, 4, -10, 6, 7, 8, 9]))
>>> b = a[[3,3,-3,8]]
>>> b
array([101, 101, 7, 8])

三、多维数组
>>> import numpy as np
>>> a = np.arange(0,60,10)
>>> a
array([ 0, 10, 20, 30, 40, 50])
# reshape(-1,1)表示只需要制定特定的列数,行数无所谓用-1(通配符)来代替;(1,-1)表示制定特定的行数
>>> a = np.arange(0,60,10).reshape(-1,1)
>>> a
array([[ 0],
[10],
[20],
[30],
[40],
[50]])
>>> a = np.arange(0,60,10).reshape(-1,1)+np.arange(0,6)
>>> a
array([[ 0, 1, 2, 3, 4, 5],
[10, 11, 12, 13, 14, 15],
[20, 21, 22, 23, 24, 25],
[30, 31, 32, 33, 34, 35],
[40, 41, 42, 43, 44, 45],
[50, 51, 52, 53, 54, 55]])
>>> a[0,3:5] ------ 输出第0行第[3,5)的元素
array([3, 4])
>>> a[4:,4:] ------ 输出第[4,∞)行,每行第[4,∞)的元素
array([[44, 45],
[54, 55]])
>>> a[2::2,::2] ------ 输出第[2,∞)行的每两行输出一行,每行所有元素各取两个输出一个
array([[20, 22, 24],
[40, 42, 44]])
四、结构数组
>>> persontype = np.dtype({
'names':['name','age','weight'],
'formats':['S30','i','f']})
>>> a = np.array([("Zhang",32,75.5),("Tian",23,70.0)],dtype=persontype)
这样就创建了一个persontype的结构体
>>> a[0]
(b'Zhang', 32, 75.5)

五、ufunc函数
a = np.arange(0,4)
b = np.arange(1,5)
# 四则运算
np.add(a,b) ------ array([1,3,5,7])
np.subtract(a,b) ------ 减法
np.multiply(a,b) ------ 乘法
np.divide(a,b) ------ 如果两个均为整数,则是整除
np.power(a,b) ------ 乘方

# 比较运算和布尔运算
使用==和>对两个数组进行比较,会返回一个布尔数组,每一个元素都是对应元素的比较结果。
np.array([1,2,3]) < np.array([3,2,1]) ------ array([ True, False, False],dtype=bool)
equal(x1,x2[,y]) ------ y = x1 == x2
not_equal(x1.x2[,y]) ------ y = x1 != x2
less(x1,x2[,y]) ------ y = x1 < x2
less_equal(x1,x2[,y]) ------ y = x1 <= x2
greater(x1,x2[,y]) ------ y = x1 > x2
greater_equal(x1,x2[,y]) ------ y = x1 >= x2

# 自定义ufunc函数
自己编写的函数:
def num_judge(x,a):
if x%3 == 0:
r = 0
elif x%5 == 0:
r = 0
else:
r = a
return r
x = np.linspace(0,10,11)
y = np.array([num_judge(t,2) for t in x]) # 列表生成式 ------ array([0,2,2,0,2,0,0,2,2,0,0])
用frompyfunc()转化,调用格式如下:
frompyfunc(func,nin,nout)
# func:自己写的计算函数
# nin:计算函数的输入参数个数
# nout:计算函数的输出个数
num_judge = np.frompyfunc(num_judge,2,1)
y = num_judge(x,2) ------ array([0,2,2,0,2,0,0,2,2,0,0],dtype=object)
# 强制类型转换
y.astype(np.int) ------ array([0,2,2,0,2,0,0,2,2,0,0],dtype=int)

# 广播
使用ufunc对两个数组进行运算时,ufunc函数会对两个数组的对应位置的元素进行运算,如果两个数组形状不同,就会进行广播处理也就是说,会把两个数组变为同一种形状,每行(列)补充的元素和该行(列)原有的元素一致。
    例如:
>>> a = np.arange(0,60,10)
>>> a
array([ 0, 10, 20, 30, 40, 50])
>>> a = a.reshape(-1,1)
>>> a
array([[ 0],
  [10],
 [20],
 [30],
 [40],
 [50]])
>>> b = np.arange(0,5)
>>> b
array([0, 1, 2, 3, 4])
>>> c = a + b
"""
在运算c时,a就变为:
array([[ 0, 0, 0, 0, 0],
 [10, 10, 10, 10, 10],
[20, 20, 20, 20, 20],
  [30, 30, 30, 30, 30],
 [40, 40, 40, 40, 40],
 [50, 50, 50, 50, 50]])
b变为:
array([0, 1, 2, 3, 4],
  [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4])
"""
>>> c
array([[ 0, 1, 2, 3, 4],
[10, 11, 12, 13, 14],
[20, 21, 22, 23, 24],
[30, 31, 32, 33, 34],
[40, 41, 42, 43, 44],
[50, 51, 52, 53, 54]])
>>> c.shape
(6, 5)
ogrid用来生成广播运算所用的数组:
>>> x,y,z = np.ogrid[:5,:5,:5]
>>> x
array([[[0]],
[[1]],
[[2]],
[[3]],
[[4]]])
>>> y
array([[[0],
[1],
[2],
[3],
[4]]])
>>> z
array([[[0, 1, 2, 3, 4]]])
# 根据从外到内的每个大括号(分别代表xyz)中包含几个元素来决定该数组的形状,
>>> x.shape,y.shape,z.shape
((5, 1, 1), (1, 5, 1), (1, 1, 5))

六、NumPy函数库
# 随机数
from numpy import random as nr
nr.rand(4,3) ------ 生成一个4行3列矩阵,矩阵元素为0到1的随机数
nr.randint(a,b) ------ 制定范围内的随机整数
nr.randn ------ 标准正态的随机数
nr.choice ------ 随机抽取样本
nr.normal ------ 正态分布的随机数
nr.uniform ------ 均匀分布
nr.poisson(2.0,(4,3)) ------ 生成一个4行3列矩阵,矩阵元素呈现泊松分布
nr.shuffle ------ 随机打乱顺序

# 数值运算
np.set_printoptions(precision=2) ------ 显示小数点后两位
np.sum(a,axis=1) ------ 求行和,axis=0求列和,keepdims=True保持原来的维度
np.average() ------ 求加权平均数
np.var ------ 方差
np.mean ------ 期望
np.std ------ 标准差
np.product ------ 连乘积
np.abs ------ 返回绝对值

# 大小排序
min/max ------ 最值
ptp ------ 极差
argmin/argmax ------ 最值下标
minimum/maximum ------ 二元最值
# 对数组排序会改变数组内容返回一个新的数组,axis默认为-1,即按最终轴进行排序,0表示对每列上的值进行排序
sort ------ 数组排序
argsort ------ 数组排序下标
percentile ------ 分位数
median ------ 中位数
>>> a = np.array([1,3,5,7])
>>> b = np.array([2,4,6])
>>> a[None,:]
array([[1, 3, 5, 7]])
>>> b[:,None]
array([[2],
[4],
[6]])
# maximum返回两组进行广播之后的比较结果
>>> np.maximum(a[None,:],b[:,None]) ------ array([[2, 3, 5, 7],
         [4, 4, 5, 7],
         [6, 6, 6, 7]])

# 统计函数
1、unique()
去掉数组中的重复数字,并进行排序之后输出。
参数:
return_index=True ------ 同时返回排序后的各个元素在原数组中的下标
return_inverse=True ------ 表示原始数组的各个元素在新数组中的下标
例子:
>>> np.random.seed(42)
>>> a = np.random.randint(0,8,10) ------ array([6, 3, 4, 6, 2, 7, 4, 4, 6, 1])
>>> np.unique(a) ------ array([1, 2, 3, 4, 6, 7])
>>> x = np.unique(a,return_index=True)
>>> x ------ array([9, 4, 1, 2, 0, 5], dtype=int64)
>>> y = np.unique(a,return_inverse=True)
>>> y ------ array([4, 2, 3, 4, 1, 5, 3, 3, 4, 0], dtype=int64)

2、bincount()
返回数组中的第i个元素是整数i出现的次数,即返回各个元素的索引值在数组中出现的次数。
x = np.array([0,1,2,2,1,1,0])
w = np.array([0.1,0.3,0.2,0.4,0.5,0.8,1.2])
计算方式:
x中索引0对应的数据出现在第0和第6的位置,那么就取对应位置的weight(权值)为w[0]+w[6]=0.1+1.2=1.3,以此类推。
np.bincount(x,w) ------ array([1.3,1.6,0.6])

3、histogram()
对数组进行直方图统计。
参数:
a是待统计数据的数组;
bins指定统计的区间个数;
range是一个长度为2的元组,表示统计范围的最小值和最大值,默认值None,表示范围由数据的范围决定
weights为数组的每个元素指定了权值,histogram()会对区间中数组所对应的权值进行求和
density为True时,返回每个区间的概率密度;为False,返回每个区间中元素的个数

# 操作多维数组
vstack((a,b)):按照第一轴连接数组
hstack((a,b)):按照第0轴连接数组
column_stack((a,b)):按列连接多个一维数组

>>> a = np.arange(3)
>>> b = np.arange(10,13)
>>> v = np.vstack((a,b))
>>> h = np.hstack((a,b))
>>> c = np.column_stack((a,b))
>>> v
array([[ 0, 1, 2],
[10, 11, 12]])
>>> h
array([ 0, 1, 2, 10, 11, 12])
>>> c
array([[ 0, 10],
[ 1, 11],
[ 2, 12]])

split()进行分段:
np.split(a,idx) ------ 按元素位置进行分段
np.split(a,2) ------ 按数组个数进行分段

总结自:
https://zhuanlan.zhihu.com/p/391261981
posted @ 2022-02-07 20:30  Sunshine_y  阅读(47)  评论(1编辑  收藏  举报