数据分析的核心库有Numpy、Matplotlib和pandas
这篇文章首先介绍Numpy库数值计算基础
目录
0 前言
首先需要安装jupyter notebook,本篇实验的内容主要采用jupyter notebook运行,安装步骤见之前的文章,传送带:【软件安装】手把手教你在Windows上安装anaconda和jupyter-CSDN博客
1 什么是NumPy
NumPy 是一个用于科学计算的Python库。它的全称是 "Numerical Python"。简单来说,NumPy 不仅提供了一种非常方便和高效的方式来存储和处理大规模的数组和矩阵运算。NumPy的数据容易能够保存任意类型的数据,使得NumPy可以无缝并快速的整合各种数据。
2 Numpy数值计算基础
python提供了一个array模块,array和list不同,array直接保存数值,和C语言的一维数组比较类似。但由于python的array模块不支持多维,也没有各种运算函数,因此不适合做数值运算。
所以numpy弥补了python不支持多维等不足之处,它提供了一种存储单一数据类型的多维数组ndarray。
2.1 创建数组对象
numpy提供了两种基本对象:
- ndarray(N-dimensional Array):存储单一数据类型的多维数组(下边统称数组)
- ufunc(Universal Funtion):对数组进行处理的函数
2.1.1 数组的属性
·要想去理解数组,需要知道数组的属性,介绍如下:
- ndim:返回int型,表示数组维数
- shape:返回tuple型(元组),表示数据的尺寸。例如n行m列的矩阵,形状为(n,m)
- size:返回int型,表示数组的元素总数,形状的乘积,如上例,则为n*m
- dtype:返回data-type,表示数组中元素的类型
- itemsize:返回int型,表示数组每个元素的大小。例:一个元素类型为float64的数组的itemsize属性值为8(float64占用64bits,每个字节长度为8,所以64/8,占用8个字节)
2.1.2 array函数创建数组
numpy中的array函数可以创建一维或多维数组。语法如下:
numpy.array(object,dtype=None,copy=True,order='K',subok=False,ndmin=0)
参数解释如下:
- subok: 可选参数,类型为bool值,默认为False。为True时,使用object的内部数据类型; 为False 时使用object数组的数据类型
- ndmin:接收int。指定生成数组应该具有的最小维数。默认为None
- copy: 可选参数,当数据源是ndarray 时表示数组能否被复制,默认是True
- order: 可选参数,以哪种内存布局创建数组,有3个可选值,分别是C(行序列)/F(列序列)/A(默认)
打开jupyter notebook,我们通过例子来说明:
1. 创建一维数组arr1
import numpy as np
arr1 = np.array([1,2,3,4])
print('创建的数组是:',arr1)
输出为:
2. 创建二维数组arr2
arr2 = np.array([[1,2,3,4],[2,3,4,5],[3,4,5,6]])
print('创建的数组是:\n',arr2)
注意:这里是[[...],[...],[...]]的形式
输出为:
3. 查看数组arr2的类型
print('数组类型是:',arr2.dtype)
输出为:
4. 查看数组arr2的结构
print('数组结构是:',arr2.shape)
输出为:
还可以通过修改数组的shape属性,在保持数组元素个数不变的情况下改变数组每个轴的长度。例如将上述(3,4)变为(4,3),但并不是对数组进行转置,而是改变每个轴的大小,数组元素不变。如下:
arr2.shape = 4,3
print('重新设置shape后的arr2:\n',arr2)
输出为:
5. 查看数组arr2的元素个数
print('数组元素个数:',arr2.size)
输出为:
6. 查看数组arr2中每个元素的大小
print('数组每个元素的大小:',arr2.itemsize)
输出为:
2.1.3 arange函数创建数组
上述用array函数创建数组,是先创建了一个python序列,然后将其转换为数组,这样效率不高。因此有其他函数来创建数组。首先是arange函数。
函数形式:numpy.arange(start, stop, step, dtype = None)
- start:开始位置,数字,可选项,默认起始值为0
- stop:停止位置,数字
- step:步长,数字,可选项, 默认步长为1,如果指定了step,则必须给出start。
- dtype:输出数组的类型。 如果未给出dtype,则从其他输入参数推断数据类型。
创建一个从0到1,步长为0.1的数组,如下所示:
print('使用arange函数创建的数组为:\n',np.arange(0,1,0.1))
输出为:
2.1.4 linspace函数创建数组
该函数是通过指定开始值、终值和元素个数来创建一维数组,它们的间隔是均匀的。
函数形式:np.arange(start,stop,num,endpoint,dtype)
- start:起始点。如果设置为0,则结果的第一个数为0,必填项
- stop:终止点。通常为结果的最后一个值。必填项
- num:共有多少个元素。默认为50,可选项
- endpoint:决定终止值(stop参数指定)是否被包含在结果数组中。如果 endpoint = True, 结果中包括终止值,反之不包括。默认为True。可选项
- dtype:决定输出数组的数据类型。如果不指定,python基于其他参数值推断数据类型。
例如:
print('使用linspace函数创建的数组为:',np.linspace(0,100,5))
输出为:
再如:
print('使用linspace函数创建的数组为:',np.linspace(0,100,11))
输出为:
2.1.5 logspace函数创建数组
与linspace类似,它创建的是在对数尺度上生成等间距的数值来创建数组。
函数形式:numpy.logspace(start, stop, num, endpoint, base, dtype, axis)
- start:序列的起始值,作为基数的幂给出,例如
,start就是0,假如
,start就是0
- stop:序列的结束值,同上
- num:生成的样本数,默认为50
- endpoint:如果为True,包含终止值。否则,它不包括在内。默认为True
- base:对数的底数,默认为10
- dtype:输出数组的类型。如果未给出,则从其他输入参数推断数据类型
- axis:在结果数组中放置样本的轴。0表示沿着第一个轴放置,1表示沿着第二个轴,依此类推。默认为0。
例如:
print('使用logspace函数创建的数组为:',np.logspace(0,2,20))
输出为:
2.1.6 zeros函数创建数组
zeros函数用来创建值全部为0的数组,即创建的数组值全部填充为0。
函数形式:numpy.zeros(shape, dtype, order)
- shape:数组的形状,可以是一个整数或一个表示形状的元组。
- dtype:数组的数据类型,可选项,默认为float64。
- order:数组元素在内存中的排列顺序,可选项,可以是’C’(按行排列)或’F’(按列排列)。
例如:
print('使用zeros函数创建的数组为:\n',np.zeros((2,3)))
输出为:
2.1.7 eye函数创建数组
eye函数用来生成主对角线上的元素为1,其他元素为0的数组,类似单位矩阵
函数形式:numpy.eye(N,M, k, dtype,order)
- N:int型,行数,如果不指定M,则默认为N=M
- M:int型,列数,可选项
- k:int型,可选项,默认情况下输出的是对角线全“1”,其余全“0”的方阵,如果k为正整数,则在右上方第k条对角线全“1”其余全“0”,k为负整数则在左下方第k条对角线全“1”其余全“0”。
- order:{‘C’,‘F’},可选项,也就是输出的数组的形式是按照C语言的行优先’C’,还是按照Fortran形式的列优先‘F’存储在内存中
例1:输出一个3*3的单位矩阵
print('使用eye函数创建的数组为:\n',np.eye(3))
输出:
例2:输出5*5,k为2(对角线沿着右上移动2)的矩阵
print('使用eye函数创建的数组为:\n',np.eye(5,5,2))
输出:
2.1.8 diag函数创建数组
diag函数创建类似对角的数组,即除对角线以外的其他元素都为0,对角线元素可以是0或其他值。
函数形式:numpy.diag(v,k)
- v:如果v是2D数组,返回k位置的对角线。如果v是1D数组,返回一个v作为k位置对角线的2维数组。
- k:对角线的位置,大于零位于对角线上面,小于零则在下面。
例1:
print('使用diag函数创建的数组为:\n',np.diag([1,2,3,4]))
输出:
例2:
print('使用diag函数创建的数组为:\n',np.diag([1,2,3,4],1))
输出为:
2.1.9 ones函数创建数组
ones函数用来创建元素全部为1的数组,即创建的数组全部填充为1。
函数形式:numpy.diag(shape, dtype=None, order='C')
- shape:指定输出数组的形状,可以是一个整数或整数元组。例如,shape(3, )将创建一个长度为3的一维数组,shape(2,3)将创建一个2行3列的二维数组。
- dtype:可选项,用于指定数组中元素的数据类型。如果未指定,则默认为float64
- order:指定数组在内存中的存储顺序,通常为’C’(按行存储)或’F’(按列存储)。大多数情况下,不需要修改此参数。
例1:
print('使用ones函数创建的数组为:\n',np.ones((5,3)))
输出:
例2:
print('使用ones函数创建的数组为:\n',np.ones((5,)))
输出:
2.2 数据类型转换
numpy的基本数据类型及其取值范围如下:
类型 | 描述 |
bool | 一位存储的布尔类型(True或False) |
inti | 由所在平台决定其精度的整数(一般为int32或int64) |
int8 | 整数,-128——127 |
int16 | 整数,-32768——32767 |
int32 | 整数, |
int64 | 整数, |
uint8 | 无符号整数,0——255 |
uint16 | 无符号整数,0——65535 |
uint32 | 无符号整数,0——2^(32) -1 |
uint64 | 无符号整数,0——2^(64) -1 |
float16 | 半精度浮点数(16位),其中一位表示正负号,5位表示指数,用10位表示尾数 |
float32 | 单精度浮点数(32位),其中一位表示正负号,8位表示指数,用23位表示尾数 |
float64(默认为float) | 双精度浮点数(64位),其中一位表示正负号,11位表示指数,用52位表示尾数 |
complex64 | 复数,分别用32位浮点数表示实部和虚部 |
complex128(默认为complex) | 复数,分别用64位浮点数表示实部和虚部 |
每一种数据类型均有其对应的转换函数。如下
整型转浮点型:
print('转换结果为',np.float64(66))
输出为:
浮点型转整型:
print('转换结果为',np.int8(66.6))
输出为:
注意:numpy.int函数不能直接四舍五入,它主要用于将浮点数或其他类型的数据转换为整数类型,只取整数部分。如果想四舍五入,可以用numpy.round函数。如下:
print('转换结果为',np.round(66.6))
输出为:
整型转换为布尔型:
注意:numpy版本1.20之后用np.bool_,如果是版本1.20之前用np.bool
print('转换结果为',np.bool_(66))
输出:
print('转换结果为',np.bool_(0))
输出:
布尔型转换位浮点型
注意:numpy版本1.20之后用np.float_,如果是版本1.20之前用np.float,这个版本问题目前仅在布尔转换的时候用
print('转换结果为',np.float_(True))
输出为:
print('转换结果为',np.float_(False))
输出为:
2.3 小案例
创建一个存储餐饮企业库存信息的数据类型
- 商品名称:用一个能存储40个字符的字符串记录
- 商品库存数量:用一个64位的整数记录
- 商品的价格:用一个64位的单精度浮单数记录
创建数据类型:
df = np.dtype([("name",np.str_,40),("numitems",np.int64),("price",np.float64)])
print('数据类型为:',df)
输出为:
- '<U40'表示:长度不超过40个Unicode字符
- '<i8'表示:整型数占用8个字节
- '<f8'表示:浮点数占用8个字节
查看数据类型:
下边两种方式都可
print('数据类型为:',df["name"])
输出为:
print('数据类型为:',np.dtype(df["name"]))
输出为:
自定义数组数据
用array创建数组时,数组的数据类型默认是浮点型。自定义数组数据,则可以预先指定数据类型。
如下,dtype=df就是预先指定数据类型。上述说“name”是字符串,“numitems”是整型,“price”是浮点型。对应下边的数据:“tomatoes”,42,4.14
itemz = np.array([("tomatoes",42,4.14),("cabbages",13,1.72)],dtype=df)
print('自定义数据为:',itemz)
输出为:
2.4 生成随机数
numpy有生成随机数的功能,与随机数相关的函数都在random模块中,以下是一些常用的随机数生成方法。
2.4.1 生成一般随机数
random模块里的random函数,返回随机生成的一个浮点数,范围在[0,1)之间。random(),括号里如果不填的话,默认为生成一个范围在[0,1)之间的随机数,填数字就代表生成n个范围在[0,1)之间的浮点数。
例1
输出:
例2:
print('生成的随机数组为:',np.random.random())
输出为:
2.4.2 生成均匀分布的随机数
rand函数可以生成服从均匀分布的随机数,
rand函数形式:numpy.random.rand(d0,d1,…,dn),rand函数根据给定维度生成[0,1)之间的数据,包含0,不包含1。
不同个数参数输出详解:
例1:一个参数时
print('生成的随机数组为:\n',np.random.rand(2))
输出了一个一行两列的一维数组:
例2:两个参数时
print('生成的随机数组为:\n',np.random.rand(2,3))
输出了一个两行三列的二维数组:
例3:三个参数时
print('生成的随机数组为:\n',np.random.rand(2,3,4))
输出2个小矩阵,每个小矩阵都是3行4列,并且这2个小矩阵组成一个大矩阵 ,如下:
例4:四个参数时
print('生成的随机数组为:\n',np.random.rand(2,3,4,5))
输出一个大矩阵里包含2个矩阵,然后每个矩阵又有3个矩阵,这三个矩阵分别是4行5列的矩阵,如下所示:
以此类推......
2.4.3 生成正态分布的随机数
randn函数可以生成服从正态分布的随机数,函数形式如下:
numpy.random.randn(d0,d1,…,dn)
这里的参数表示和生成均匀分布rand的一样。不具体展示每个参数了。
例:
print('生成的随机数组为:\n',np.random.randn(3,4))
输出:
2.4.4 生成给定上下限范围的随机数
randint函数可以生成给定上下限范围的随机数,函数形式如下:
numpy.random.randint(low,high=None,size=None,dtype='1')
其中 ,low为最小值,high为最大值,size为数组的shape,如下所示,生成一个最小值不低于2,最大值不高于10的2行5列的数组
print('生成的随机数组为:',np.random.randint(2,10,size=[2,5]))
输出为:
2.4.5 random模块常用的随机数生成函数
函数 | 说明 |
seed | 确定随机数生成器的种子 |
permutation | 返回一个序列的随机排列或返回一个随机排列的范围 |
shuffle | 对一个序列进行随机排序 |
binonial | 产生二项分布随机数 |
normal | 产生正态(高斯)分步的随机数 |
beta | 产生beta分布的随机数 |
chisquare | 产生卡方分布的随机数 |
gamma | 产生gamma分布的随机数 |
uniform | 产生[0,1]中均匀分布的随机数 |
2.5 索引访问数组
2.5.1 一维数组的索引
一维数组的索引方法与python种的list索引方法一致。
例1 用整数作为下标获取数组中的某个元素
arr = np.arange(10)
print('数组为:',arr)
print('索引结果为:',arr[5])
输出:
例2 用范围作为下标获取数组的一个切片,包括arr[3],不包括arr[5]
print('索引结果为:',arr[3:5])
输出:
例3 省略开始下标,表示从arr[0]开始
print('索引结果为:',arr[:5])
输出:
例4 下标使用负数,-1表示从数组最后往前数的第一个元素
print('索引结果为:',arr[-1])
输出:
例5 用下标修改元素值
arr[2:4]=100,101
print('数组为:',arr)
输出:
例6 范围中的第三个参数表示步长,2表示隔一个元素取一个元素
print('索引结果为:',arr[1:-1:2])
输出:
例7 步长为负数时,开始下标必须大于结束下标
print('索引结果为:',arr[5:1:-2])
输出:
2.5.2 多维数组的索引
多维数组每个维度都有一个索引,各个维度的索引之间用逗号隔开。
arr2 = np.array([[1,2,3,4,5],[4,5,6,7,8],[7,8,9,10,11]])
print('创建的二维数组为:\n',arr2)
输出:
例1 索引第0行中第3和4列的元素
print('索引结果为:',arr2[0,3:5])
输出:
例2 索引第2和3行中第3—5列的元素
print('索引结果为:\n',arr2[1:,2:])
输出:
- '1:' 代表第一行之后的所有行
- '2:' 代表第二列之后的所有列
例3 索引第2列的元素
print('索引结果为:',arr2[:,2])
输出:
例4 从两个序列的对应位置取出两个整数来组成下标:arr2[0,1],arr2[1,2],arr2[2,3]
print('索引结果为:',arr2[(0,1,2),(1,2,3)])
(0,1,2)代表第0,1,2行
(1,2,3)代表第1,2,3列
输出:
例5 索引第2,3行中第0,2,3列的元素
print('索引结果为:',arr2[1:,(0,2,3)])
输出:
例6 mask是一个布尔数组,它索引第1,3行中第2列的元素
mask = np.array([1,0,1],dtype = np.bool_)
print('索引结果为:',arr2[mask,2])
- 上边[1,0,1]代表第1,3行,因为是布尔类型的,即[1,2,3,4,5][7,8,9,10,11]
- arr2[mask,2]代表第3列(因为索引是从0开始的),所以是[3,9]
输出: