《利用Python进行数据分析·第2版》第四章 Numpy基础:数组和矢
《利用Python进行数据分析·第2版》第四章 Numpy基础:数组和矢量计算numpy高效处理大数组的数据原因:
4.0 前提知识数据:结构化的数据代指所有的通用数据,如表格型,多维数组,关键列,时间序列等 import numpy as np import matplotlib.pyplot as plt import pandas as pd import seaborn as sns import statsmodels as sm 数据规整(Munge/Munging/Wrangling): 伪码(Pseudocode): 语法糖(Syntactic sugar): 4.1 Numpy的ndarrray:一种多维数组对象ndarray:N维数组对象,快速而灵活的大数据集容器
对整块数据执行运算的语法=标量元素执行运算的语法 np.random.randn(n,m):生成2行3列的正态分布随机数组 data = np.random.randn(2,3) array([[-0.2047,0.4789,-0.5194],[-0.5557,1.9658,1.3934]]) data * 10 array([[ -2.0471,4.7894,-5.1944],[ -5.5573,19.6578,13.9341]]) In [17]: data.shape Out[17]: (2,3) In [18]: data.dtype Out[18]: dtype('float64') 1)创建ndarraynp.array(一切对象)—>自动推断数据类型 np.zeros((n,m)) / np.ones((n,m)) / np.empty((n,m)):生成全0,全1,全未初始化垃圾值数组,传入元组/整数 np.arange():range函数的numpy版本 如果没有特别指定,数据类型基本都是float64(浮点数) 2)ndarray的数据类型dtype是一个特殊的对象:含有ndarray将一块内存解释为特定数据类型所需的信息 numpy会将 Python类型映射到等价的dtype上(如误写float映射为np.float64) 3)Numpy数组的运算矢量化(vectorization):大小相等的数组之间任何运算均应用到元素级 数组与标量的算术运算会将标量值广播到各个元素 大小相同的数组之间比较会生成布尔数组(逻辑运算) 4)基本的索引和切片一维数组: 数组切片是原始数组的视图,不同于python内置列表,切片上的修改会映射到源数组上 二维数组: 5)切片索引一维数组同python列表 6)布尔型索引一维布尔型数组可用于数组索引:一维布尔型数组长度==索引数组的行长度(轴长度) —>用于筛选 比较运算(组合逻辑)得到布尔型索引—>比较运算可以用!= / 也可以用~()对条件进行否定 布尔型数组中用 & 和 | ,而不用and or —>数据运算得到的布尔型索引数组是新数组 print(data) print(data[names == 'tom',1:]) [[ 0.16915065 0.15038684 0.34028728] [ 0.32732646 0.69241855 0.65203056] [ 0.84402175 0.77184234 0.48730057] [ 0.94376757 0.33876278 0.77287885] [ 0.58535219 0.50321862 0.28196336]] [[ 0.15038684 0.34028728] [ 0.50321862 0.28196336]] (注意: 原书中翻译“通过布尔型索引选取数组中的数据,将总是创建数据的副本,即使返回一模一样的数组也是如此。”<该处翻译可能有误>,因为如下) In [113]: data[data < 0] = 0 In [114]: data Out[114]: array([[ 0.0929,0.2817,0.769,1.2464],[ 1.0072,0.,0.275,0.2289],[ 1.3529,0.8864,0. ],[ 1.669,0.477 ],[ 3.2489,0.1241],[ 0.3026,0.5238,0.0009,1.3438],[ 0.,0. ]]) 可以通过布尔索引对数组进行赋值,证明布尔索引得到的数据是视图而非副本 7)花式索引numpy术语,利用整数数组进行索引 In [119]: arr Out[119]: array([[ 0.,0.],[ 1.,1.,1.],[ 2.,2.,2.],[ 3.,3.,3.],[ 4.,4.,4.],[ 5.,5.,5.],[ 6.,6.,6.],[ 7.,7.,7.]]) In [120]: arr[[4,3,6]] Out[120]: array([[ 4.,6.]]) 花式索引在选择索引行、列上使用频繁(1.一个[]就是一个维度,逗号分割维度 2.按照[]内顺序进行筛选 npo[[行],[:,列]],扩展同理(后面格式必须得这样,否则会出现预期不一样的结果 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],[24,25,26,27],[28,29,30,31]]) In [124]: arr[[1,7,2],[0,2]] #这种格式相当于是[1,0],[5,3].... Out[124]: array([ 4,23,10]) In [125]: arr[[1,2]][:,2]] #这种格式才是预期的结果,把第一行的第0,2列都拿出来,再是第五行的.... Out[125]: array([[ 4,6],22],31,30],11,10]]) 花式索引!=切片,花式索引是副本而非视图 8)数组转置和轴对换npo.T属性:数组的转置数组(方法一:针对一二维数组:返回视图非副本 In [60]: arr1 Out[60]: array([[[ 0,[ 3,4,5]],[[ 6,8],[ 9,11]]]) In [61]: arr1.shape #看形状 Out[61]: (2,3) #说明这是一个2*2*3的数组(矩阵),返回的是一个元组,可以对元组进行索引,也就是0,2,维度进行编号 In [134]: arr.transpose((1,2)) #这里的(1,2)元组就相当是维度元组(0,2) 说明把第三维和第二维进行了交换(一般而言保持第一维度不会变化 Out[134]: array([[[ 0,#比如数值6,原本是(1,0)的位置,变换后是(0,0) [ 8,11]],[[ 4,15]]]) np.dot():计算矩阵内积 —>np.dot(npo.T,npo) 转置和轴对换 4.2 通用函数:快速的元素级数组函数 ufunc简单函数(接受一个或多个标量值,并产生一个或多个标量值)的矢量化包装器。 一元ufunc(接受一个矢量):np.sqrt np.exp... 一元:unary ufunc可接受一个out可选参数:表示在传入数组上原地进行操作(即结果值返回至数组中 4.3利用数组进行数据处理np.meshgrid():生成网格点坐标矩阵 //强烈的规律性快速生成矩阵 图中每个交叉点都是网格点;网格点的坐标的矩阵就是坐标矩阵
传入参数为两个一维数组,分别是所有的x、y值 numpy.meshgrid()理解 1)将条件逻辑表述为数组运算np.where():三元表达式 x if condition else y 的矢量化版本 In [165]: xarr = np.array([1.1,1.2,1.3,1.4,1.5]) In [166]: yarr = np.array([2.1,2.2,2.3,2.4,2.5]) In [167]: cond = np.array([True,False,True,False]) #cond为True时,选取xarr的值,否则从yarr中选取。 In [168]: result = [(x if c else y) #列表生成式写法 .....: for x,y,c in zip(xarr,yarr,cond)] In [169]: result Out[169]: [1.1000000000000001,2.2000000000000002,1.3999999999999999,2.5] #1.大数据处理慢 2.无法用于多维数组(多个for时间度问题 In [170]: result = np.where(cond,xarr,yarr) #np.where解决 In [171]: result Out[171]: array([ 1.1,2.5]) np.where作用:根据另一个数组而产生一个新数组; In [173]: arr Out[173]: array([[-0.5031,-0.6223,-0.9212,-0.7262],[ 0.2229,0.0513,-1.1577,0.8167],[ 0.4336,1.0107,1.8249,-0.9975],[ 0.8506,-0.1316,0.9124,0.1882]]) In [174]: arr > 0 Out[174]: array([[False,False],[ True,True],True]],dtype=bool) In [175]: np.where(arr > 0,-2) Out[175]: array([[-2,-2,-2],[ 2,2]]) 2)数学和统计方法聚合计算:(aggregation,通常叫约简(reduction)) 聚类统计 np.sum np.mean np.std... 求和平均标准差 可以对整个数组 / 也可以接受一个axis计算对某轴的统计值 非聚合计算:np.cumsum np.cumprod... 累加累乘 产生一个结果数组(多维数组中一样,可以指定轴) 3)用于布尔型数组的方法布尔型数组也可用于统计方法—>转为1 / 0 (sum求True个数 4)排序npo.sort():原地排序 (多维数组加axis np.sort返回副本,npo.sort原地修改本身 计算数组分位数:1.排序 2.选取特定位置值 In [203]: large_arr = np.random.randn(1000) In [204]: large_arr.sort() In [205]: large_arr[int(0.05 * len(large_arr))] # 5% quantile Out[205]: -1.5311513550102103 其他排序:附录+pandas 5)唯一化以及其他的集合逻辑集合函数 np.unique():找出数组中唯一值并返回排序结果 = set+sorted 4.4 用于数组的文件输入输出(较为简单的fIO)np.save:数组以未压缩的原始二进制格式 扩展名:.npy 4.5线性代数x.dot(y) = np.dot(x,y) :矩阵乘法 所有数组dot方法和np命名空间函数的区别是:dot方法是视图,函数是副本 @符(类似python3.5)也可以作为中缀运算符进行矩阵乘法: In [230]: x @ np.ones(3) Out[230]: array([ 6.,15.]) numpy.linalg中有一组标准的矩阵分解运算以及如求逆和行列式等: 4.6 伪随机数生成np.random.normal:标准正态分布 4.7 示例:随机漫步纯python: In [247]: import random .....: position = 0 .....: walk = [position] .....: steps = 1000 .....: for i in range(steps): .....: step = 1 if random.randint(0,1) else -1 .....: position += step .....: walk.append(position) .....: 转为numpy: In [251]: nsteps = 1000 In [252]: draws = np.random.randint(0,size=nsteps) #size决定是一维的 In [253]: steps = np.where(draws > 0,-1) In [254]: walk = steps.cumsum() In [249]: plt.plot(walk[:100]) #x步数也就是时间,y是离初始点的距离 对l累加后的漫步数据一些统计计算处理: In [255]: walk.min() Out[255]: -3 In [256]: walk.max() Out[256]: 31 假设离初始点距离10步外就是穿越过了漫步地点,想要知道首次穿越时间: In [257]: (np.abs(walk) >= 10).argmax() #argmax返回数组最大值的第一个索引位置 Out[257]: 37 #所以第37步时第一次走出漫步地点 一次性模拟多个随机漫步: In [258]: nwalks = 5000 In [259]: nsteps = 1000 In [260]: draws = np.random.randint(0,size=(nwalks,nsteps)) # 0 or 1 #size决定是二维的 行:第几次walk 列:nwalk的第几步 In [261]: steps = np.where(draws > 0,-1) In [262]: walks = steps.cumsum(1) #按行作累加 / 非聚合 In [263]: walks Out[263]: array([[ 1,...,8,[ 1,-1,34,33,32],4],24,26],14],[ -1,-3,-24,-23,-22]]) 计算所有随机漫步的统计数据: In [264]: walks.max() Out[264]: 138 In [265]: walks.min() Out[265]: -133 之后计算每个随机漫步的首次穿越时间:阈值=30(注:不是每次漫步都能够穿越,所以需要清理检查 In [266]: hits30 = (np.abs(walks) >= 30).any(1) #按行筛选每行是不是有abs>30的值 In [267]: hits30 Out[267]: array([False,dtype=bool) In [268]: hits30.sum() # Number that hit 30 or -30 #为True的就是满足要求的,一共有3410个 Out[268]: 3410 获取穿越时间: In [269]: crossing_times = (np.abs(walks[hits30]) >= 30).argmax(1) #花式索引筛选满足要求行+argmax找到首次穿越的时间 In [270]: crossing_times.mean() Out[270]: 498.88973607038122 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |