Python 中的Numpy函数



一、什么是Numpy

简单的说,Numpy 是 Python 的一个科学计算包,包含了多维数组以及多维数组的操作。
Numpy 的核心是 ndarray 对象,这个对象封装了同质数据类型的n维数组。起名 ndarray 的原因就是因为是 n-dimension-array 的简写。

1.1 ndarray

Numpy 中最重要的一个对象就是 ndarray。
ndarray中的每个元素在内存中使用相同大小的块。 ndarray中的每个元素是数据类型对象的对象(称为 dtype)。

构建ndarray

#导入numpy包
import numpy as np

np.array() 就相当于我们学习过的list,int,str等等,将其他的数据类型转换为ndarray

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

1.2 数据类型

Numpy 中的数组比 Python 原生中的数组(只支持整数类型与浮点类型)强大的一点就是它支持更多的数据类型。
Numpy 常见的基本数据类型如下:

数据类型描述
bool_布尔(True或False),存储为一个字节
int_默认整数类型(与C long相同;通常为int64或int32)
intc与C int(通常为int32或int64)相同
intp用于索引的整数(与C ssize_t相同;通常为int32或int64)
int8字节(-128到127)
int16整数(-32768到32767)
int32整数(-2147483648至2147483647)
int64整数(-9223372036854775808至9223372036854775807)
uint8无符号整数(0到255)
uint16无符号整数(0到65535)
uint32无符号整数(0至4294967295)
uint64无符号整数(0至18446744073709551615)
float_float64的简写。
float16半精度浮点:符号位,5位指数,10位尾数
float32单精度浮点:符号位,8位指数,23位尾数
float64双精度浮点:符号位,11位指数,52位尾数
objectPython对象,放什么都可以

重点:ndarry里面只能装一种数据类型
需要注意的是,不同于 Python 列表,NumPy 要求数组必须包含同一类型的数据。如果类型不匹配,NumPy 将会向上转换(如果可行)。
那么什么叫做向上转换呢?

b = np.array([3.14, 4, 2, 3])
b
>>array([3.14, 4.  , 2.  , 3.  ])

1、数据中存在整数型和浮点型数据,最终转换结果为都变成了浮点型数据

np.array(['3',5,4.2])
>>array(['3', '5', '4.2'], dtype='<U3')

2、数据中有整数型、浮点型和字符串,最终都转换成了字符串类型

指定数据类型,采用dtype参数:

a = np.array([3.14, 4, 2, 4], dtype='int64')
a
>>array([3, 4, 2, 4], dtype=int64)

上面例子就将浮点类型数据强制转换成了整数类型

查看ndarray数据类型的方法: 用dtype:

a.dtype
>>dtype('int64')

转换数据类型的方法: 用astype:

a.astype(np.float32)
>>array([3., 4., 2., 4.], dtype=float32)

Numpy 的矢量化(向量化)功能

如果想要将一个数组 a 的每个元素与长度相同的另外一个数组 b 中相应位置的元素相乘,在numpy中如何利用矢量化实现上述功能

a = [[1, 2, 3], [5, 7, 8], [4, 5, 6]]
b = [[6, 2, 1], [2, 3, 1], [4, 5, 6]]
a1 = np.array(a)
b1 = np.array(b)

a1*b1
>>array([[ 6,  4,  3],
       [10, 21,  8],
       [16, 25, 36]])

矢量化代码有很多优点,其中包括:

  • 矢量化代码更简洁易读
  • 更少的代码行通常意味着更少的错误
  • 该代码更接近地类似于标准数学符号(使得更容易,通常,以正确地编码数学构造)
  • 矢量化导致更多的“Pythonic”代码。如果没有向量化,我们的代码将会效率很低,难以读取for循环。

二、创建常用的数组

单位矩阵,全零矩阵,三角矩阵等常用的矩阵数组,在线性代数的辅助计算中有很多特殊的作用
下面我们来看一下如何创建这些矩阵数组。

#全部行都能输出
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

2.1 创建一个全0数组

参数说明:
shape 形状,要创建数组的形状
dtype 数组的类型

np.zeros(10) # float型
np.zeros(10, dtype="int32")
np.zeros((3, 3), dtype="int32") #二维数组

>>array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
array([[0, 0, 0],
       [0, 0, 0],
       [0, 0, 0]])
#三维数组
np.zeros((4,3,2),dtype='int')
#这里的4代表有4个二维平面构成的三维体
#3代表每一个二维元素里面都是由3个一维元素构成的
#2代表每一个一维元素里面都是由2个0维元素构成的

2.2 全1数组

数组中所有元素均为1

np.ones([4,3])
>>array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]])

2.3 单位矩阵

矩阵对角线元素为1,剩余元素均为0

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

#向上偏移一行
np.eye(5,k=1)
>>array([[0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 1.],
       [0., 0., 0., 0., 0.]])

#向下偏移一行
np.eye(5,k=-1)
>>array([[0., 0., 0., 0., 0.],
       [1., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.]])

2.4 对角矩阵

d = np.diag(np.array([1, 2, 3, 4]))
d
>>array([[1, 0, 0, 0],
       [0, 2, 0, 0],
       [0, 0, 3, 0],
       [0, 0, 0, 4]])

2.5 设定具体的值

np.full((3, 5),3.14 )#三行五列
>>array([[ 3.14,  3.14,  3.14,  3.14,  3.14],
       [ 3.14,  3.14,  3.14,  3.14,  3.14],
       [ 3.14,  3.14,  3.14,  3.14,  3.14]])

设置空值和无穷大

有一点要尤其注意的是: np.nan, np.inf 都是浮点类型
结合ndarray中的数据类型必须是相同的, 也就是说数组中如何有一个数据是空值,那么所有的数据都只能是浮点型.

np.nan#空(啥也没有)
np.inf#无穷大
type(np.inf)
>>float

2.6 随机数组

上面提到的都是有固定值的数组及矩阵,下面的是自动生生的随机数数组,也就是说数组的值不会固定不变,意味着每次运行结果都会不同

#生成1-10的三行六列的数组
np.random.randint(1, 10, (3, 6))
>>array([[5, 1, 8, 8, 9, 9],
       [7, 7, 9, 5, 6, 5],
       [6, 1, 5, 5, 5, 6]])
#生成0-1的随机数
a = np.random.rand(2, 3)       # uniform in [0, 1]
a
>>array([[0.05254766, 0.59756243, 0.99502083],
       [0.4723183 , 0.72458214, 0.85551448]])
#四舍五入到小数点后三位(利用round函数)
np.round(np.random.random((3,4)),3)
>>array([[0.147, 0.727, 0.522, 0.178],
       [0.53 , 0.207, 0.797, 0.162],
       [0.82 , 0.288, 0.032, 0.134]])
#生成5-12的随机序列
#先放大7倍,再向右偏移5个单位
7*np.random.random((3,4))+5
>>array([[11.46104262,  7.41313746,  8.1893867 ,  7.83397531],
       [ 7.89122632,  8.69092695, 11.22702728,  5.85397128],
       [ 9.9093688 , 10.82050394,  9.74349257, 10.05593118]])

2.6.1 正态分布随机数

正态分布是统计学中常用的一种概率分布

#标准正态分布(均值为0,方差为1)
np.random.rand(3,2)
>>array([[0.36129005, 0.82424353],
       [0.61575358, 0.52226236],
       [0.74051091, 0.11037443]])
#均值为4,标准差为2的普通正态分布
array = np.random.normal(4, 2, (10, 3))  # 均值, 标准差, 形状
array
>>array([[ 5.95973621,  7.19262672,  2.98362756],
       [ 4.78153143,  1.78440733,  5.8766825 ],
       [ 5.43184024,  3.23992211,  3.71794129],
       [ 5.20221566,  1.84128205,  1.94329058],
       [ 2.75472565,  2.58743767, -3.26293124],
       [ 4.50987806,  5.15885142,  1.11565559],
       [ 2.19926954,  3.24967032,  0.22541738],
       [ 3.37805791,  4.37907265,  2.40445887],
       [ 6.53946577,  5.14046091,  5.23462548],
       [ 1.0062933 ,  2.51757328,  4.7654928 ]])

2.6.2 其他分布

#卡方分布,自由度是5
np.random.chisquare(5,(3,4))
>>array([[ 5.01762679,  1.8848837 ,  3.11996202,  5.74481173],
       [ 6.63079251,  4.03316576,  3.16723971,  1.80446791],
       [11.0604356 , 10.64043017,  4.8995559 ,  7.71885382]])
#t分布,自由度3
np.random.standard_t(3,(3,4))
>>array([[-0.360586  ,  1.55431396,  1.06826751, -0.24576188],
       [-3.15302156, -2.55289713, -0.95298275,  0.11738487],
       [-1.78035877, -1.02519345,  0.09922377, -0.87289364]])
#f分布,分子自由度2,分母自由度3
np.random.f(2,3,(3,4))
>>array([[8.65117009e-01, 1.66171994e+00, 4.94743004e+00, 4.17935167e-01],
       [2.33295805e-01, 5.39910799e+00, 1.14388224e-01, 6.95415742e-01],
       [1.13709537e+00, 2.17429504e+00, 1.63103939e-02, 1.73043383e+01]])
#泊松分布
np.random.poisson(0.5,(3,4))
>>array([[0, 1, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 1]])
#二项分布
np.random.binomial(10,0.5,(3,4))
>>array([[2, 4, 5, 9],
       [9, 9, 3, 6],
       [5, 4, 7, 4]])

2.6.3 设置随机数种子

上面知道生成的随机数组具有很强的不确定性,每次结果都会不同,所谓随机数种子就是设置一个固定种子值,那么每次生成的随机数组都会是完全相同的,这个数值可任意设定。

# 设置随机数种子
np.random.seed(200)
c = np.random.randn(2, 3)
c
>>array([[-1.45094825,  1.91095313,  0.71187915],
       [-0.24773829,  0.36146623, -0.03294967]])

2.7 创建一个线性序列的数组

有以下两种方法:

arange([start,] stop[, step,])
如果只填一个stop参数,默认从0开始,步长为1

特点: 可以设置开始位置,终止位置和步长,但产生数字的数量不方便控制

#如果只填一个stop参数,默认从0开始,步长为1
np.arange(0, 20, 4)
>>array([ 0,  4,  8, 12, 16])

np.linspace(开始位置, 终止位置, 产生数量)

特点: 可以设置开始位置和终止位置以及产生数量,但不方便控制步长

np.linspace(1, 101, 49, dtype=int)
>>array([  1,   3,   5,   7,   9,  11,  13,  15,  17,  19,  21,  23,  26,
        28,  30,  32,  34,  36,  38,  40,  42,  44,  46,  48,  51,  53,
        55,  57,  59,  61,  63,  65,  67,  69,  71,  73,  76,  78,  80,
        82,  84,  86,  88,  90,  92,  94,  96,  98, 101])

三、 ndaray常用属性

  1. 查看数据形状
    x.shape
  2. 查看维度
    x.ndim
  3. 查看数组元素个数
    x.size

3.1 数组的索引和切片

3.1.1 单个元素索引

数组的单元素索引是人们期望的。它的工作原理与其他标准Python序列一样。它是从0开始的,并且接受负索引来从数组的结尾进行索引。

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

3.1.2 高维数组索引

与Python原生的列表、元组不同的是,Numpy数组支持多维数组的多维索引。
每一个逗号, 代表索引的一个维度

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

x2[第一个维度,第二个维度]
#从外往里看,第一个维度是3,7,1,第二个维度是3,5,2,4
x2[行,列]
x2[0]
x2[0, 0]
x2[1, 1]#第一行第一列
>>array([3, 5, 2, 4])
3
6

3.1.3 修改某一个元素值

利用索引来实现,直接赋值

x2[:2,:2] = 100
x2
>>array([[100, 100,   2,   4],
       [100, 100,   8,   8],
       [  1,   6,   7,   7]])

3.2 切片

可以使用切片和步长来截取不同长度的数组,使用方式与Python原生的对列表和元组的方式相同。
语法和之前学过的列表的切片是一样的
x[start:stop:step]

x2
>>array([[3, 5, 2, 4],
       [7, 6, 8, 8],
       [1, 6, 7, 7]])
#x2[第一维度,第二维度 ]
x2[:2:1, 0:2:1]
>>array([[3, 5],
       [7, 6]])
#获取第1列
x2[:, 1]  
>>array([5, 6, 6])

3.3 关于视图

关于数组切片有一点很重要也非常有用,那就是数组切片返回的是
数组数据的视图,而不是数值数据的副本。这一点也是 NumPy 数
组切片和 Python 列表切片的不同之处:在 Python 列表中,切片是
值的副本。例如此前示例中的那个二维数组:

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

x2_0 = x2[:2, :2]
x2_0
>>array([[3, 5],
       [7, 6]])

x2_0[0, 0] = 8888
x2_0
>>array([[8888,    5],
       [   7,    6]])

x2
>>array([[8888,    5],
       [   7,    6]])

也就是说修改某个元素值不仅会将切片内的元素修改,原来的数组也会改变。
若想不改变原数组就要用到创建副本。

改为创建副本

也可以通过.copy()方法创建一个副本,这样就不会对原数组进行改动。

x2_1 = x2[:2, :2].copy()#副本(深复制)
x2_1
>>array([[4, 3],
       [8, 4]])

x2_1[0, 0] = 8888
x2_1
>>array([[8888,    3],
       [   8,    4]])
       
x2
>>array([[4, 3, 4, 4],
       [8, 4, 3, 7],
       [5, 5, 0, 1]])

3.4 数组的变形

数组的变形也是一类非常有用的操作。
数组变形最灵活的实现方式是通过 reshape() 函数来实现。例如,如果你希望将数字 1~9 放入一个3×3 的矩阵中,可以采用如下方法:

3.4.1 reshape改变数组的形状

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

x2.reshape((2, 6))
>>array([[3, 5, 2, 4, 7, 6],
       [8, 8, 1, 6, 7, 7]])

3.4.2 拉伸成一维数组(数组的平铺)

x2
>>array([[3, 5, 2, 4],
       [7, 6, 8, 8],
       [1, 6, 7, 7]])
x2.ravel()
>>array([3, 5, 2, 4, 7, 6, 8, 8, 1, 6, 7, 7])

3.4.3 转置

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

x2.T
>>array([[3, 7, 1],
       [5, 6, 6],
       [2, 8, 7],
       [4, 8, 7]])

无论是ravel、reshape、T,它们都不会更改原有的数组形状,都是返回一个新的数组。

3.5 数组的拼接

拼接或连接 NumPy 中的两个数组主要由np.concatenate实现

x = np.array([34, 43, 12])
y = np.array([343, 34, 676])
#拼接(一维的拼接)
np.concatenate((x, y))
>>array([ 34,  43,  12, 343,  34, 676])
x2
>>array([[1, 2, 3],
       [3, 2, 1],
       [0, 0, 0]])       
x3
>>array([[1, 2, 3],
       [3, 2, 1],
       [0, 0, 0]])
#二维数组的横向拼接
np.concatenate([x2, x3], axis=1)
>>array([[1, 2, 3, 1, 2, 3],
       [3, 2, 1, 3, 2, 1],
       [0, 0, 0, 0, 0, 0]])

axis是轴的意思,axis=0,-2沿着竖方向拼接,axis=1,-1沿着横方向拼接

3.6 数据的分裂

将一个数组分成几个较小的数组

既然可以将多个数组进行对堆叠,自然也可以将一个数组拆分成多个小数组。

使用split,可以指定均匀切割成几份,也可以指定沿着哪个位置进行切割, 还可以指定沿着哪个轴进行切割.

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

#sectins:均匀切分成几份
#indices:手动指定切分点
a
>>array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])
np.split(a,2,axis=0)#在索引值为2前面切割
>>[array([[ 0,  1,  2,  3,  4,  5],
        [ 6,  7,  8,  9, 10, 11]]), array([[12, 13, 14, 15, 16, 17],
        [18, 19, 20, 21, 22, 23]])]

#不均匀切分(在指定列前面索引)
np.split(a, [1, 3])
>>[array([[0, 1, 2, 3, 4, 5]]), array([[ 6,  7,  8,  9, 10, 11],
        [12, 13, 14, 15, 16, 17]]), array([[18, 19, 20, 21, 22, 23]])]

3.7 广播机制

3.7.1 什么是广播

我们都知道,Numpy中的基本运算(加、减、乘、除、求余等等)都是元素级别的,但是这仅仅局限于两个数组的形状相同的情况下。
可是大家又会发现,如果让一个数组加1的话,结果是整个数组的结果都会加1,这是什么情况呢?

广播broadcast:当把一个低维和一个高维数据进行计算时,会自动将低维数据拉伸到和高维相同的形状,然后进行对应元素位置操作
其实这就是广播机制:Numpy 可以转换这些形状不同的数组,使它们都具有相同的大小,然后再对它们进行运算。给出广播示意图:

广播

x
>>array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
x + 1
>>array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])

3.7.2 广播示例

a
>>array([ 0, 10, 20, 30])
b
>>array([[0],
       [1],
       [2]])
a + b
>>array([[ 0, 10, 20, 30],
       [ 1, 11, 21, 31],
       [ 2, 12, 22, 32]])

四、Numpy运算

Numpy 中数组上的算术运算符使用元素级别。最后的结果使用新的一个数组来返回。

4.1 基本运算操作

a
b
>>array([20, 30, 40, 50])
array([0, 1, 2, 3])
c = a-b
c
>>array([20, 29, 38, 47])
b**2
>>array([0, 1, 4, 9])

需要注意的是,乘法运算符*的运算在NumPy数组中也是元素级别的(这与许多矩阵语言不同)。如果想要执行矩阵乘积,可以使用dot函数:

A
B
>>array([[1, 1],
       [0, 1]])
array([[2, 0],
       [3, 4]])
A.dot(B)
>>array([[5, 4],
       [3, 4]])
B.dot(A)
>>array([[2, 2],
       [3, 7]])

np.dot(A, B)
>>array([[5, 4],
       [3, 4]])
np.dot(B,A)
>>array([[2, 2],
       [3, 7]])

A*B 元素乘积(elementwise product)
A.dot(B) 矩阵相乘(matrix product)(A左乘B)
np.dot(A, B) 矩阵相乘的另一种方式(another matrix product)(函数形式)

4.2 常用函数

数学运算函数
add(x1,x2 [,out])按元素添加参数,等效于 x1 + x2
subtract(x1,x2 [,out])按元素方式减去参数,等效于x1 - x2
multiply(x1,x2 [,out])逐元素乘法参数,等效于x1 * x2
divide(x1,x2 [,out])逐元素除以参数,等效于x1 / x2
exp(x [,out])计算输入数组中所有元素的指数。
exp2(x [,out])对于输入数组中的所有p,计算2 * p*。
log(x [,out])自然对数,逐元素。
log2(x [,out])x的基础2对数。
log10(x [,out])以元素为单位返回输入数组的基数10的对数。
expm1(x [,out])对数组中的所有元素计算exp(x) - 1
log1p(x [,out])返回一个加自然对数的输入数组,元素。
sqrt(x [,out])按元素方式返回数组的正平方根。
square(x [,out])返回输入的元素平方。
sin(x [,out])三角正弦。
cos(x [,out])元素余弦。
tan(x [,out])逐元素计算切线。

4.3 规约函数(用于统计数据的函数)

下面所有的函数都支持axis来指定不同的轴,用法都是类似的。

函数名称函数功能
ndarray.sum([axis,dtype,out,keepdims])返回给定轴上的数组元素的总和。
ndarray.cumsum([axis,dtype,out])返回沿给定轴的元素的累积和。
ndarray.mean([axis,dtype,out,keepdims])返回沿给定轴的数组元素的平均值。
ndarray.var([axis,dtype,out,ddof,keepdims])沿给定轴返回数组元素的方差。
ndarray.std([axis,dtype,out,ddof,keepdims])返回给定轴上的数组元素的标准偏差。
ndarray.argmax([axis,out])沿着给定轴的最大值的返回索引。
ndarray.min([axis,out,keepdims])沿给定轴返回最小值。
ndarray.argmin([axis,out])沿着给定轴的最小值的返回索引。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值