数据分析入门
第二天 参考视频
三、Numpy使用
(一)概述
-
Numpy介绍 - 数值计算库
num - numerical 数值化的
py - python
开源python科学计算库,用于处理任意维度的数组
-
ndarray - Numpy核心数据结构
n - 任意个
d - dimension 维度
array - 数组
-
ndarray 相比于原生python的list
(1)存储风格
ndarray - 相同类型 - 通用性不强 (存储时数据地址连续,顺序存储?)
list - 不同类型 - 通用性很强(存储时不一定连续,有引用类型)
(2)并行化运算(向量化运算)
ndarray支持向量化运算
(3)底层语言
C语言,解除了GIL
(二)认识N维数组 - ndarray属性
-
ndarray的属性(5个)
shape - 形状
ndim - 维度 size - 数组中item个数
dtype - 类型
itemsize - 每一项大小
-
ndarray的形状 (具体请参考“Numpy矩阵维度和axis操作理解” Numpy矩阵维度链接 axis理解链接)
(x1,x2,x3,…,xn) 有n维,每一个维度xi个下标,共有 ∏ i = 1 n x i \displaystyle\prod_{i = 1}^{n}x_i i=1∏nxi个元素(偏好设置勾选LaTeX内联公式,LaTeX内联公式参考此)
-
ndarray的类型
# 常用int32,int64,float32,float64等 # 两种指定类型的方式 np.array([1.1,2.2,3.3],dtype=np.float32) np.array([1.1,2.2,3.3],dtype='float32')
(三)基本操作 (ndarray.方法() /np.函数名() )
-
生成数组的方法
(1)生成0和1
# shape=可写可不写,其后既可以用(tuple)也可用[list] np.zeros(shape=(3,4),dtype='float32') np.ones(shape=[3,4],dtype=np.int32)
(2)从现有数组中生成
score = np.ones([3,4],dtype=np.int32) # np.array() 深拷贝(新造了个对象) data1 = np.array(score) # np.copy() 深拷贝 data3 = np.copy(score) # np.asarray() 浅拷贝(用指针指向原对象) data2 = np.asarray(score)
(3)生成固定范围的数组
# np.linspace(0, 10, 100) # [0, 10](左闭右闭),等距离 np.linspace(0,10,5) # array([ 0. , 2.5, 5. , 7.5, 10. ]) # np.arange(a, b, c) # 类似range(a, b, c),[a, b)(左闭右开),c是步长 np.arange(0,10,5) # array([0, 5]),10取不到
(4)生成随机数组(分布状况 - 直方图)
# 均匀分布 - 每组的可能性相等 myData1 = np.random.uniform(low=-1.0, high=1.0, size=(1000000,)) # plt.figure(figsize=(20,8),dpi=80) # plt.hist(myData1,bins=1000) # plt.show()
# 正态分布 - 自然界常见 # μ:平均值 # σ:标准差(方差开根号),通常称为幅度、波动程度、集中程度、稳定性、离散程度 myData2 = np.random.normal(loc=0.0, scale=1.0, size=(1000000,)) # loc - μ,scale - σ,size - 生成正态分布值个数 # plt.figure(figsize=(20,8),dpi=80) # plt.hist(myData2,bins=1000) # plt.show()
-
数组的索引、切片
# 每一维操作同原生list(左闭右开) a1 = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]) print(a1.shape) # shape=(2, 2, 3) # 取7,8,9三个数 print(a1[1,0,:3]) # 三维里的第二个,二维里的第一个,一维里三个元素
-
形状修改(三种方法)
对于Reshape和Resize的作用尚存疑惑,以后用到再深究
# 对于Reshape和Resize的作用尚存疑惑,以后用到再深究 testDataReshape = np.random.normal(loc=0,scale=1,size=(8,10)) # ndarray.reshape(shape) 返回新的ndarray,原始数据没有改变 testDataReshape.reshape(10,8) # 只对原ndarray进行了切割后赋给新ndarray,并没有改排列 testDataReshape.reshape(-1,8) # -1表示自动计算行数 testDataResize = np.random.normal(loc=0,scale=1,size=(8,10)) # ndarray.resize(shape) 没有返回值,对原始的ndarray进行了修改 testDataResize.reshape(10,8) # 只对原ndarray进行了切割后,并没有改排列 testDataT = np.random.normal(loc=0,scale=1,size=(8,10)) # ndarray.T 转置 行变成列,列变成行 testDataT.T
-
类型修改
# 修改ndarray中数据的数据类型 testData = np.random.normal(loc=0,scale=1,size=(8,10)) # ndarray.astype(type) testData.astype("int32") # ndarray序列化到本地 # 不推荐使用 testData.tostring()
-
数组的去重
testData = np.array([[1,2,3,4],[3,4,5,6]]) # 使用np方法 np.unique(testData) # 使用flatten将n维变成一维,再用set集合 set(testData.flatten())
(四)ndarray运算
-
逻辑运算
stock_change = np.random.normal(loc=0,scale=1,size=(8,10)) # 如果>0.5为True,否则为False stock_change_with_condition = stock_change>0.5 # 布尔索引 stock_change[stock_change>0.5] = 1.1 # 传入了一组bool值 stock_change # 所有值>0.5的都被改成了1.1 # np.all(布尔值) 只要有一个False就返回False,只有全是True才返回True # 判断stock_change[:2,:5]是否全是上涨的 stock_change[:2,:5]>0 np.all(stock_change[:2,:5]>0) # np.any() 只要有一个True就返回True,只有全是False才返回False # 判断前五支stock_change[:5,:]是否有上涨的 np.any(stock_change[:5,:]>0) # np.where(三元运算符) np.where(传入布尔值, True的位置的值, False的位置的值) # 判断前四支股票前四天stock_change[:4,:4]涨跌幅 np.where(stock_change[:4,:4]>0,1,0) # np.where(三元运算符)复杂逻辑判断 np.logical_and(stock_change[:4,:4]>0,stock_change[:4,:4]<10) # 将此组bool值传入where即可运算 np.logical_or(stock_change[:4,:4]>0.7,stock_change[:4,:4]<0.2)
-
统计运算
# min, max, mean, median, var(方差), std(标准差) stock_change = np.random.normal(loc=0,scale=1,size=(8,10)) # 使用ndarray方法 stock_change.max(axis=0) # 按列排最大值 即把第0维[]里面包含的8个[],按每一个相同位置比较大小得出最大值 stock_change.max(axis=1) # 按行排最大值 即把第1维[](共8个)里面包含的10个值,比较大小得出最大值 stock_change.max(axis=-1) # -1,从右往左数,只有两维时,左数第二维即右数-1维 np.max(stock_change,axis=1) # 使用np函数亦可 # 实际使用时直接试试即可 # 返回最大值下标 stock_change.argmax(axis=1) np.argmax(stock_change,axis=1)
-
数组间运算
(1)数组与数的运算
# + - * / 等 test = np.array([[1,2,3],[3,5,6]]) test + 1
(2)数组与数组的运算 参考链接
# 广播机制broadcast ''' 广播 当两个数组的形状并不相同的时候,我们可以通过扩展数组的方法来实现相加、相减、相乘等操作 广播的原则 广播的原则:如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符,或其中的一方的长度为1,则认为它们是广播兼容的。广播会在缺失和(或)长度为1的维度上进行。 这句话乃是理解广播的核心。广播主要发生在两种情况,一种是两个数组的维数不相等,但是它们的后缘维度的轴长相符,另外一种是有一方的长度为1(一方为1时可以维度不同,此种情况应该是有一方后缘维度为1,扩展后两者后缘维度相等)。 ''' import numpy as np import matplotlib.pyplot as plt %matplotlib inline import random arr1 = np.array([[1],[1],[1],[2]]) #arr1.shape = (4,1) arr2 = np.array([2, 3, 4,5]) #arr2.shape = (4,) arr_sum = arr1 + arr2 print(arr_sum) ''' # arr1沿着1维扩展,arr2沿着0维扩展 result: [[3 4 5 6] [3 4 5 6] [3 4 5 6] [4 5 6 7]] '''
(3)矩阵运算
①什么是矩阵
矩阵matrix,只能是二维的
②矩阵是有一定运算规则限制的二维数组
# 矩阵的存储有两种方式 # 1.ndarray 二维数组 data = np.array([[60,61],[62,63],[64,65],[66,67],[68,69],[70,71],[72,73],[74,75]]) # 2.matrix数据结构 data_mat = np.mat([[60,61],[62,63],[64,65],[66,67],[68,69],[70,71],[72,73],[74,75]])
③矩阵的操作
# 乘法运算,同线性代数,形状(m, n) * (n, l) = (m, l) # 1.以ndarray二维数组方式存储时,实现矩阵乘法 data = np.array([[60,61],[62,63],[64,65],[66,67],[68,69],[70,71],[72,73],[74,75]]) weights = np.array([[0.3],[0.7]]) # 第一种方式 np.matmul(data,weights) # 第二种方式 np.dot(data,weights) # 第三种方式 data @ weights # 2.以matrix数据结构方式存储时,实现矩阵乘法 data_mat = np.mat([[60,61],[62,63],[64,65],[66,67],[68,69],[70,71],[72,73],[74,75]]) weights_mat = np.mat([[0.3],[0.7]]) data_mat * weights_mat
(五)合并、分割
-
合并矩阵(拼接一定要注意各个维数大小对应)
a = np.array([[1,1,1],[2,2,2]]) # a.shape=(2, 3) b = np.array([[4,4,4],[5,5,5]]) # b.shape=(2, 3) # np.hstack() 水平拼接 np.hstack((a,b)) # np.vstack() 竖直拼接 np.vstack((a,b)) # np.concatenate() # 此函数作用与numpy矩阵维度以及axis作用相关 np.concatenate((a,b),axis=1) # 水平拼接 把第1维对应矩阵拼接,shape(2, 3)变成(2, 6),第1维变第0维不变 np.concatenate((a,b),axis=0) # 竖直拼接 把第0维对应矩阵拼接,shape(2, 3)变成(4, 3),第0维变第1维不变
-
分割
a = np.array(range(8)) # np.split()只能进行均等分割。 np.split(a,2) # np.array_split()可以进行不均等分割 np.array_split(a,3)
(六)IO操作与数据处理
-
一般不用numpy读取数据
-
缺失值处理(一般使用pandas,不用numpy直接处理)
①直接删除含有缺失值的样本
②替换/插补,按列求平均,用平均值进行填补def fill_nan_by_column_mean(t): for i in range(t.shape[1]): # shape=(n,m) t.shape[1]取出m,即列数 # 计算nan个数 nan_num = np.count_nonzero(t[:,i][t[:,i] != t[:,i]]) if nan_num > 0: now_col = t[:,i] # 求和 now_col_not_nan = now_col[np.isnan(now_col) == False].sum() # 求平均值 now_col_mean = now_col_not_nan / (t.shape[0] - nan_num) # 赋值给now_col now_col[np.isnan(now_col)] = now_col_mean # 赋值给t,即更新当前列 t[:,i] = now_col return t