Python NumPy库 常见基本用法总结(学习笔记)

目录

简介

1.ndarray对象

1.1 创建数组

1.1.1 np.array()

1.2 数组形状与元素类型

1.2.1 ndarray.shape  #获得形状

1.2.2 ndarray.reshape()  #改变形状

1.2.3 ndarray.dtype  #获得元素类型

1.2.4 ndarray.astype()  #转换元素类型

 1.2.5 np.set_printoptions(precision = )  #控制小数点位数

1.3 自动生成数组

1.3.1 np.arange()  #等差一维数组

1.3.2 np.linspace()  #等差一维数组

1.3.3 np.logspace()  #指数数组

1.3.4 np.zeros()、np.ones()、np.empty()、np.full()  #特殊数组

1.3.5 np.zeros_like()、np.ones_like()、np.empty_like()、np.full_like()  #形状相同的特殊数组

1.4 存取元素

1.4.1 下标、切片

1.4.2 ndarray[[ ]]  #批量提取数组元素

1.4.3 ndarray.take()  #获取元素

1.4.3 np.compress()  #通过布尔数组获取元素

1.5 多维数组

1.5.1 二维数组的创建

1.5.2 二维数组的切片

1.6 结构数组

1.6.1 定义结构数组 np.dtype()

1.6.2 结构数组的存取

2.ufunc对象

2.1 四则运算

2.2 比较运算和布尔运算

2.2.1 比较运算(<,=,>)

2.2.2 布尔运算(np.logical_and、or、not)

2.2.3 布尔运算(np.all()、np.any())

2.3 自定义ufunc函数

2.3.1 np.frompyfunc()  #分段函数

2.4 广播(broadcasting)

2.4.1 广播处理规则

2.4.2 np.broadcast_arrays()  #查看广播之后的数组

2.4.3 ndarray.repeat()  #复制元素

2.4.4 下标对象None

2.5 ufunc的方法

2.5.1 np..reduce()  #对数组内元素四则运算

2.5.2 np..accumulate()  #对数组内元素四则运算

2.5.3 np..reduceat()  计算多组reduce()的结果

2.5.4 np..outer()  #计算表

3.多维数组的下标存取

3.1 下标对象

3.2 整数数组作为下标

3.3 布尔数组作为下标

3.3.1 np.nonzero()  #找出不为0的元素

4.NumPy的函数库

4.1 随机数(np.random模块)

4.1.1 np.random.rand()(产生随机0~1浮点数)

4.1.2 np.random.randn()(产生正态分布随机数)

4.1.3 np.random.randint()(产生随机整数)

4.1.4 np.random.normal()(随正态分布)

4.1.5 np.random.uniform()(均匀分布)

4.1.6 np.random.possion()(泊松分布)

4.1.7 np.random.permutation()  #产生乱序数组、打乱数组

4.1.8 np.random.shuffle()  #打乱数组

4.1.9 np.random.choice()  #随机抽取

4.1.10 np.random.seed()  #种子

4.2 求和、平均值、方差

4.2.1 np.sum()  #求和

4.2.2 np.mean()  #求平均数

4.2.3 np.average()  #计算加权平均数

4.2.4 np.std()  #计算标准差

4.2.5 np.var()  #计算方差

4.2.6 np.product()  #计算所有元素乘积

4.3 大小与排序

4.3.1 np.min(),np.max(),np.minimum(),np.maximum(),np.ptp()

4.3.2 np.argmax(),np.argmin()  #求最值下标

4.3.3 np.unravel_index()  #下标转化

4.3.4 np.sort()  #排序

4.3.5 np.argsort()  #排序后的下标

4.3.6 np.lexsort()  #多列排序

4.3.6 np.lexsort() 应用:成绩姓名全局排序

4.3.7 np.partition(),np.argpartition()  #数组分割

4.3.8 np.median()  #计算中位数

4.3.9 np.percentile()  #计算百分数

4.3.10 np.searchsorted()  #插入元素(二分查找)

4.4 统计函数

4.4.1 np.unique()  #去除重复元素

4.4.2 np.bincount()  #对整数数组的元素计数

4.4.3 np.histogram()  #直方图统计

4.5 分段函数

4.5.1 np.where()  #if

4.5.2 np.select()  #多分支的if

4.5.3 np.piecewise()  #分段函数

4.6 操作多维数组

4.6.1 np.concatenate()  #连接多个数组

4.6.2 np.vstack()  #沿第0轴连接数组

4.6.3 np.hstack()  #沿第1轴连接数组

4.6.4 np.c[]  #按列连接多个一维数组

4.6.5 np.split()、np.array_split()  #将数组分为多段

4.6.6 np.transpose()、np.swapaxes()  #重新设置轴的顺序

4.6.7 np.swapaxes()  #交换两个轴的顺序

4.7 多项式函数

4.7.1 np.poly1d()  #转化成poly1d对象

4.7.2 deriv()  #计算微分

4.7.3 integ()  #计算积分

4.7.4 np.roots()  #求根

4.7.5 np.poly()  #用根求多项式方程

4.7.6 np.polyfit()  #拟合多项式函数

4.8 多项式函数类

4.8.1 np.polynomial.Polynomial()  #创建Polynomial对象

4.8.2 p.deriv()  #计算导函数

4.8.3 np.polynomial.Chebyshev()(拓展)

4.9 各种乘积运算

4.9.1 np.dot()  #矩阵乘积

4.9.2 np.inner()  #内积

4.9.3 np.outer()  #外积

4.9.4 np.tensordot()  #张量乘积


简介

NumPy提供了两种基本的对象:

1.ndarry:储存单一数据类型的多维数组

2.nfunc:对数组进行处理的特殊函数

查看numpy库的版本:

import numpy
print(numpy.__version__)

结果如下:

1.19.2

1.ndarray对象

1.1 创建数组

1.1.1 np.array()

用np.array()创建数组,括号中可以是列表、元组、多维列表:

import numpy as np

a = np.array([1,2,3])
b = np.array((1,2,3))
c = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])

print(a)
print(b)
print(c)

结果如下:

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

1.2 数组形状与元素类型

1.2.1 ndarray.shape  #获得形状

用ndarray.shape可获得数组的形状,返回元组(几行,几列):

import numpy as np

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

print(a.shape)
print(b.shape)

结果如下:

(3,)
(3, 4)

1.2.2 ndarray.reshape()  #改变形状

用ndarray.reshape(x,y)可以改变数组形状:

import numpy as np

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

b = a.reshape(2,6)
print(b)

结果如下:

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

(ps.b是通过a的转化得来,因此在这之后对a操作也会引起b的变化,示例如下:)

import numpy as np

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

b = a.reshape(2,6)

a[0][0] = 100

print(a)
print(b)

结果如下:

[[100   2   3   4]
 [  5   6   7   8]
 [  9  10  11  12]]
[[100   2   3   4   5   6]
 [  7   8   9  10  11  12]]

1.2.3 ndarray.dtype  #获得元素类型

ndarray.dtype可以得到数组元素的类型:

import numpy as np

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

print(a.dtype)

结果如下:

int32

即32位的长整型(默认值与操作系统和Python有关)

1.2.4 ndarray.astype()  #转换元素类型

astype()方法可以对数组的元素类型进行转换:

import numpy as np

a = np.array([1,2,3])
b = a.astype(np.float)
c = a.astype(np.complex)

print(b.dtype)
print(b)

print(c.dtype)
print(c)

结果如下:

float64
[1. 2. 3.]
complex128
[1.+0.j 2.+0.j 3.+0.j]

 1.2.5 np.set_printoptions(precision = )  #控制小数点位数

该函数可以控制输出的数组中显示小数点位数

(set_printoptions()里还有很多参数,在此仅说明precision的意义)

import numpy as np

np.set_printoptions(precision = 3)    #四舍五入保留三位小数

a = np.array([0.12345,2.54687])
print(a)

结果如下:

[0.123 2.547]

1.3 自动生成数组

1.3.1 np.arange()  #等差一维数组

np.arange(start, stop, step)可以创建等差数列的一维数组,其中开始值和终值遵循“左闭右开”的原则,类似于list中的range()

import numpy as np

a = np.arange(0,1,0.1)

print(a)

结果如下:

[0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]

1.3.2 np.linspace()  #等差一维数组

np.linspace(start, stop, number, endpoint = )中可以指定开始值、终值和元素个数,可以通过endpoint参数指定是否包含终值,endpoint = True 则包含终值(默认为True)

import numpy as np

a = np.linspace(0,1,10,endpoint = False)

print(a)

结果如下:

[0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]

1.3.3 np.logspace()  #指数数组

np.logspace()与np.linspace()相似,其start和stop为10的幂,例如(0,3,3)表示从10^{0}开始到10^{3},元素数量为4的等比数列:

import numpy as np

a = np.logspace(0,3,4)

print(a)

结果如下:

[   1.   10.  100. 1000.]

1.3.4 np.zeros()、np.ones()、np.empty()、np.full()  #特殊数组

np.zeros():创建制定形状的全零数组

np.ones():创建制定形状的全一数组

np.empty():只分配数组所使用的内存

np.full():将元素初始化为指定的值

import numpy as np

a = np.zeros((2,3),int)
b = np.ones((2,3),int)
c = np.empty((2,3),float)
d = np.full((2,3),666)

print(a)
print(b)
print(c)
print(d)

结果如下:

[[0 0 0]
 [0 0 0]]
[[1 1 1]
 [1 1 1]]
[[1.  1.1 1.2]
 [9.7 9.8 9.9]]
[[666 666 666]
 [666 666 666]]

1.3.5 np.zeros_like()、np.ones_like()、np.empty_like()、np.full_like()  #形状相同的特殊数组

括号中输入数组,创建与输入数组相同形状的全零数组、全一数组等等

以np.zeros_like()为例:

import numpy as np

a = [[1,2,3,4],[5,6,7,8]]
print(a)

b = np.zeros_like(a)
print(b)

结果如下:

[[1, 2, 3, 4], [5, 6, 7, 8]]
[[0 0 0 0]
 [0 0 0 0]]

1.4 存取元素

1.4.1 下标、切片

与列表(list)中操作相同,不再赘述

1.4.2 ndarray[[ ]]  #批量提取数组元素

两个[[ ]]中填入需要的元素下标,该操作可以提取ndarry指定下标的元素并组成一个新的数组:

import numpy as np

a = np.arange(10,20,1)
print(a)

b = a[[2,4,6,8]]
print(b)

结果如下:

[10 11 12 13 14 15 16 17 18 19]
[12 14 16 18]

这种方法中,可以理解为:b是将a中元素提取后重新创建的一个数组,因此a和b不共用内存,所以对a操作不会影响b,a和b是相互独立的,互不影响。

ndarray[[ ]]也可以快速修改指定下标位置处元素的值:

import numpy as np

a = np.arange(0,10,1)
print(a)

a[[2,4,6,8]] = 0,0,0,0
print(a)

结果如下:

[0 1 2 3 4 5 6 7 8 9]
[0 1 0 3 0 5 0 7 0 9]

1.4.3 ndarray.take()  #获取元素

沿着指定轴获取元素

import numpy as np

a = np.arange(3*4).reshape(3,4)
print(a)

result = a.take(indices = 0,axis = 1)
print(result)

结果如下:

[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

[0 4 8]

即:沿着axis = 1(纵轴)取第0列元素

1.4.3 np.compress()  #通过布尔数组获取元素

沿着指定轴通过布尔数组获取元素

np.compress(condition, ndarray, axis = )

import numpy as np

a = np.array([0,1,-2,0,3])
print(a)

b = np.compress([1,0,1],a,axis = 0)
print(b)

c = np.compress([1,0,1,0,1],a,axis = 0)
print(c)

结果如下:

[ 0  1 -2  0  3]
[ 0 -2]
[ 0 -2  3]

即在数组a中,沿着axis = 0的轴(横轴),取布尔数组中真值对应下标的元素

1.5 多维数组

1.5.1 二维数组的创建

二维数组的创建实际上是一个加法表,由纵向量和横向量的元素相加而得,例如:

import numpy as np

a = np.arange(0,60,10).reshape(-1,1) 
b = np.arange(0,6)

print(a)
print(b)
print(a+b)

结果如下:

[[ 0]
 [10]
 [20]
 [30]
 [40]
 [50]]
[0 1 2 3 4 5]
[[ 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]]

1.5.2 二维数组的切片

import numpy as np

a = np.arange(0,60,10).reshape(-1,1) + np.arange(0,6)
print(a)
print('\n')

print(a[0,3:5])    #表示第0行的第3到5个元素
print('\n')

print(a[4:,4:])    #第4行之后及第4列之后元素组成的数组
print('\n')

print(a[:,2])    #每一行的第二个元素组成的列表
print('\n')

print(a[2::2,::2])    

结果如下:

[[ 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]]


[3 4]


[[44 45]
 [54 55]]


[ 2 12 22 32 42 52]


[[20 22 24]
 [40 42 44]]

需要注意的是,b = a[0,3:5]这样的切片中,b是a的视图,他们共享数据,因此,改变a会对b造成影响

1.6 结构数组

1.6.1 定义结构数组 np.dtype()

创建一个dtype对象person,其参数是字典,键:'names','formats',

其中names定义结构中每个字段的名称;formats定义每个字段的类型:

        'S30':长度为30个字节的字符串类型,(必须指明其长度)

        'i':32位的整数类型,相当于'np.int32'

        'f':32位的单精度浮点型,相当于'np.float32'

然后调用array()创建数组,通过dtype参数来制定创建的数组的元素类型为person

import numpy as np

person = np.dtype({
    'names':['name','age','height'],  #'names'是固定名称,不可更改,但name、age等可更改
    'formats':['S30','i','f']},       #'formats'是固定名称,不可更改
    align = True)

a = np.array([('Jia',20,177),('Zhang',19,159)],dtype = person)

print(a)

print(a.dtype)

结果如下:

[(b'Jia', 20, 177.) (b'Zhang', 19, 159.)]

{'names':['name','age','height'], 'formats':['S30','<i4','<f4'],
 'offsets':[0,32,36], 'itemsize':40, 'aligned':True}

其中'<i4','<f4'的'<'表示低位字节在前,即小端模式(little endian);'>'表示高位字节在前,即大端模式(big endian);不显示则表示忽略字节顺序。

1.6.2 结构数组的存取

结构数组的存取和一般数组相同,通过下标就能获取:

import numpy as np

person = np.dtype({
    'names':['name','age','height'],  
    'formats':['S30','i','f']},        
    align = True)

a = np.array([('Jia',20,177),('Zhang',19,159)],dtype = person)

print(a[0])

结果如下:

(b'Jia', 20, 177.)

需要注意的是,输出的结果长得像元组,但并不是元组,而是结构:

print(a[0].dtype)

结果如下:

{'names':['name','age','height'], 'formats':['S30','<i4','<f4'],
 'offsets':[0,32,36], 'itemsize':40, 'aligned':True}

因此可以用字段名作为下标获取相应元素,也可以通过这种方法修改元素:

print(a[0]['name'])

结果如下:

b'Jia'

2.ufunc对象

2.1 四则运算

数组的运算符以及对应的ufunc函数
表达式对应的ufunc函数
y = x1 + x2add(x1, x2 [ ,y])
y = x1 - x2subtract(x1, x2 [ ,y])
y = x1 * x2multiply(x1, x2 [ ,y])
y = x1 / x2divide(x1, x2 [ ,y]),如果两个数组的元素为整数,则用整数除法
y = x1 / x2true_divide(x1, x2 [ ,y]),总是返回精确的商
y = x1 // x2floor_divide(x1, x2 [ ,y]),总是对返回值取整
y = -xnegative(x [ ,y])
y = x1 ** x2power(x1, x2 [ ,y])
y = x1 % x2remainder(x1, x2 [ ,y]),mod(x1, x2 [ ,y])

用符号也可以直接运算:

import numpy as np

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

print(a+b)
print(a-b)
print(a*b)
print(a/b)
print(a//b)
print(-a)
print(a**b)
print(a%b)

结果如下:

[4 4 4]
[-2  0  2]
[3 4 3]
[0.33333333 1.         3.        ]
[0 1 3]
[-1 -2 -3]
[1 4 3]
[1 0 0]

2.2 比较运算和布尔运算

2.2.1 比较运算(<,=,>)

比较两个数组的对应元素,如果满足要求则不二数组对应位置为True,否则为False

表达式对应的ufunc函数
x1 == x2equal(x1, x2 [ ,y])
x1 !=  x2not_equal(x1, x2 [ ,y])
x1 < x2less(x1, x2 [ ,y])
x1 <= x2less_equal(x1, x2 [ ,y])
x1 > x2greater(x1, x2 [ ,y])
x1 >= x2greater_equal(x1, x2 [ ,y])

用符号也可以直接运算:

import numpy as np

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

print(a == b)
print(a != b)
print(a < b)
print(a <= b)
print(a > b)
print(a >= b)

结果如下:

[False  True False]
[ True False  True]
[ True False False]
[ True  True False]
[False False  True]
[False  True  True]

2.2.2 布尔运算(np.logical_and、or、not)

Python中布尔运算使用and、or、not关键字,无法被重载,因此数组的布尔运算只能通过相应的ufunc函数进行,他们都以“logical_”开头:logical_and()、logical_or()、logical_not()

import numpy as np

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

print(np.logical_and(a > b,a == b))

结果如下:

[False False False]

2.2.3 布尔运算(np.all()、np.any())

NumPy中也定义了np.any()和np.all()

np.any():只要有一个元素为True就返回True

np.all():只有当全部元素都为True才返回True

import numpy as np

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

print(np.all(a))
print(np.any(a))

结果如下:

False
True

2.3 自定义ufunc函数

2.3.1 np.frompyfunc()  #分段函数

通常情况下,自定义(def)出的函数只能计算单个值

例如:定义一个分段函数,小于-10时输出-1,在-10到10之间输出0,大于10输出1。

def f(a,b,x):
    if x <= a:
        return -1
    if a < x <b:
        return 0
    if x >= b:
        return 1

c = 6
result = f(-10,10,c)
print(result)

结果如下:

0

但如果此时c不再是一个数字,而是一串数字,例如列表、数组,这种函数就不能直接计算,只能多次调用,单独计算。通过np.frompyfunc()可以将计算单个值的函数转化为能对数组的每个元素进行计算的ufunc函数。

np.frompyfunc()的调用格式为:np.frompyfunc(func, nin, nout)。其中func:计算单个值的函数;nin:func中输入参数的个数;nout:func中返回值的个数。(注意:np.frompyfunc()只起到转换函数的作用,需要计算时要重新调用)

例如:定义一个分段函数,小于-10时输出-1,在-10到10之间输出0,大于10输出1

import numpy as np

def f(a,b,x):
    if x <= a:
        return -1
    if a < x <b:
        return 0
    if x >= b:
        return 1

function = np.frompyfunc(f,3,1)    #只起到转换函数的作用

c = np.arange(-15,15,3)
result = function(-10,10,c)     #计算时重新调用function()函数

print(c)    #自变量
print(result)    #分段函数输出的结果

结果如下:

[-15 -12  -9  -6  -3   0   3   6   9  12]
[-1 -1 0 0 0 0 0 0 0 1]

2.4 广播(broadcasting)

使用ufunc函数对两个数组计算时,会对两个数组的对应元素进行计算,因此要求两个数组形状相同。如果不同,会进行广播(broadcasting)处理

2.4.1 广播处理规则

①以维数最多的数组为准,其他数组向它看齐,shape属性中不足的部分通过在前面加1补齐;

②输出数组的shape属性是输入数组shape属性的各个轴上的最大值;

③如果输入数组的某个长度为1,或与输出数组的对应轴长度相同,则这个数组可以用来计算,否则出错;

④当输入数组的某个轴长度为1时,沿着该轴运算时,都用该轴上的第一组值。

具体实例:

先创建一个二维数组a,形状为(6, 1)

import numpy as np

a = np.arange(0,60,10).reshape(-1,1)

print(a)
print(a.shape)

结果如下:

[[ 0]
 [10]
 [20]
 [30]
 [40]
 [50]]
(6, 1)

再创建一维数组b,其形状为(5, ):

import numpy as np

a = np.arange(0,60,10).reshape(-1,1)
b = np.arange(0,5)

print(b)

结果如下:

[0 1 2 3 4]

计算a与b的和,得到一个加法表,相当于计算两个数组中所有元素对的和,得到一个形状为(6, 5)的数组:

import numpy as np

a = np.arange(0,60,10).reshape(-1,1)
b = np.arange(0,5)
c = a+b

print(c)

结果如下:

[[ 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]]

由于a和b的维数不同,根据①,需要让b的shape属性向a对齐,于是在b的shape属性前补加1,变为(1, 5),即从 [0,1,2,3,4,5] 变成 [[0,1,2,3,4,5]],则a和b的shape变为(6, 1)和(1, 5),根据②,输出的数组长度为各个轴长度的最大值,则输出的c的shape属性为(6, 5)

由于b的第0轴(横着的,行)的长度为1,a的第0轴的长度为6,要把b的第0轴扩展成长度为6才能相加,即:

[[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]]

对a同理,则可以保证形状相同,才能相加。

2.4.2 np.broadcast_arrays()  #查看广播之后的数组

np.broadcast_arrays()可以查看广播之后的数组,返回广播后的多个数组

import numpy as np

a = np.arange(2*3).reshape(2,3)
print(a)
print(a.shape)

b = np.array([1,2,3])
print(b)
print(b.shape)

result = np.broadcast_arrays(a,b)
print(result)

结果如下:

[[0 1 2]
 [3 4 5]]

(2, 3)

[1 2 3]

(3,)

[array([[0, 1, 2],
       [3, 4, 5]]), 
array([[1, 2, 3],
       [1, 2, 3]])]

2.4.3 ndarray.repeat()  #复制元素

ndarray.repeat(复制的次数,axis = )

其中,axis = 0表示第0轴(列),即沿着axis = 0的轴,复制数组中各个元素的值

axis = 1表示第1轴(行),同理。

例1:对二维数组,沿第0轴复制

import numpy as np

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

c = a.repeat(3,axis = 0)
print(c)

结果如下:

[[1 2 3 4 5]]

[[1 2 3 4 5]
 [1 2 3 4 5]
 [1 2 3 4 5]]

例2:对一维数组,沿第0轴复制

import numpy as np

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

c = a.repeat(3,axis = 0)
print(c)

结果如下:

[1 2 3 4 5]
[1 1 1 2 2 2 3 3 3 4 4 4 5 5 5]

例3:对二维数组,沿第1轴复制

import numpy as np

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

c = a.repeat(3,axis = 1)
print(c)

结果如下:

[[1 2 3 4 5]]
[[1 1 1 2 2 2 3 3 3 4 4 4 5 5 5]]

2.4.4 下标对象None

表示在None对应的位置创建一个长度为1的新轴,例如:a[None, :]和a.reshape(1, -1)等效

import numpy as np

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

print(a[None,:])
print(a.reshape(1,-1))
print(a[:,None])

结果如下:

[1 2 3 4 5]

[[1 2 3 4 5]]

[[1 2 3 4 5]]

[[1]
 [2]
 [3]
 [4]
 [5]]

2.5 ufunc的方法

ufunc方法本身还有一些函数,这些方法只对2个输入、1个输出的ufunc函数有效,其他的ufunc对象调用这些方法时会抛出ValueError异常

2.5.1 np.<op>.reduce()  #对数组内元素四则运算

np.<op>.reduce(array, axis = , dtype = )

<op>是指运算符,例如add、subtract、multiple、divide等等,该方法沿着axis指定的轴对数组进行操作,相当于沿着axis轴,将<op>添加到数组的各个元素之间,输出计算结果,例如:

import numpy as np

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

b = np.add.reduce(a,axis=0)    #1+2+3+4
print(b)

c = np.subtract.reduce(a,axis=0)    #1-2-3-4
print(c)

d = np.multiply.reduce(a,axis=0)    #1*2*3*4
print(d)

结果如下:

10
-8
24

2.5.2 np.<op>.accumulate()  #对数组内元素四则运算

accumulate与reduce类似,只是返回与输入形状相同的数组,保存所有的中间计算过程:

import numpy as np

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

b = np.add.accumulate(a,axis=0)
print(b)    #[1,1+2,1+2+3,1+2+3+4]

c = np.subtract.accumulate(a,axis=0)
print(c)    #[1,1-2,1-2-3,1-2-3-4]

d = np.multiply.accumulate(a,axis=0)
print(d)    #[1,1*2,1*2*3,1*2*3*4]

结果如下:

[ 1  3  6 10]
[ 1 -1 -4 -8]
[ 1  2  6 24]

2.5.3 np.<op>.reduceat()  计算多组reduce()的结果

reduceat()方法计算多组reduce()的结果,通过indices参数指定一系列的起始和终止位置,例如:

import numpy as np

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

result = np.add.reduceat(a,indices = [0,1,0,2,0,3,0])
print(result)

结果如下:

[ 1  2  3  3  6  4 10]

对于indices的每一个值,都会计算出一个值,结果中除了最后一个参数外,计算过程如下:

if indices[i] < indices[i+1]:    #如果该元素小于后面一个元素
    result[i] = <op>.reduce(a[indices[i]:indices[i+1]])    

else:    #如果该元素不小于后面一个元素
    result[i] = a[indices[i]]    

对于最后一个元素,计算过程如下:

<op>.reduce(a[indices[-1]:])

2.5.4 np.<op>.outer()  #计算表

np.<op>.outer(a,b),其结果是一个计算表(加法表,乘法表,减法表),例如:

import numpy as np

a = np.array([1,2,3,4,5])
b = np.array([2,3,4])

result = np.multiply.outer(a,b)
print(result)

结果如下:

[[ 2  3  4]
 [ 4  6  8]
 [ 6  9 12]
 [ 8 12 16]
 [10 15 20]]

相当于是乘法表(加法,减法同理):

   2  3  4
  ----------
1| 2  3  4
2| 4  6  8
3| 6  9  12
4| 8  12 16
5| 10 15 20

3.多维数组的下标存取

3.1 下标对象

多维数组的下标是一个“ 长度 = 数组维度 ”的数组,

如果下标的长度 > 数组维数,则会出错;

如果下标长度 < 数组维数,则会在下标元组后面补“ : ”,使得长度和维数相同。

----------------------------------------------------------------------

如果下标对象不是元组,NumPy会先把他转化成元组,但这个过程可能与用户想的有出入,例如:a是一个三维数组,分别用 二维列表 和 二维数组 作为下标,输出是不一样的: 

import numpy as np

a = np.arange(3*4*5).reshape(3,4,5)
print(a)    #三维数组

b = tuple([[0],[1]])    #二维元组
c = np.array([[0],[1]])    #二维数组

print(a[b])
print(a[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 24]
  [25 26 27 28 29]
  [30 31 32 33 34]
  [35 36 37 38 39]]

 [[40 41 42 43 44]
  [45 46 47 48 49]
  [50 51 52 53 54]
  [55 56 57 58 59]]]


[[5 6 7 8 9]]


[[[[ 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 32 33 34]
   [35 36 37 38 39]]]]

3.2 整数数组作为下标

如果下标元组的所有元素都是切片和整数,那么用它作为下标的得到的是原始数组的一个视图,即它和原始数组共享数据空间

3.3 布尔数组作为下标

布尔数组作为下标对象时,相当于用nonzero()将布尔数组转化成一组整数数组,然后用整数数组进行下标运算

3.3.1 np.nonzero()  #找出不为0的元素

np.nonzero()返回数组中元素不为零的值的下标组成的数组,例如:

import numpy as np

a = np.array([0,1,-2,0,3])
print(a)

b = np.nonzero(a)
print(b)

结果如下:

[ 0  1 -2  0  3]
(array([1, 2, 4], dtype=int64),)

4.NumPy的函数库

4.1 随机数(np.random模块)

笔记函数总览:

函数名功能函数名功能
rand0到1之间的随机数randn标准正态分布的随机数
randint指定范围内的随机整数normal正态分布
uniform均匀分布poisson泊松分布
permutation随机排列shuffle随机打乱顺序
choice随机抽取样本seed设置随机数种子

4.1.1 np.random.rand()(产生随机0~1浮点数)

产生0到1之间的随机浮点数,所有参数用于指定所产生数组的形状

import numpy as np

a = np.random.rand()
print(a)

b = np.random.rand(2,3)
print(b)

结果如下:

0.26454873391353306

[[0.32604263 0.61228564 0.92722863]
 [0.3631769  0.53571405 0.04554973]]

4.1.2 np.random.randn()(产生正态分布随机数)

产生服从标准正态分布的随机数,参数含义与rand()相同

import numpy as np

a = np.random.randn()
print(a)

b = np.random.randn(2,3)
print(b)

结果如下:

-0.07751610157473836
[[ 0.20687204  0.41934397 -0.80796835]
 [ 0.44276644  0.84450041 -0.41650222]]

4.1.3 np.random.randint()(产生随机整数)

产生指定范围内的随机整数,范围左闭右开

np.random.randint(start, stop, shape)

参数分别指定:起始值,终值,产生数组的形状(若没有这一项则默认返回一个随机整数)

import numpy as np

b = np.random.randint(0,10)
print(b)

c = np.random.randint(0,10,(2,3))
print(c)

结果如下:

3

[[5 8 9]
 [5 2 3]]

4.1.4 np.random.normal()(随正态分布)

正态分布,其参数有三个,分别是:期望值、标准差、形状。例如:

import numpy as np

a = np.random.normal(100,10)
print(a)

b = np.random.normal(100,10,(2,3))
print(b)

 结果如下:

97.37335368991738

[[ 99.207  88.422 113.329]
 [100.994  81.526  99.495]]

4.1.5 np.random.uniform()(均匀分布)

均匀分布,其参数有三个,分别是:起始值、终值、形状。例如:

import numpy as np

a = np.random.uniform(10,20)
print(a)

b = np.random.uniform(10,20,(2,3))
print(b)

结果如下:

17.06049626065125
[[16.817 16.852 14.206]
 [13.688 15.58  18.359]]

4.1.6 np.random.possion()(泊松分布)

泊松分布,其参数有两个,分别是:\lambda系数(单位时间或单位面积内随机事件的平均发生率)、形状。例如:

import numpy as np

a = np.random.poisson(2)
print(a)

b = np.random.poisson(2,(2,3))
print(b)

结果如下:

2

[[2 1 0]
 [2 1 4]]

4.1.7 np.random.permutation()  #产生乱序数组、打乱数组

产生一个乱序数组

当参数为整数n时,他返回 [0, n) 这n个整数的随机排列;

当参数为一个序列时,他返回这个序列的随机排列。

import numpy as np

r1 = np.random.permutation(6)  #生成乱序数组
print(r1)

a = np.array([11,12,13,14,15,16])  #打乱数组
r2 = np.random.permutation(a)
print(r2)

结果如下:

[3 0 1 2 5 4]
[12 11 16 13 15 14]

4.1.8 np.random.shuffle()  #打乱数组

将指定数组打乱,与permutation的区别是:

permutation将原数组中的元素打乱后放入新的数组中(产生了新的数组),对原数组没有影响;

shuffle直接改变原数组,将原数组打乱(不能产生新数组),是对原数组的操作,不能将其赋给新的变量

import numpy as np

a = np.array([11,12,13,14,15,16])

r1 = np.random.permutation(a)
print(r1)
print(a)

np.random.shuffle(a)
print(a)

结果如下:

[11 16 14 15 12 13]    # a打乱后赋值给r1

[11 12 13 14 15 16]    # a没有改变

[16 12 13 14 15 11]    # a被改变

4.1.9 np.random.choice()  #随机抽取

从指定样本中随机抽取

np.random.choice(ndarray, size = , replace = , p = )

size:用于指定输出数组的形状

replace:replace = True(默认)时,进行放回抽取;否则进行不放回抽取

p:指定每个元素的抽取概率(以列表或数组形式),如果不指定则默认为等概率抽取

当参数只有ndarray时,则返回随机抽取的一个数

import numpy as np

a = np.arange(10)

r1 = np.random.choice(a)
print(r1)

r2 = np.random.choice(a,size = (2,3),replace = True,p = a/np.sum(a))
print(r2)

结果如下:

2

[[1 7 5]
 [8 7 2]]

4.1.10 np.random.seed()  #种子

保证每次运行时出现相同的随机数,可以通过seed()指定随机数的种子

调用格式为:np.random.seed(num)

import numpy as np

np.random.seed(2)

a = np.random.rand()
print(a)

结果如下:

0.43599490214200376(运行无数次都是这个结果)

4.2 求和、平均值、方差

函数总览:

函数名功能函数名功能
sum求和mean求期望
average加权平均数std标准差
var方差product连乘积

4.2.1 np.sum()  #求和

对指定元素进行求和,可以对所有元素求和,沿行(列)求和,对指定轴求和

import numpy as np

a = np.arange(2*3).reshape(2,3)
print(a)

r1 = np.sum(a)    #对所有元素求和
r2 = np.sum(a,axis = 0)    #沿着行方向,对a的每一列求和 
r3 = np.sum(a,axis = 1,dtype = float)    #沿着列方向,对a的每一行求和

print(r1)
print(r2)
print(r3)

 结果如下:

[[0 1 2]
 [3 4 5]]

15

[3 5 7]

[ 3. 12.]

4.2.2 np.mean()  #求平均数

求数组的平均值,参数与sum()相同

import numpy as np

a = np.arange(2*3).reshape(2,3)
print(a)

r1 = np.mean(a)
r2 = np.mean(a,axis = 0)

print(r1)
print(r2)

结果如下:

[[0 1 2]
 [3 4 5]]

2.5

[1.5 2.5 3.5]

4.2.3 np.average()  #计算加权平均数

average()也可以进行平均计算,特殊点在于:他有一个weights参数,可以计算加权平均数

import numpy as np

score = np.array([88,90,93])
number = np.array([15,25,30])

result = np.average(score,weights = number)
print(result)

结果如下:

90.85714285714286

4.2.4 np.std()  #计算标准差

计算数组的标准差

np.std(ndarray, axis = , dtype= , out =  , ddof= )

ddof = 0(默认)时,计算偏样本标准差;ddof = 1时,计算无偏样本标准差

import numpy as np

a = np.array([1,2,3,4,5,6])

r1 = np.std(a,axis = 0, ddof = 0)
r2 = np.std(a,axis = 0, ddof = 1)

print(r1)
print(r2)

结果如下:

1.707825127659933
1.8708286933869707

4.2.5 np.var()  #计算方差

计算数组的方差,参数与np.std()一样

import numpy as np

a = np.array([1,2,3,4,5,6])

r1 = np.var(a,axis = 0, ddof = 0)
r2 = np.var(a,axis = 0, ddof = 1)

print(r1)
print(r2)

结果如下:

2.9166666666666665
3.5

4.2.6 np.product()  #计算所有元素乘积

计算数组中所有元素的乘积

参数与np.sum()类似

import numpy as np

a = np.array([1,2,3,4,5,6])

r1 = np.product(a)
print(r1)

结果如下:

720

4.3 大小与排序

函数总览

函数名功能函数名功能
min最小值max最大值
minimum二元最小值maximum二元最大值
ptp极差argmin最小值的下标
argmax最大值的下标unravel_index一维下标转化成多维下标
sort数组排序argsort计算数组排序的下标
lexsort多列排序partition

快速计算前k位

argpartition前k位的下标median中位数
percentile百分位数searchsorted二分查找

4.3.1 np.min(),np.max(),np.minimum(),np.maximum(),np.ptp()

np.min(),np.max(),np.minimum(),np.maximum()分别表示计算最小值、最大值、二元最小值、二元最大值、极差

前四个函数的用法与np.sum()类似,np.ptp()有axis和out参数,用法与之前类似,这里例举最简单的情况:

import numpy as np

a = np.array([-1,6,4,-7,3,4])
b = np.arange(2*3).reshape(2*3)

print(a)
r1 = np.min(a)
r2 = np.max(a)
r3 = np.ptp(a)
print(r1)
print(r2)
print(r3)

print(b)
r4 = np.minimum(a,b)    #对比a和b对应位置的元素,选出两个中最小的一个,放入新数组的对应位置
r5 = np.maximum(a,b)    
r6 = np.ptp(b)
print(r4)
print(r5)
print(r6)

结果如下:

[-1  6  4 -7  3  4]    #a
-7    #min
6    #max
13    #max-min

[0 1 2 3 4 5]    #b
[-1  1  2 -7  3  4]    #minimum
[0 6 4 3 4 5]    #maximum
5    #maximum-minimum

4.3.2 np.argmax(),np.argmin()  #求最值下标

可以求最大值和最小值的下标

如果不指定axis参数,则返回平坦化(转化成一维数组)之后的数组下标

如果指定axis参数,可以沿着指定轴计算最大值的下标

import numpy as np

a = np.random.randint(0,10,size = (2,3))
r1 = np.argmax(a)
print(a)
print(r1)

结果如下:

[[8 9 0]
 [1 1 4]]
1

4.3.3 np.unravel_index()  #下标转化

可以将一维数组下标转化成多维数组的下标

np.unracel_index(下标, 多维数组的形状)

import numpy as np

a = np.random.randint(0,10,size = (2,3))
r1 = np.argmax(a)
print(a)    #输出数组a
print(r1)    #最大值在数组平坦化后的下标

r2 = np.unravel_index(r1,a.shape)
print(r2)    #最大值在原数组形状下的下标

结果如下:

[[6 0 1]
 [0 2 7]]

5

(1, 2)

4.3.4 np.sort()  #排序

np.sort()可以对数组进行排序,并将排序后的值赋给新的数组

默认axis = 1(对每行数组进行排序)

axis = 0表示对每列数组进行排序

axis = None表示,将数组平坦化后进行排序

import numpy as np
np.random.seed(1)

a = np.random.randint(0,10,size = (3,4))
print(a)

r1 = np.sort(a)
r2 = np.sort(a,axis = 1)
r3 = np.sort(a,axis = 0)
r4 = np.sort(a,axis = None)
print(r1)
print(r2)
print(r3)
print(r4)

结果如下:

[[5 8 9 5]
 [0 0 1 7]
 [6 9 2 4]]    #a

[[5 5 8 9]
 [0 0 1 7]
 [2 4 6 9]]    #r1

[[5 5 8 9]
 [0 0 1 7]
 [2 4 6 9]]    #r2

[[0 0 1 4]
 [5 8 2 5]
 [6 9 9 7]]    #r3

[0 0 1 2 4 5 5 6 7 8 9 9]    #r4

4.3.5 np.argsort()  #排序后的下标

np.argsort()返回数组的排序下标,参数axis默认为-1

import numpy as np
np.random.seed(69)

a = np.random.randint(0,10,size = (5,))
print(a)

r1 = np.argsort(a)
print(r1)

结果如下:

[6 9 7 4 1]
[4 3 0 2 1]

即:a中1是最小的,其下标是4,所以4在r1[0];

以此类推,4是a中第二小的,其下标为3,所以3在r1[1]

4.3.6 np.lexsort()  #多列排序

np.lexsort()类似于Excel中的多列排序,其参数为一个形状为(k, N)的数组,即包含k个长度为N的序列,可以理解成N行k列的表格,该方法返回排序下标,数组中最后的行为排序的主键(以数组中最后一行为标准进行排列)

例如:

import numpy as np
np.random.seed(69)

name = ['A','B','C','D','E']
age = [31,35,40,29,25]

r1 = np.lexsort([name,age])    #参数是一个2行5列的数组
print(r1)    

结果如下:

[4 3 0 1 2]

即,以最后一行(age)为标准进行排序,所以返回age的下标排序

4.3.6 np.lexsort() 应用:成绩姓名全局排序

背景:A、B等5人乘积分别是95,93,87,99,96,将姓名与成绩对应,并按成绩由大到小排列

import numpy as np
np.random.seed(69)

name = ['A','B','C','D','E']
score = [95,93,87,99,96]

idx = np.lexsort([name,score])
print(idx)

r1 = list(zip(name,score))
l = []
for i in idx:
    l.append(r1[i])
    
print(l)

结果如下: 

[2 1 0 4 3]
[('C', 87), ('B', 93), ('A', 95), ('E', 96), ('D', 99)]

4.3.7 np.partition(),np.argpartition()  #数组分割

np.partition(),np.argpartition()可以对数组进行分割,快速找出排序后数组的前k个元素(调用速度比sort()快很多)

np.partition(ndarray, kth = )

调用后,使新数组前kth个元素是原数组中最小的kth个,且这kth个也不按大小排序,只是把他们挑出来放在新数组的前面而已,剩余的放在后面随便排,例如:

import numpy as np
np.random.seed(69)

a = np.random.randint(0,10,size = (10,))
print(a)

r1 = np.partition(a,kth = 7)
print(r1)

结果如下:

[6 9 7 4 1 6 9 8 1 6]
[6 1 1 4 6 7 6 8 9 9]

即:r1的前7个元素是a中最小的7个,且在r1中没有按大小排序,只是把它们挑出来放在前七个位置上而已,后面的8,9,9是随便排的

如果需要将前7个排序,再调用一下np.sort()就可以:

import numpy as np
np.random.seed(69)

a = np.random.randint(0,10,size = (10,))
print(a)

r1 = np.partition(a,kth = 7)
print(r1)

r2 = np.sort(r1[:7])
print(r2)

结果如下:

[6 9 7 4 1 6 9 8 1 6]
[6 1 1 4 6 7 6 8 9 9]
[1 1 4 6 6 6 7]

 np.argpartition()同理,只是返回的是下标而已:

import numpy as np
np.random.seed(69)

a = np.random.randint(0,10,size = (10,))
print(a)

r1 = np.argpartition(a,kth = 7)
print(r1)

r2 = np.sort(a[r1[:7]])
print(r2)

 结果如下:

[6 9 7 4 1 6 9 8 1 6]
[5 4 8 3 0 2 9 7 6 1]
[1 1 4 6 6 6 7]

4.3.8 np.median()  #计算中位数

np.median()可以获得数组的中值,即:先把数组排序,再取中值。当长度是偶数时,取中间两个数的平均数

可以指定axis参数

import numpy as np
np.random.seed(69)

a = np.random.randint(0,5,size = (5,))
print(np.sort(a))
r1 = np.median(a)
print(r1)

b = np.random.randint(0,6,size = (6,))
print(np.sort(b))
r2 = np.median(b)
print(r2)

结果如下:

[1 2 3 3 4]
3.0
[0 0 0 1 1 1]
0.5

4.3.9 np.percentile()  #计算百分数

np.percentile()用于计算百分数,即:将元素从小大到排列,计算处于p%位置上的值

调用格式及参数:np.percentile(ndarray, p),其中p可以是一个数,也可以是一个数组

import numpy as np

a = np.array([1,2,3,4,5,6,7,8,9,10])
print(a)

r1 = np.percentile(a,[0,25,50,75,100])
print(r1)

结果如下:

[ 1  2  3  4  5  6  7  8  9 10]
[ 1.    3.25  5.5   7.75 10.  ]

4.3.10 np.searchsorted()  #插入元素(二分查找)

searchsorted(a, value, side='left')

a:已经排好序的升序数组(如果a不是升序的,则该方法会先将a升序排列)

value:插入数组a的值,可以是单个元素、列表、数组

side:可以填入‘left‘或‘right‘。left则返回第一个符合条件的元素下标;right则返回最后一个符合条件的元素下标,如果没有符合的元素,则返回0或N(数组a的长度),即应该插入到a的最开始或最末尾

若a中有value中的元素(假设该元素为i):

        当side = left(默认)时:直接返回a中第一个i的下标

        当side = right时:返回a中最后一个i的下标并+1

import numpy as np

a = np.array([2,2,2,2,4,8,16,32])
print(a)

r1 = np.searchsorted(a,2,side = 'left')
print(r1)

r2 = np.searchsorted(a,2,side = 'right')
print(r2)

结果如下:

[ 2  2  2  2  4  8 16 32]
0
4

若a中没有value中的元素:

        将value的各个元素插入到a的合适位置,使插入后的元素value满足:

            当side = left(默认)时:a[i-1] < value <= a[i](局部升序)

            当side = right时:a[i-1] <= value < a[i](局部升序)

import numpy as np

a = np.array([2,4,8,16,32])
print(a)

r1 = np.searchsorted(a,[1,3,5,7,9,11])
print(r1)

r2 = np.searchsorted(a,[1,3,5,7,9,11],side = 'right')
print(r2)

结果如下:

[ 2  4  8 16 32]
[0 1 2 2 3 3]
[0 1 2 2 3 3]

4.4 统计函数

函数总览:

函数名功能函数名功能
unique去除重复元素bincount对整数数组的元素计数
histogram一维直方图统计

4.4.1 np.unique()  #去除重复元素

np.unique()返回去除重复元素后的数组,并按从小到大的顺序排列

np.unique(ndarray, return_index, return_inverse)

return_index:为True时,返回:新数组在原数组中的下标组成的数组,默认为False

return_inverse:为True时,返回:原始数组在新数组中的下标组成的数组,默认为False

import numpy as np
np.random.seed(1)

a = np.random.randint(0,10,size = (10,))
print(a)

r1 = np.unique(a,return_index = True,return_inverse = True)
print(r1)

结果如下:

[5 8 9 5 0 0 1 7 6 9]
(array([0, 1, 5, 6, 7, 8, 9]),     #新数组
array([4, 6, 0, 8, 7, 1, 2], dtype=int64), 
array([2, 5, 6, 2, 0, 0, 1, 4, 3, 6], dtype=int64))

4.4.2 np.bincount()  #对整数数组的元素计数

np.bincount()对整数数组中各个元素的出现次数进行统计,要求原数组必须是非负的

np.bincount(ndarray, weights = )

返回一个数组,数组中下标为i的元素表示:数字i出现的次数

import numpy as np
np.random.seed(1)

a = np.random.randint(0,10,size = (10,))
print(a)

r1 = np.bincount(a)
print(r1)

结果如下:

[5 8 9 5 0 0 1 7 6 9]
[2 1 0 0 0 2 1 1 1 2]

即:0出现2次,1出现1次,3出现0次…… 

参数weights可以指定一个数组w,表示每个数所对应的权值。

返回数组a中的每个整数所对应的w中的权值之和,例如:

import numpy as np
np.random.seed(1)

a = np.random.randint(0,4,size = (5,))
print(a)

w = np.array([0.1,0.2,0.3,0.4,0.5])
print(w)

r1 = np.bincount(a,weights = w)
print(r1)

结果如下:

[1 3 0 0 3]
[0.1 0.2 0.3 0.4 0.5]
[0.7 0.1 0.  0.7]

即:0所对应的权值为0.3+0.4=0.7;1所对应的权值为0.1;

       2所对应的权值为0;3所对应的权值为0.2+0.5=0.7

所以返回[0.7, 0.1, 0, 0.7]

4.4.3 np.histogram()  #直方图统计

np.histogram()对一维数组进行直方图统计

np.histogram(ndarray, bis = , range = , weights = , density = )

bis:统计区间的个数,bis是一个数,则将统计范围等分成bis份;若bis是一个数组,则可以实现区间的不等分,例如[0, 0.1, 0.3, 0.4, 0.9, 1]

range:该参数是一个长度为2的元组,表示统计范围的最小值和最大值。默认为None,即(a.min(), a.max())

weights:与np.biscount()中的weights类似,表示权值,若指定weights参数,则对区间中数值所对应的权值进行求和

density:为False时,返回ndarray的数据在每个区间中的个数;True时,返回每个区间的概率密度

该方法返回两个一维数组:hist和bin_edges。hist是每个区间的统计结果,bin_edges是hist所对应的区间,的长度是len(hist)+1,每两个相邻数值构成一个统计区间

例如:

import numpy as np
np.random.seed(1)

a = np.random.rand(100)

r1 = np.histogram(a,bins = 5,range = (0,1))
print(r1)

结果如下:

(array([24, 16, 21, 20, 19], dtype=int64), 
array([0. , 0.2, 0.4, 0.6, 0.8, 1. ]))

即:生成100个0~1之间的随机数,然后将区间(0, 1)等分成5份,结果显示有24(第一个数组的结果)个元素在0~0.2(第二个数组的结果)之间,16个元素在0.2~0.4之间……

4.5 分段函数

函数总览

函数名功能函数名功能
where

矢量化判断表达式

piecewise分段函数
select多分支判断选择

4.5.1 np.where()  #if

x = np.where(condition, y, z)

其中condition, y, z都是数组,其返回值是一个形状与condition相同的数组

当condition中的某个元素为True时,x中对应下标的值从数组y获取,否则从z获取

import numpy as np
np.random.seed(1)

x = np.random.randint(0,10,size = (5,))
print(x)

y = np.where(x<5,'yes','no')
print(y)

结果如下:

[5 8 9 5 0]
['no' 'no' 'no' 'no' 'yes']

4.5.2 np.select()  #多分支的if

如果分段函数分段的数量很多,就需要用np.where()一层一层嵌套,不利于编写与阅读用np.select()就可以解决这个问题

select(condlist, choicelist, default = 0)

condlist:长度为N的布尔数组列表(必须是列表形式),用于判断分段的条件(例如x是否<5)

choicelist:长度为N的储存候选值的数组列表(必须是列表形式),用于具体计算

default:当所有条件都不满足时,用default填上

关于布尔数组,例如:

import numpy as np
np.random.seed(1)

a = np.random.randint(0,10,size = 5)
print(a)
x = [a<5]    #布尔数组
print(x)

结果如下:

[5 8 9 5 0]
[array([False, False, False, False,  True])]

对于np.select的具体用法,

例如:分段函数:x<5时,y=x**2;5<=x<=10时,y=-x;x>10时,y=0

import numpy as np
np.random.seed(5)

x = np.random.randint(0,15,size = 10)
print(x)

#指明自变量分段的条件
condition = [x<5,
             np.logical_and(x>=5,x<=10),    #用逻辑运算,Python不支持5<=x<=10
             x>10]

#指明各段的函数
choice = [x**2,-x,0]

y = np.select(condition,choice)
print(y)

结果如下:

[ 3 14 13  6  6  0  9  8  4  7]
[ 9  0  0 -6 -6  0 -9 -8 16 -7]

4.5.3 np.piecewise()  #分段函数

尽管用np.select,如果输入的数组很大,计算时会产生许多保存中间结果的数组,会发生大量内存分配和释放。为了解决这个问题,有np.piecewise()专门计算分段函数

np.piecewise(x, condlist, funclist)

condlist:长度为M的布尔数组列表

funclist:长度为M或M+1的函数列表,这些函数的输入和输出都是数组;如果长度为M,则正常计算;如果长度为M+1,则最后一个函数计算所有条件都为False时的值

例如:分段函数:x<5时,y=x**2;5<=x<=10时,y=-x;x>10时,y=0

import numpy as np
np.random.seed(5)

x = np.random.randint(0,15,size = 10)
print(x)

#指明自变量分段的条件
condition = [x<5,
             np.logical_and(x>=5,x<=10),    #用逻辑运算,Python不支持5<=x<=10
             x>10]

#指明各段的函数,此处需要用lambda
funclist = [lambda x:x**2,
            lambda x:-x,
            0]

y = np.piecewise(x,condition,funclist)
print(y)

结果如下:

[ 3 14 13  6  6  0  9  8  4  7]
[ 9  0  0 -6 -6  0 -9 -8 16 -7]

4.6 操作多维数组

函数总览

函数名功能函数名功能
concatenate连接多个数组vstack沿第0轴连接数组
hstack、c_[]沿第1轴连接数组column_stack按列连接多个一维数组
split、array_split将数组分为多段transpose重新设置轴的顺序
swapaxes交换两个轴的顺序

4.6.1 np.concatenate()  #连接多个数组

用于连接多个数组,第一个参数为需要连接的数组,用()括起来,第二个参数是axis,用于指定沿axis轴进行连接,默认为0

import numpy as np
np.random.seed(5)

a = np.zeros((3,3))
b = np.ones((3,3))

r1 = np.concatenate((a,b))
print(r1)

r2 = np.concatenate((a,b),axis = 1)
print(r2)

结果如下:

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

4.6.2 np.vstack()  #沿第0轴连接数组

np.vstack()用于沿着第0轴连接数组,当被连接数组是长度为N的一维数组时,将其形状改为(1, N)

其参数为要连接的数组,用()括起来

import numpy as np
np.random.seed(5)

a = np.zeros((3,3))
b = np.ones((3,3))

r1 = np.vstack((a,b))
print(r1)

结果如下:

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

4.6.3 np.hstack()  #沿第1轴连接数组

与np.vstack()相似,沿着第1轴连接数组,当所有数组都是一维时,沿着第0周连接数组

import numpy as np
np.random.seed(5)

a = np.zeros((3,3))
b = np.ones((3,3))

r1 = np.hstack((a,b))
print(r1)

结果如下:

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

4.6.4 np.c[]  #按列连接多个一维数组

和np.hstack()一样,按列连接数组

调用格式为:np.c_[a,b]

import numpy as np
np.random.seed(5)

a = np.zeros((3,3))
b = np.ones((3,3))

r1 = np.c_[a,b]
print(r1)

结果如下:

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

4.6.5 np.split()、np.array_split()  #将数组分为多段

np.split()、np.array_split()用法基本相同,将一个数组沿着指定轴分成多个数组,可以直接或指定切分轴上的切分点下标

np.split(a, indices_or_sections, axis=0)

indices_or_sections:类型为int或一维数组,表示切的位置。如果值是一个整数n的话,就将数组平均分为n份(如果不能平均分则报错);如果是一个数组的话,就医数组中的数字为索引切开

axis:对于二维数组,axis = 0表示横向切(用刀横着切数组),axis = 表示纵向切

具体见下方实例:

1.当 indices_or_sections为整数时):

import numpy as np
np.random.seed(5)

a = np.arange(1,10).reshape(3,3)
print(a)

r1 = np.split(a,3)    # indices_or_sections为整数
print(r1)

A,B,C = np.split(a,3)    # indices_or_sections为整数
print(A)
print(B)
print(C)

结果如下:

[[1 2 3]
 [4 5 6]
 [7 8 9]]

[array([[1, 2, 3]]), array([[4, 5, 6]]), array([[7, 8, 9]])]

[[1 2 3]]

[[4 5 6]]

[[7 8 9]]

2.当 indices_or_sections为数组时(axis = 0):

import numpy as np
np.random.seed(5)

a = np.arange(5*6).reshape(5,6)
print(a)

A,B,C = np.split(a,[1,4])
print(A)
print(B)
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]
 [24 25 26 27 28 29]]

#横向切(横着切),在纵向下标为1和4处分隔
[[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]]

3.当 indices_or_sections为数组时(axis = 0):

import numpy as np
np.random.seed(5)

a = np.arange(5*6).reshape(5,6)
print(a)

A,B,C = np.split(a,[1,4],axis = 1)
print(A)
print(B)
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]
 [24 25 26 27 28 29]]

#纵向切(竖着切),在横向下标为1和4处分隔
[[ 0]
 [ 6]
 [12]
 [18]
 [24]]

[[ 1  2  3]
 [ 7  8  9]
 [13 14 15]
 [19 20 21]
 [25 26 27]]

[[ 4  5]
 [10 11]
 [16 17]
 [22 23]
 [28 29]]

4.6.6 np.transpose()、np.swapaxes()  #重新设置轴的顺序

np.transpose()用于修改轴的顺序

例如:np.transpose(a,[1,2,0])表示:新数组的第0轴存放a的第1轴,新数组的第1轴存放a的第2轴,新数组的第2轴存放a的第0轴

import numpy as np

a = np.arange(1*2*3).reshape(1,2,3)
print(a.shape)

r1 = np.transpose(a,[1,2,0])
print(r1.shape)

结果如下:

(1, 2, 3)
(2, 1, 3)

4.6.7 np.swapaxes()  #交换两个轴的顺序

np.swapaxes()用于交换两个轴的顺序

例如:np.swapaxes(a,0,1)表示:将a的第0轴和第1轴交换顺序

import numpy as np

a = np.arange(2*3*4).reshape(2,3,4)
print(a.shape)

r1 = np.swapaxes(a,0,1)
print(r1.shape)

结果如下:

(2, 3, 4)
(3, 2, 4)

4.7 多项式函数

4.7.1 np.poly1d()  #转化成poly1d对象

np.poly1d()可以将列表、数组转化成poly1d对象,该对象可以像函数一样调用

import numpy as np

a = np.array([1,2,3])
r1 = np.poly1d(a)
print(r1)

结果如下:

   2
1 x + 2 x + 3

即表示:x^{2}+2x+3

用法1:可以像函数一样被调用:

import numpy as np

a = np.array([1,2,3])
f = np.poly1d(a)
print(f)

r1 = f(2)    #x=2带入
print(r1)

结果如下:

   2
1 x + 2 x + 3

11    #表示x=2时上式的结果

用法2:多项式的四则运算

import numpy as np

a = np.array([1,2,3])
f = np.poly1d(a)
print(f)

print(f + [5,5])
print(f*2)
print(f*f)
print(f/[1,3])

结果如下:

   2
1 x + 2 x - 3    # f

   2
1 x + 7 x + 2    # f + [5,5]

   2
2 x + 4 x - 6    # f*2

   4     3     2
1 x + 4 x - 2 x - 12 x + 9    # f*f

(poly1d([ 1., -1.]), poly1d([0.]))    #f/[1,3]  
#返回两个poly1d类型的元素,第一个是商,第二个是余数

4.7.2 deriv()  #计算微分

deriv()用于计算多项式函数的微分,调用格式为:poly1d对象.deriv()

import numpy as np

a = np.array([1,2,-3])
f = np.poly1d(a)
print(f)

r1 = f.deriv()
print(r1)

结果如下:

   2
1 x + 2 x - 3
 
2 x + 2

4.7.3 integ()  #计算积分

integ()用于计算多项式函数的积分,调用格式为:poly1d对象.integ()

import numpy as np

a = np.array([1,2,-3])
f = np.poly1d(a)
print(f)

r1 = f.integ()
print(r1)

结果如下:

   2
1 x + 2 x - 3
        3     2
0.3333 x + 1 x - 3 x

4.7.4 np.roots()  #求根

np.roots()用于计算多项式函数的根,调用格式为:np.roots(poly1d对象)

import numpy as np

a = np.array([1,2,-3])
f = np.poly1d(a)
print(f)

r1 = np.roots(f)
print(r1)

结果如下:

   2
1 x + 2 x - 3
[-3.  1.]

4.7.5 np.poly()  #用根求多项式方程

np.poly()可以通过根求多项式系数

import numpy as np

a = np.array([1,2])
r1 = np.poly(a)
print(r1)

结果如下:

[ 1. -3.  2.]

4.7.6 np.polyfit()  #拟合多项式函数

np.polyfit():根据数据拟合出相应的多项式函数,找出与这组数据的误差平方最小的多项式的系数

np.polyfit(x, y, 最高次的次数)

import numpy as np

a = np.array([1,2,3,4,5])
b = np.array([1,4,9,16,25])

r1 = np.polyfit(a,b,3)
print(r1)

结果如下:

[ 1.62920807e-17  1.00000000e+00 -4.54973822e-15  2.70557374e-15]

4.8 多项式函数类

np.polynomial中提供了更丰富的多项式函数类,其中多项式各项的系数按照幂从小到大的顺序排列(与4.7相反)

4.8.1 np.polynomial.Polynomial()  #创建Polynomial对象

np.polynomial.Polynomial()可以创建Polynomial对象,并计算多项式函数

import numpy as np

a = np.array([1,2,3])
f = np.polynomial.Polynomial(a)
r1 = f(2)    #计算1*(2^0) + 2*(2^1) + 3*(2^2)
print(r1)

结果如下:

17.0

4.8.2 p.deriv()  #计算导函数

对于Ploynomial对象,p.deriv()可以计算导函数:

import numpy as np

a = np.array([1,2,3])
f = np.polynomial.Polynomial(a)
r1 = f.deriv()
print(r1)

结果如下:

poly([2. 6.])

即:1+2x+3x^{2},求导得 2+6x

4.8.3 np.polynomial.Chebyshev()(拓展)

切比雪夫多项式是一个正交多项式序列T_{i}(x),一个n次多项式可以表示为多个切比雪夫多项式的加权和

使用Chebyshev类表示由切比雪夫多项式组成的多项式p(x)=\sum_{i=0}^{n}c_{i}T_{i}(x)

T_{i}(x)多项式可由Chebyshev.basis(i)获得

1.利用convert方法转换多项式类型

语句:Chebyshev.basis(i).convert(kind = )

例如:将T_{4}(x)转化成Polynomial类:

import numpy as np

a = np.polynomial.Chebyshev.basis(4)
print(a)

r1 = a.convert(kind = np.polynomial.Polynomial)
print(r1)

结果如下:

cheb([0. 0. 0. 0. 1.])
poly([ 1.  0. -8.  0.  8.])

即:T_{4}(x)=1-8x^{2}+8x^{4}

2.切比雪夫节点

切比雪夫多项式的根称为切比雪夫节点可以用于多项式插值。相应的差值多项式能最大程度降低龙格现象(等距插值多项式在两端有很大的振荡),并且提供多项式在连续函数的最佳一致逼近。

详细查看(p101)

4.9 各种乘积运算

函数总览

函数名功能函数名功能
dot矩阵乘积inner内积
outer外积tensordot张量乘积

4.9.1 np.dot()  #矩阵乘积

对于一维数组,其计算内积;对于二维数组,其计算矩阵乘积

通用公式:dot(a, b)[i, j, k, m] = sum(a[i, j, :] * b[k , :, m])

对于一维数组:直接计算内积,即向量点乘

import numpy as np
#一维数组
a = np.arange(3)
b = np.array([2,3,4])
print(a)
print(b)

r1 = np.dot(a,b)
print(r1)

结果如下:

[0 1 2]
[2 3 4]
11    # 0*2 + 1*3 + 2*4

对于二维数组:进行矩阵乘法(第一行乘第一列,m*n与n*k才能相乘)

import numpy as np
# 二维数组
a = np.arange(6).reshape(3,2)
b = np.array([[2,3,4],[5,6,7]])
print(a)
print(b)

r1 = np.dot(a,b)
print(r1)

结果如下:

[[0 1]
 [2 3]
 [4 5]]

[[2 3 4]
 [5 6 7]]

[[ 5  6  7]
 [19 24 29]
 [33 42 51]]

4.9.2 np.inner()  #内积

np.inner()用于计算内积

对于一维数组,inner()和dot()一样,

对于二维数组,具体计算过程见下例

计算内积时,需保证两个矩阵形状相同!!!

import numpy as np
# 二维数组
a = np.arange(6).reshape(2,3)
b = np.array([[2,3,4],[5,6,7]])
print(a)
print(b)

r1 = np.inner(a,b)
print(r1)

结果如下:

[[0 1 2]     # a行
 [3 4 5]]    # b行

[[2 3 4]     # c行
 [5 6 7]]    # d行

[[11 20]     # [a*c  a*d]
 [38 74]]    # [b*c  b*d]

4.9.3 np.outer()  #外积

np,outer()用于计算外积,且只对一维数组进行计算,如果传入的是多维数组,先将数组展平为一维数组再计算(具体计算过程见下例)

对于一维数组:

import numpy as np
# 一维数组
a = np.arange(3)
b = np.array([2,3,4])
print(a)
print(b)

r1 = np.outer(a,b)
print(r1)

结果如下:

[0 1 2]

[2 3 4]

[[0 0 0]    # [0*2 0*3 0*4] 或 [a11*b11 a11*b12 a11*b13]
 [2 3 4]    # [1*2 1*3 1*4]
 [4 6 8]]   # [2*2 2*3 2*4]

对于二维数组:

import numpy as np
# 二维数组
a = np.arange(6).reshape(2,3)
b = np.array([[2,3,4],[5,6,7]])
print(a)
print(b)

r1 = np.outer(a,b)
print(r1)

结果如下:

[[0 1 2]
 [3 4 5]]
[[2 3 4]
 [5 6 7]]
[[ 0  0  0  0  0  0]     # [0*2 0*3 0*4 0*5 0*6 0*7]
 [ 2  3  4  5  6  7]     # [1*2 1*3 1*4 1*5 1*6 1*7]
 [ 4  6  8 10 12 14]     # ……
 [ 6  9 12 15 18 21]
 [ 8 12 16 20 24 28]
 [10 15 20 25 30 35]]

4.9.4 np.tensordot()  #张量乘积

np.tensordot()将两个多维数组a和b指定轴上的对应元素相乘并求和

np.tensordot(a,b,axes = [[轴1],[轴2]])

axes有两个参数,第一个表示a中的轴,第二个表示b中的轴,该方法会将指定轴的对应元素相乘再相加

(即:第一?和第一?相乘并相加,放在a11,第一?和第二?相乘再相加,放在a12,……其中轴1和轴2分别控制两个问号,0表示列,1表示行。例如:axes = [[0],[1]]表示第一列和第一行相乘并相加,放在a11,以此类推……)

如果axes是整数,则表示把a中的后axes个轴和b中的前axes个轴进行相乘再相加的运算,其他轴保持不变

import numpy as np
# 二维数组
a = np.arange(9).reshape(3,3)
b = np.array([[2,3,4],[5,6,7],[8,9,10]])
print(a)
print(b)

r1 = np.tensordot(a,b,axes = [[0],[0]])    #表示a的列和b的列相乘,放在a11……
print(r1)

结果如下:

[[0 1 2]
 [3 4 5]
 [6 7 8]]

[[ 2  3  4]
 [ 5  6  7]
 [ 8  9 10]]

[[ 63  72  81]
 [ 78  90 102]
 [ 93 108 123]]

  • 50
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值