Python编程数据分析篇之Numpy基本操作
文章目录
Numpy介绍与安装
可参考官网:
https://numpy.org/devdocs/user/quickstart.html
为什么会有Numpy?
Python自带的列表函数在处理大量数据时由于其自身保存数据的机制问题(既要保存数据的值,又要保存数据的指针),导致占用内存较大,效率较低;array模块只需要保存数据的值即可,所以效率比较高,但是它只能处理一维数组。统合上面两种情况,Numpy随即诞生,它只需要保存数据的值即可,而且能够处理多维数组,因此处理数据的效率很高。
Numpy是什么?
Numpy(Numerical Python)是目前Python数值计算中最为重要的基础包。大多数计算包都提供了Numpy的科学函数功能,将Numpy的数组对象作为数据交换的通用语。
Numpy的特定
- 提供高效多维数组
- 提供了基于数组的便捷算数操作以及广播机制
- 对数据进行快速的矩阵计算
- 对硬盘中的数组数据进行读写操作
Numpy安装
直接在dos命令行中输入pip install numpy回车即可
创建N维数组对象
生成数组最简单的方式就是使用array函数。array函数接收任意序列型的对象,生成一个新的包含传递数据的Numpy数组。
- numpy.array(object)
代码如下(示例):
import numpy as np
np.array([1,2,3,4])
- numpy.arange([start,] stop[,step])
注意:
numpy数组的类型为ndarray,ndarray数组是一个通用的多维同类数据容器,意味着数据里面的每一个元素均为相同类型。
数组的数据类型
Numpy数据类型
类型 | 类型代码 | 描述 |
---|---|---|
int8,uint8 | i1,u1 | 有符号和无符号的8数位整数 |
int16,uint16 | i2,u2 | 有符号和无符号的16数位整数 |
int32,uint32 | i4,u4 | 有符号和无符号的32数位整数 |
int64,uint8 | i8,u8 | 有符号和无符号的64数位整数 |
float16 | f2 | 半精度浮点数 |
float32 | f4 | 标准单精度浮点数 |
float64 | f8 | 标准双精度浮点数 |
bool | ? | 布尔值,存储True或False |
string_ | S | ASCII字符串类型,eg:'S10‘ |
unicode_ | U | Unicode类型,eg:‘U10’ |
查看数组数据类型
arr.dtype
指定数组的数据类型
- 创建数组时指定数组的数据类型
np.array([1,2,3,4],dtype='U')
- 在已创建数组中重新指定数据类型
arr.astype
数组形状
-
arr.ndim
查看数组的维度,返回值为整数 -
arr.shape
-
查看数组的形状,返回值为元组
N维数组对象
一维
0轴代表列
二维
- 0轴代表行
- 1轴代表列
代码如下(示例):
import numpy as np
np.array([[1,2,3],[4,5,6]])
np.array([[1,2,3],[4,5]]) # 注意: 不对等的则是一维,把子列表当成独立的列表对象
三维
- 0轴代表块
- 1轴代表行
- 2轴代表列
代码如下(示例):
import numpy as np
np.array([
[[0,1,2],[3,4,5]],
[[7,8,9],[6,7,8]]
])
重塑数组
一维转多维
代码如下(示例):
import numpy as np
arr = np.arrange(6) # 一维
arr.reshape(3,2) # 二维 reshape(shape,order='C') 默认以行方向进行分配
arr.reshape(3,2,order='F') # 以列方向进行分配
arr.reshape(2,-1) # 形状维度可以有一个值为-1,表示维度自动通过数据进行判断
np.arange(24).reshape(2,3,-1) # 三维
多维转一维
代码如下(示例):
import numpy as np
arr = np.arange(24).reshape(4,6) # 二维
arr.reshape(arr.shape[0]*arr.shape[1]) # 一维
arr.reshape(-1) # 一维
- arr.flatten() 扁平化
代码如下(示例):
import numpy as np
arr = np.arange(24).reshape(4,6) # 二维
arr.flatten() # 一维
- arr.ravel() 分散化
import numpy as np
arr = np.arange(24).reshape(4,6) # 二维
arr.ravel() # 一维
数组转置与换轴
- arr.transepose() # 转置
- arr.T # 转置
- arr.swapaxes() # 换轴
代码如下(示例):
import numpy as np
arr = np.arange(24).reshape(4,6) # 二维
arr.transepose()
arr.T
arr.swapaxes(1,0) # 0,1轴交换
创建数组的其它函数
函数名 | 描述 |
---|---|
array | 将输入数据转换为ndarray数组,自动推断数据类型,默认复制所有数据 |
asarray | 将输入数据转换为ndarray数组,输入数据是非ndarray将复制全部数据,但输入数据已经是ndarray则不再复制 |
arange | python内建函数range的数组版,返回一个数组 |
zeros | 根据给定形状和数据类型生成全0数组 |
ones | 根据给定形状和数据类型生成全1数组 |
empty | 根据给定形状和数据类型生成一个没有初始化数值的空数组 |
full | 根据给定形状和数据类型生成指定数值的数组 |
数组的拷贝
理解
计算机内存分为栈区和堆区,栈区是指内存中的内存,响应速度快,容量小;堆区相当于内存中的硬盘,相对来说响应速度要慢一些,但容量大。栈区中存储的数据指针,堆区中存储对应数据,通过指针来获取数据。
不拷贝
代码如下(示例):
import numpy as np
arr = np.arange(5)
arr2 = arr # arr2与arr指向了同一个内存地址(数据指针)
浅拷贝
浅拷贝是在栈区重新开辟一份内存空间指向堆区。由此可知,由于浅拷贝只是改变栈区的数据而没有改变堆区的数据,所以新拷贝的数据和原数据只是数据指针不一样(id不同),而堆区的数据还是同一份。
代码如下(示例):
import numpy as np
arr = np.arange(5)
arr2 = arr.view() # 浅拷贝
arr2 is arr # 返回False,但是arr2的值与arr完全相同,修改一个,另一个也相应改变
深拷贝
深拷贝是在栈区和堆区都重新开辟了相应的内存空间,新的栈区指向新的堆区,即新的数据指针指向新的数据。新拷贝数据和原数据是完全不同的两份数据,没有任何关系。
代码如下(示例):
import numpy as np
arr = np.arange(5)
arr2 = arr.copy() # 深拷贝
Numpy数组算数
数组之所以重要是因为它允许我们进行批量操作数据并且没有任何for循环,也被称作向量化。
数组与标量的算数操作
数组与标量的算数操作会把计算参数传递给数组的每一个元素。
import numpy as np
arr = np.arange(6).reshape(2,3)
arr + 1
两个等尺寸数组的算数操作
两个等尺寸数组的算数操作实际上是对应位置上的元素操作。
import numpy as np
arr = np.arange(6).reshape(2,3)
arr + arr
arr / arr
arr - arr
arr > arr # 对应位置进行比较,返回bool值
广播机制
广播机制规则:如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符且其中一方的长度为1,则认为它们是广播兼容的。广播会在缺失和(或)长度为1的维度上进行。
与列数相同并且只有一行的数组进行运算
- 在其丢失的轴上进行,也就是0轴广播
与行数相同并且只有一列的数组进行运算
- 在其长度为1的轴上进行,也就是1轴广播
注意:在numpy中维度完全不一致时无法进行广播
数组拼接
- np.vstack() 垂直拼接
- np.hstack() 水平拼接
注意: - 水平拼接需要对应行数一致,垂直拼接需要对应列数一致
- 传入的参数为tuple
- 维度不一致时无法进行拼接
切片
一维索引与切片
同python中的内建数据类型list一致
注意:
- 索引默认从0开始
- 切片左闭右开
- 步长为整数
二维索引与切片
- 二维数组递归方式获取
- 二维数组逗号分隔获取(行,列),即用逗号区分维度
取单行 arr[x1,:]
取连续行 arr[x1:x2,:]
取分开行 arr[[x1,x2],:]
取子矩阵 arr[[x1:x2,y1:y2]]
取点 arr[[x1,x2],[y1,y2]]
布尔索引
numpy中的逻辑运算符与python中的逻辑运算符有所不同,不是and 和 or,而是 & 和 |,注意运算符的优先级
- np.where(condition, [x,y])
np调用,条件成立时选择x,否则选择y - arr.clip()
数组调用
代码如下(示例):
import numpy as np
arr = np.arange(16).reshape(4,4)
np.where(arr<10, [0, 10])
arr.clip(5,10) # 小于等于5的替换为5,大于10的替换为10
Numpy操作本地数据
写入本地数据
- np.savetxt(fname)
fname 文件路径
dtype 数据类型
delimiter 分隔符
fmt=’%.18e’ 写入文件的格式,例如:%d,%.2f,%.18e
converters 对数据预处理。比如{0:func}第0列进行func函数预处理
header 指定为表头
代码如下(示例):
import numpy as np
scores = np.random.randint(0,100,size=(40,2)) # 期中与期末考试成绩
np.savetxt('scores.csv',scores,delimiter=',',fmt='%d',header='期中,期末',comments='')
读取本地数据
- np.loadtxt(fname) # 加载本地数据
NaN与inf
nan与inf介绍
- nan:not a number,表示不是一个数字,属于浮点型
- inf:np.inf表示正无穷,-np.inf表示负无穷,属于浮点型
NaN特点
- nan与inf都是浮点型
代码如下(示例):
import numpy as np
a = np.nan
a
type(a) # float
b = np.inf
b
type(b) # float
- 两个nan是不相等的
该特性可以用来判断nan的个数
np.count_nonzero()计算非零个数
np.isnan()判断数组元素是否为NaN,返回值为bool
np.nan == np.nan # False
import numpy as np
a = np.arange(16).reshape(4,4).astype('float')
a[1:3,2:4] = np.nan
# 判断a中nan的个数
# 法一
len(a[a != a])
# 法二
np.count_nonzero(a!=a)
# 法三
np.count_nonzero(np.isnan(a))
- nan与任何数值计算都是nan
np.array([2,np.nan,3])+100 # array([102,np.nan,103])
正因为np.nan与任何数值计算都是nan,所以在运算时会带来较大的误差。一般我们都会将其处理掉。
如何处理nan
直接删除缺失值所在行,但是当数据量较小时,这样处理会影响整体的数据,产生较大的误差。更优雅的做法是当求和时,将np.nan处理为0;当求均值时,将np.nan处理为非nan的均值。
- 删除nan所在的行
import numpy as np
arr = np.arange(9).reshape(3,3)
arr[(0,1),(1,2)] = np.nan
# np.where(condition) 只有condition返回满足条件的元素 (所在行,所在列)
row_index = np.where(np.isnan(arr))[0]
# 将含有nan的行删除
"""
np.delete??
- arr 输入的数组
- obj 要移除的索引
- axis 表示要移除的轴(行或列)
"""
del_arr = np.delete(b,row_index,axis=0)
random模块
np.random为我们提供了许多获取随机数的函数。其实是python内置random模块进行的封装。
参考网址:
https://numpy.org/doc/stable/reference/random/legacy.html#numpy.random.RandomState
np.random.seed()
用于指定随机数生成时所用算法开始的整数值,如果使用相同的seed()值,则每次生成的随机数都相同;如果不设置这个值,则系统根据时间来自己选择这个值,此时每次生成的随机数因时间差异二部同。一般没有特殊要求不用设置。
代码如下(示例):
import numpy as np
np.random.seed(1)
print(np.random.seed())
np.random.rand()
生成一个值为[0,1)之间的数组,形状由参数指定,如果没有参数,那么将返回一个随机数。
代码如下(示例):
import numpy as np
np.random.rand() # 生成0-1之间的随机数
np.random.seed(1) # 加上seed后,rand每次生成的值都相同,只对最近的rand起作用
np.random.rand()
np.random.randn()
生成均值μ为0,标准差σ为1的标准正态分布的值。
代码如下(示例):
import numpy as np
np.random.randn(2,3) # 生成一个2行3列的数组,数组中的值都满足标准正态分布
np.random.randint()
生成指定范围内的随机数,并且可以通过size参数指定维度。
代码如下(示例):
import numpy as np
np.random.randint(1,10,size=(4,4)) # 注意:与python内置randint有区别,范围是左闭右开[1,10)
np.random.choice()
从一个列表或者数组中,随机进行采样,或者是从指定的区间中进行采样,采样个数可以通过参数指定。
代码如下(示例):
import numpy as np
data = np.arange(5)
np.random.randchoice(data,size=(4,4))
np.random.shuffle()
把原来数组元素的位置打乱
代码如下(示例):
import numpy as np
a = np.arange(10)
np.random.shuffle(a) # 没有返回值,改变的是原数组
np.random.uniform()
生成服从均匀分布的数据
代码如下(示例):
import numpy as np
np.random.uniform(-10,10,size=(3,5))
常用函数
聚合函数
方法 | 描述 |
---|---|
sum | 沿着轴向计算所有元素的累和 ,0长度的数组,累和为0 |
mean | 数学平均 ,0长度的数组,均值为NaN |
max,min | 求最值 |
argmax,argmin | 求最值的位置 |
std,var | 求标准差和方差 |
ptp | 求极值 |
cumsum | 从0开始元素累积和 |
median | 求中值 |
nan+聚合方法:nansum()/nanmedian()/nanmin()… | 对数组中除nan的其它元素进行计算 |
代码如下(示例):
import numpy as np
a = np.arange(12).reshape(3,4)
a.astype('float')
a[2,2] = np.nan
np.nansum(a)
注意:
虽然python中也有相应的内置函数来进行运算,但实际进行数据处理时尽量使用numpy中的聚合函数,因为numpy中的聚合函数的运算效率远高于python中内置函数的效率。
一元函数
一元函数是只有一个自变量的函数
方法 | 描述 |
---|---|
np.abs | 绝对值 |
np.sqrt | 开平方 |
np.square | 平方 |
np.exp | 计算指数(e^x) |
np.log, np.log10, np.log2, np.log1p | 求以e为底, 以10为底,以2为底,以(1+x)为底的对数 |
np.ceil | 向上取整 |
np.floor | 向下取整 |
np.rint, np.round | 四舍六入五成偶 |
np.modf | 将整数和小数分隔开来形成两个数组 |
np.isnan | 判断是否是nan |
np.isinf | 判断是否是inf |
np.cos, np.cosh, np.sin, np.sinh, np.tan, np.tanh | 三角函数,反三角函数 |
np.sign | 将数组中的值标签化,即大于0的变为1,等于0的变为0,小于0的变为-1 |
二元函数
方法 | 描述 |
---|---|
np.add | 加法运算,相当于+ |
np.subtract | 减法运算,相当于- |
np.negative | 负数运算,相当于加个负号 |
np.multiply | 乘法运算,相当于* |
np.divide | 除法运算,相当于/ |
np.floor_divide | 取整运算(整除),相当于// |
np.mod | 取余运算,相当于% |
np.greater, np.greater_equal, np.less, np.less_equal, np.equal, np.not_equal | >, >=, <, <=, =, !=的函数表达式 |
np.logical_and | 逻辑与&的函数表达式 |
np.logical_or | 逻辑或的函数表达式 |
布尔函数
方法 | 描述 |
---|---|
np.any | 只要有一个位True,就返回True |
np.all | 只要有一个位False,就返回False |
其它函数
- np.sort() 排序函数,默认以后一个轴进行排序,且只能升序
代码如下(示例):
import numpy as np
a = np.random.randint(1,10,size=(4,4))
np.sort(a)
- np.linspace() 对指定区间进行均分
- np.unique() 返回数组中的唯一值
代码如下(示例):
import numpy as np
data = np.arange(5)
arr = np.random.choice(data,size=(2,3))
np.unique(arr, return_counts=True) # 返回数组中的唯一值,在指定return_counts=True时,返回每个唯一值出现的次数