本文内容主要来自阿里云免费课程《Python 科学计算库 NumPy 快速入门》 课程链接
NumPy 官方文档:https://numpy.org/devdocs/user/quickstart.html
NumPy(Numerical Python)是一个开源的Python科学计算库,用于快速处理任意维度的数组。Numpy支持常见的数组和矩阵操作。对于同样的数值计算任务,使用Numpy比直接使用Python要简洁的多。
NumPy 使用 ndarray 来处理多维数组,该对象是一个快速而灵活的大数据容器。
NumPy 提供了一个N维数组类型 ndarray,它描述了相同类型的“items”的集合。
NumPy 专门针对ndarray 的操作和运算进行了设计,所以数组的存储效率和输入输出性能就远优于Python中的嵌套数组,数组越大,NumPy的优势就越明显。
ndarray与python list的不同
上图可以看出 ndarray 在存储数据的时候,数据与数据的地址都是连续的,这样就给是的批量操作数组元素时速度更快。
因为ndarray中的所有元素的类型都是相同的,而Python list中的元素类型是任意的,所以ndarray在存储元素时内存可以连续,而Python原生list只能通过寻址的方式找到下一个元素,这虽然也导致了在通用性能方面Numpy的ndarray就可以省掉很多循环语句,代码使用方面比Python原生list简单的多。
NumPy的数组比Python列表更紧凑-您在Python中描述的列表列表至少需要20 MB左右,而单元格中具有单精度浮点数的NumPy 3D数组则需要4 MB。使用NumPy可以更快地读取和写入项目。
也许您只关心一百万个单元格就不会那么在意,但您肯定会关心十亿个单元格-这两种方法都不适合32位体系结构,但是如果使用64位版本,NumPy可以节省大约4 GB的内存,仅Python就需要至少约12 GB(很多指针的大小加倍),这是一个昂贵得多的硬件!
差异主要是由于“间接性”所致-Python列表是指向Python对象的指针的数组,每个指针至少4个字节,即使最小的Python对象也至少包含16个字节(类型指针为4,引用计数为4,类型为4值-内存分配器舍入为16)。NumPy数组是统一值的数组-单精度数字每个占用4个字节,双精度数字每个占用8个字节。灵活性较差,但您需要为标准Python列表的灵活性付出巨大的代价!
(问题来源于stack overflow)
1.shape
2.dtype
3.itemsize
在创建ndarray的时候,没有指定数据类型的时候,默认情况下,整数为int64,小数默认为float64.(元素大小为8个字节)
维度的判断:中括号[]的层数。第一个元素前有几层中括号(嵌套)就是几维。
维度的表示:元组。是几维的就用几个元素表示。例如:
import numpy as np
a = np.array([[1,2,3],[4,5,6]])
b = np.array([1,2,3,4])
c = np.array([[[1,2,3],[4,5,6]],[[1,2,3],[4,5,6]]])
a # (2,3) 二维数据表示
b # (4,) 一维数据表示
c # (2, 2,3) 三维数据表示 (最外层嵌套的数组数,嵌套数组中二维数组的行数,嵌套元素中二维数组的列数)
如何理解数组的形状?
二维数组:
三维数组:
先看最外层有几个二维数组(如图中对角线所示),再看二维数组中的数据情况。
常用:
np.array(,dtype = “float32”)
np.array(,dtype = np.float32)
np.zeros(shape) # shape可以用列表,也可以用元祖指定。
np.ones(shape)
np.array() np.copy() 深拷贝
np.asarray() 浅拷贝 如果修改原数组中元素改变,np.asarray()也随之改变。
np.linspace(区间起点,区间终点,数据量) 闭区间等距离生成。
np.arange(区间起点,区间终点,步长) 左闭右开以设定步长生成,如果区间终点取不到则不生成。
import numpy as np
data1 = np.random.uniform(low=-1, high=1, size=1000000)
# 查看数据分布情况
import matplotlib.pylot as plt
# 创建画布
plt.figure(figsize=(20,8), dpi=80)
# 绘制直方图
plt.hist(data1, 1000)
# 显示图像
plt.show()
正态分布:均值决定了其位置,标准差决定了分布的幅度,标准差越大,数据越分散。
标准差别称:幅度/波动程度/集中程度/稳定性
np.random.normal(loc=0.0, scale=1.0, size=None)
loc:均值;scale:标准差;size:数据量。
import numpy as np
stock_change = np.randoms.normal(loc=0, scale=1, size=(8, 10))
### 获取第一个股票的前3个交易日的涨跌幅数据
stock_change[0, :3] # stock_change[0, 0:3]
#三维数组的索引
a1 = np.array([[[1,2,3],[4,5,6]],[[1,2,3],[4,5,6]]])
a1.shape
a1[1, 0, 2] #索引从零开始计
【需求:将刚才的股票行、日期列翻转。】
reshape()方法 有返回值,在不改变原数组数据的情况下,将它reshape成一个新的维度。如果给定的数组数据和需要reshape的形状不符合时,将会报错。
stock_change.reshape((10, 8))
#resize()方法 没有返回值,给定一个数组,和特定维度,将会返回一个给定维度形式的新数组。如果新数组比原数组大,则将会copy原数组中的值对新数组进行填充
stock_change.resize((10, 8))
#.T类似于矩阵转置操作
stock_change.T
ndarray序列化到本地:.tostring()方法
注:有可能遇到jupyter notebook输出限制的问题(IOPub data rate exceeded),需要修改配置文件。
逻辑运算
布尔索引
通用判断函数
np.all(布尔值)
只要有一个False就返回False,只有全是True才返回True
np.any()
只要有一个True就返回True,只有全是False才返回False
np.where()
np.where(布尔值,True的位置的值,False的位置的值)
统计运算
统计指标函数
min, max, mean, median, var, std
np.函数名
ndarray.方法
返回最大值、最小值所在位置
数组间运算
# 逻辑判断,如果涨跌幅大于0.5就标记为True,否则为False
stock_change > 0.5
# Bool赋值,将满足条件的设置为指定的值-布尔索引
stock_change[stock_change > 0.5] = 1
np.all()
# 判断stock_change[0:2, 0:5]是否全是上涨的
np.all(stock_change[0:2, 0:5] > 0) # False
np.any()
np.any(stock_change[0:5, :] > 0 # True
# 判断前四个股票前四天的涨跌幅,大于零的位置为1,否则为0
np.where(temp > 0, 1, 0)
符合逻辑需要结合np.logical_and 和 np.logical_or使用
# 判断前四个股票前四天的涨跌幅,大于0.5并且小于1的,换为1,否则0.
# 判断前四个股票前四天的涨跌幅,大于0.5并且小于-0.5的换为1,否则为0.
np.logical_and(temp > 0.5, temp < 1)
# 前四只股票前四天的最大涨幅
temp.max(axis=0) #按照列求最大值
temp.max(axis=1) #按照行求最大值
# 计算某只股票在某个交易日的涨幅最大或最小
np.argmax(temp, axis=)
np.argmin(temp,axis=)
不同形状的数组之间是不能运算的,需要满足广播机制。
执行广播机制的前提在于,两个ndarray执行的是element-wise的运算,broadcast机制的功 能是为了方便不同形状的ndarray(numpy库的核心数据结构)进行数学运算。
当操作两个数组时,numpy会逐个比较他们的shape(构成元组的tuple),只有在下述情况下,两个数组才能够进行数组与数组的运算:
1.什么是矩阵
矩阵--二维数组
矩阵 和二维数组的区别联系:矩阵一定是二维数组,反之不成立。
两种方法存储矩阵
1)ndarray数组
2)matrix数据结构
2.矩阵乘法运算
形状
(m, n)× (n,l)=(m,l) 引用汤老师口诀:内标决定乘,外标决定型。八达鸟
运算规则
略
矩阵乘法api:
np.matmul
np.dot
ndarray存储矩阵
注意:使用运算符运算时,矩阵乘用 *与ndarray乘用@,两种操作结果相同。
读取会出先有缺失值问题,有些字段的读取结果会显示nan,如何处理缺失值的问题,有两种思路:
处理逻辑:
def fill_nan_by_column_mean(t):
#t.shape[1]获取列的索引,按照列进行填充。
for i in_range(t.shape[1]):
nan_num = np.count_nonzero(t[:,1][t[:,1] != t[:,i]])
if nan_num > 0:
#选中所有行,每一次循环计算一列
now_col = t[:,i]
# 求某一列所有不为nan的元素和
now_col_not_nan = now_col[np.isnan(now_col) == False].sum()
# 求均值 = 不为零元素和和/不为零元素个数个数
now_col_mean = now_col_not_nan / (t.shape[0] – nan_num)
# 赋值给t,即更新t当前列
t[:,i] = now_col
return t
Numpy数据运算有优势,数据处理适合用Pandas。