admin 管理员组

文章数量: 887021

《利用python进行数据分析》是一本利用python的Numpy、Pandas、Matplotlib库进行数据分析的基础介绍,非常适合初学者。

重要的python库
NumPy
http://numpy
Pandas
http://pandas.pydata
matplotlib
http://matplotlib
IPython 和 Jupyter
http://ipython
http://jupyter
Scipy
http://scipy
scikit-learn
http://scikit-learn
statsmodels
http://statsmodels
nbviewer
https://nbviewer.jupyter/

软件安装和环境配置:
安装Anaconda:https://www.anaconda/
下载安装包或者pip install jupyter notebook

Jupyter notebook用法:
内省
?, 对象前后加?号可以显示对象概要信息,针对魔术字也是生效的,即可以查看魔术字的参数
??, 使用??可以显示函数源码
?,可以作为通配符使用,与*结合可以查询符合规范的名称

Ipython magic
	https://ipython.readthedocs.io/en/stable/interactive/magics.html
	%,一个%只作用于命令行
	%%,两个%表示作用于命令框

%run
	%run script_name.py
		可以运行外部脚本
	%run -i script_name.py
		使用Ipython命名空间已有的变量
	%load script_name.py
		可以将脚本加载到单元代码
	ctrl+c
		终止程序运行
		
%paste和%cpaste
	将剪贴板代码黏贴过来,或者会提醒检查。
	没用成功过?

%timeit
	检查一段python语句的执行时间,计算平均值
	
%time
	报告单个语句的执行时间
	
%automagic
	可以关闭魔术字前面的%符号
	
%quickref
	显示Ipython快速参考卡

%magic
	显示所有magic

%debug
	从报错底部进入交互调试器,通过u和d可以切换堆栈的不同层级

%pdb
	出现任意错误自动进入调试器

%reset
	重启变量/名称,命名空间

%who, %who_ls, %whos
	展示命名空间定义的变量

%xdel variable
	删除变量

%matplotlib, %matplotlib inline
	设置matplotlib与Ipython集成,后者是用于jupyter notebook中
	
%xmode
	控制错误栈上下文的数量,有Plain和Verbose两种模式,前者同Cpython,后者是Ipython独有
	
%hist,可打印全部、部分历史输入记录

IPython扩展
ipython是一个python的交互式shell,是jupyter notebook的内核。
搜索历史命令
%run some.py
以后可输入%run s然后用上下箭头查询历史命令

输入和输出变量引用
	_和__分别表示最近的第一个和第二个命令执行结果的输出
	_number表示第number行的输出结果
	_inumber表示第number行的输入变量
	exec(_i27)可以直接执行一次第27行命令
	
与操作系统交互
	可以直接输入win或shell命令
	!cmd 执行cmd命令
	output = !cmd args 运行命令并保存输出结果
	%alias alias_name cmd 起别名
	%bookmark 使用IPython的目录书签系统。 %bookmark pydata /home/ccc/code/pydata
	%cd dir 更改目录
	%pwd 返回当前工作目录
	%pushd dir 将当前目录放在堆栈上,并更改伪目标目录
	%popd 切换到堆栈顶部弹出的目录
	%dirs 返回包含当前目录堆栈的列表
	%dhist 打印访问目录的历史记录
	%env 以字典形式返回系统环境变量
	%matplotlib 配置matplotlib集成选项

调试程序
	出问题后,通过%debug进入堆栈最底层,通过u和d可以切换堆栈的不同层级
	
	也可用%pdb直接让程序出错时进入调试模式
	
	run -d test.py,可以进入单步调试模式, s表示进入脚本,可以设置断点,可以用c继续运行程序
		b linenumber, 可以设置断点
		b path/file.py:number 在指定文件行设置断点
		n, next意思
		c, continue意思
		s,step单步意思
		!variable, 变量前面加!可以显示变量值
		u/d, 在调用栈中上下移动
		a, args显示当前函数的参数
		debug statement, 在新的调试器中调用语句statement
		l statement, 显示当前堆栈的当前位置和上下文
		w, where意思,在当前位置打印带有上下文的完整堆栈回溯
		h, help显示命令列表
		help command, 显示command命令的文档
		q,quit退出调试器
		
	%run -d test.py, 可以直接进入调试器
	
	%run -d b2 test.py, 加断点
	
	pdb.set_trace
		from IPython.core.debugger import Pdb
		def set_trace():
			Pdb(color_scheme="Linux").set_trace(sys.__getgrame().f_back)
		
		可以在程序任何地方调用set_trace(),比如在抛出异常前调用,可以进入调试模式
	
	pdb.runcall
		from IPython.core.debugger import Pdb
		def debug(f, *args, **kwargs):
			pdb = Pdb(color_scheme="Linux")
			return pdb.runcall(f, *args, **kwargs)
		可以单独调试一个函数
		def f(x, y, z=1):
			return (x+y)/z
		
		debug(f, 1,2,z=3)就可以进入调试模式
	
测试代码运行时间: %time和%timeit
	%time,执行一次
	%timeit,多次执行取平均值,可以精确到ns级别
	
分析代码性能:%prun, %run -p 
	python有个cProfile模块可以用于分析程序性能。
	举例:
		python -m cProfile -s cumulative test.py  #-s指定排序字段
	
	Ipython分析
		%prun -l 7 -s cumulative function()
		可以分析单个函数
		
		%run -p -s cumulative test.py
		
		%%prun 可以分析整个代码块。
	
	其他第三方库:SnakeViz,使用d3.js生成配置文件结果的交互式可视化
	
	%lprun,这是第三方模块,需要自己配置,可以逐行分析函数代码性能,而不仅仅限制于函数级别
		配置方式:
			方法1:c.TerminalIPythonApp.extensions = ['line_profiler']
			方法2:%load_ext line_profiler
		使用方式:
			%lprun -f add_and_sum -f call_function call_function()

重载模块
	有时候被装载的模块代码被修改,这时除了退出重新进入装载外,还有下面方法:
	import some_lib
	import importlib
	importlib.reload(som_lib)
	
	Ipython有个dreload(some_lib)可以用
	
代码设计技巧
	扁平优于嵌套
	适当的大文件比零散的多个小文件好管理
	
配置文件:
	ipython profile create   #可以形成ipython配置文件
	文件路径C:\\Users\\guangxinwang\\.ipython\\profile_default\\ipython_config.py
	
	也可以创建一个新的配置文件,并自己使用:
	ipython profile create secret_project
	ipython --profile=secret_project
	
	jupyter notebook的配置文件:
		jupyter notebook --generate-config
		默认路径.jupyter/jupyter_notebook_config.py
		jupyter notebook --config=~/.jupyter/my_custom_config.py
	
	配置内容摘要有:
		主题
		启动扩展模块等
		自定义魔术函数等

NumPy基础:数组和向量化计算
NumPy的重要性:
1、NumPy的设计对于含有大量数组的数据非常有效;
2、NumPy在内部将数据存储在连续的内存块上,NumPy的算法库是C语言写的,不需要任何类型检查。而且占用的内存量也小
3、NumPy可以针对全部数组进行复杂计算而不需要写python循环

导入:推荐import numpy as np

NumPy的核心——N维数组对象ndarray
	一个ndarray是一个通用的多维同类数据容器,即它包含的每一个元素都是相同类型
    属性:
		shape
			表示ndarray的维度
		dtype
			表示ndarray的数据类型,ndarray的默认数据类型是float64
		ndim
			表ndarray数组的维度

形成ndarray数组的方法
	array, 将输入数据转换成ndarray数组,如果不指定类型,会自动推断
	asarray, 同上,只是如果输入已经是ndarray就不再复制
	arange, range函数,返回一个数组。np.arange(0.0, 1.0, 0.01),返回从[0,1)间隔0.01的共100个dnarray数组
	ones, 全1数组
	ones_like, 根据所给数组形成全1数组,即shape同所给数组,值全1
	zeros, 全零数组
	zeros_like,参照数组形成全0数组
	empty, 空输入,内容随机
	empty_like,参照数组形成空数组
	full, 形成指定数值的数组
	full_like,参照指定数组形成指定数值的数组
	eye, identity, 形成对角线全是1的数组
	random.randn,形成随机数,满足正态分布
	random.randint,返回随机整数

ndarray的数据类型
	int/float/complex/bool/object/string_/unicode_
	长度有8/16/32/64/128/256等等
	默认int为32,float为64

	类型转换方法astype
		my_int_arra.astype(float)
		astype一定会形成新的数组

数组运算
	*,-,+,/,** 逐个元素相乘,减,加,除,幂
	>,<,逐个元素比较大小
	
索引和切片
	切记:
		NumPy的切片不生成新数组,而是原数组的引用,相关操作会直接作用在原数组上面,这样做好处是节省内存
		如果希望新创建数组需要显示的用copy方法,比如arr[5:8].copy()
		下面2种方法效果相同:
			arr2d[0][2]
			arr2d[0,2]
		可以对切片后的数组直接赋值
		
	寻址:
		对于一个N维数组a
			当需要定位到一个元素时需要同时输入N个坐标才能取到单个元素的值。
			每少一个坐标,取到的值就会多一个维度。少的一个坐标轴就会返回该坐标轴上面的所有数据;
			每多一个坐标,就可以少一个维度的不确定性。
			降维就是通过指定一个坐标轴,取该坐标轴上面其他维度的数据
			在一个轴上面切片是可以取到同维度的数组的
			
	布尔索引
		假设a数组维度为3*4即a(3,4)
		a>0,会形成同样维度的bool类型数组,里面的每个值都会是True或False
		可以用bool类型的数组作为索引,对同维度的数组进行取值,比如a(3,4),b是一维3元素数组,这样a[b>0]可以对a的行取值
			同理,更高维度也可以。比如a(5,7,4),b(7,4)执行a[:b>0]会形成一个(5,x)的维度数组,x取决于b>0的个数。注意这里会做降维处理。
		注意,两者维度不同时会报错。
		
		这里支持用==,>,<,!=,~取反,&,|等操作
		and or操作在这里不生效,需要用&/|
		
		利用布尔索引可以对一个数组的指定元素进行操作,比如a[a>0]=0,就可以将a数组里面所有大于0的元素赋值为0,而操作后a的维度不变。
		再举例:a(5,7,4),b(7,4),执行a[:,b>0]=0可以对a中所有行执行同样赋值操作,结束后a还是(5,7,4)维度不变
		
	神奇索引
		可以用数组作为索引值
		举例:
			arr(8,4)数组,arr[[4,3,0,6]]会返回第4、3、0、6行的数据,也支持负数索引
			arr[[4,3,0,6],[1,2,3,0]]返回的是一个一维数组取值(4,1),(3,2),(0,3),(6,0)
			
	行与列索引
		行索引arr[:2]
		列索引arr[:,:2]
			
	
转置和转轴
	reshape(),变换形状
		np.arange(8).reshape((2,4)) #变为2*4数组
		np.arange(8).reshape((2,-1)) #作用同上,传入-1表示让numpy自己推断数组维度
		np.arrage(8).reshape(other_arr.shape) #shape也可以作为参数传入
	扁平
		np.arange(8).reshape((2,-1)).ravel() #ravel是分散意思,会扁平成一个一维数组,不会形成副本
		np.arange(8).reshape((2,-1)).flatten() #flatten作用同ravel,区别是这个会形成一个新的副本
	arr.T,转置,是一种特殊的转轴,对于多维数组的转轴,就是将所有的轴完成倒序操作
	np.dot(arr, arr.T),计算矩阵内积
	arr.transpose()转轴,参数是轴索引
		转轴计算方法:
			第一步先变形,比如一个arr(2,3,4)矩阵,如果轴0和轴1转轴,该矩阵将变为arr(3,2,4)
			第二步填值,新的变形后的矩阵的每个元素比如arr[i,j,k]就等于原来数组的arr[j,i,k]
	arr.swapaxes()方法可以将轴进行调整重组成新数组,也是转轴的一个方法,仅支持2个轴交换
	
通用函数ufunc
	一元通用函数:
		abs,fabs, 绝对值
		sqrt,平方根
		square, 平方
		exp, e的指数值
		log,log10,log2,log1p,分别是以e,10,2为底,最后一个是log(1+x),默认以e为底
		sign, 求符号值,1,0,-1
		cell,最高整数,遇到小数往上取整
		floor,往下取整
		rint,保留整数位,且保留dtype
		modf, 分别返回小数和整数部分
		isnan,判断是否为NaN,不是一个数值
		isfinite,isinf, 是否有限还是无限
		cos,cosh,sin,sinh,tan,tanh三角函数
		arccos,arccosh,arcsin,arcsinh,arctan,arctanh,反三角函数
		logical_not,对数组元素按位取反,同~arr
	二元通用函数:
		add,元素对应相加
		subtract,减
		multiply,乘
		divide,floor_divide,除,整除
		power, 幂
		maximum,fmax,最大值
		minimum, fmin,最小值
		mod,取模求余数
		copysign,将第一个数组的符号值改成第二个数组的
		greater,greater_euqal,less,less_equal,equal,not_equal,逐元素比较,返回布尔型
		logical_and,logical_or,logical_xor,逻辑与,或,异或

面向数组编程
	np.where
		等同于python的 x if condition else y
		格式:
			new_arr = np.where(condition, xarr, yarr)
		解释:
			condition是条件判断,如果为真元素取xarr中值,false取yarr中的值
		举例:
			np.where(arr>0, 2, -2)
			arr中元素如果大于0会被置为2,小于0会被置为-2
	
	统计方法
		数组方法和np方法都可以
		arr.mean()或np.mean(arr),平均值
			mean(axis=0),计算给定轴的平均值,就是把该轴上面的值求和然后再平均,这样会导致该轴的维度扁平为1维。
			mean(0),不带axis也可以
			如果是一个三维数组(2,3,4),mean(axis=2)会把轴2扁平化,形成(2,3)数组
		sum(),求和
		cumsum()累计求和
			cumsum(axis=0),沿着行做累计求和,就是从第2行开始,每个元素都是上一行对应列加本行对应列的和。即把所有axis轴数据都加起来。
		std()标准差
		var()方差
		cov()协方差
		min(),max()最小最大值
		argmin(),argmax(),最小最大值得位置
		cumprod(),从1开始元素累积积运算,cumsum是和运算
		
	布尔值数组方法
		(arr > 0).sum()可以计算True数量
		any(),任意为True就为True
		all(),所有为True才为True
	
	排序
		sort(),可以沿着axis排序如sort(0)就是沿着x轴对y轴进行排序,就是只对y轴排序
	
	唯一值
		np.unique()
			针对一维数组,返回的是去重后的数组,并且还完成排序
		np.in1d(arr1, arr2)
			判断数组1中值是否在数组2中,返回bool类型的数组,长度同arr1
		intersect1d(x, y)
			x,y交集并排序
		union1d(x,y)
			x,y并集并排序
		setdiff1d(x, y)
			差集,在x但不在y中的x的元素
		setxor1d(x,y)
			异或,在x或y中,但不同时在x和y中
	
装载与存储
	np.save(file, arr, allow_pickle=True, fix_imports=True)
	np.load(file,mmap_mode=None,allow_pickle=False,fix_imports=True,encoding='ASCII',)
		默认都是二进制形式存取的
		文件后缀默认是npy
	np.savez(file, *args, **kwds)
		压缩存储
		举例:
			np.savez("array_arhive.npz", a=arr1, b=arr2)
			此时用np.load会返回一个字典类型
			arch = np.load("array_archive.npz")
			可以用arch['a']或arch['b']取到存储的数组
	np.savez_compressed(file, *args, **kwds)
		将新的数组存入已经压缩好的文件中
		
线性代数
	*, 表示矩阵逐元素乘法
	dot(),表示矩阵点乘
		arr1.dot(arr2)
		np.dot(arr1,arr2)
	arr1 @ arr2 
		@也是点乘,属于一元运算符
	
	numpy.linalg库函数(linear algebra)线性代数
		diag, 用于将一个方阵的对角元素转换为一维数组,或者把一维数组转换为方阵
		dot,点乘
		trace,计算对角元素和
		det,计算矩阵的行列式
		eig,(eigen)计算方阵的特征值和特征向量
		inv,(inverse)计算方阵的逆矩阵
		pinv,计算矩阵的Moore-Penrose伪逆
		qr,计算QR分解
		svd,计算奇异值分解(SVD)
		solve,求解x的线性系统Ax = b, 其中A是方阵
		lstsq,(least square)计算Ax=b的最小二乘解
	
伪随机数的形成
	np.random.normal(size=(4,4))
		形成4*4的正态分布数组
	
	np.random.seed(1234)
		更改伪随机种子,作用于全局。随机种子类似于产生随机数的初始值,随机种子相同情况下产生的随机数也相同,所以要产生不同随机数需要重置随机种子。
		
	np.random.RandomState(1234)
		创建伪随机生成器,独立于全局随机种子的影响
		rng = np.random.RandomState(1234)
		rng.randn(10)
	
	常用函数列表:
		seed, 种子
		permutation, 返回一个序列的随机排列,或返回一个乱序的整数范围序列
		shuffle, 随机排列一个序列
		rand,从均匀分布中抽取样本
		randint, 根据给定的由低到高的范围抽取随机整数
		randn, 从均值0方差1的正态分布中抽取样本
		binomial, 从二项分布中抽取样本
		normal, 从正态分布中抽取样本
		beta,从beta分布中抽取样本
		chisquare, 从卡方分布中抽取样本
		gamma,从伽马分布中抽取样本
		uniform,从均匀[0,n)中抽取样本,np.random.uniform(0,10000,size=50)
		
举例1:
    import matplotlib.pyplot as plt
	nsteps = 1000
	draws = np.random.randint(0, 2, size=nsteps) #从0,1中随机抽取1000次
	steps = np.where(draws > 0 , 1, -1) #把0,1格式化成-1和1
	walk = steps.cumsum() #对数组做累计求和
	plt.plot(walk) #打印折线图
	walk.min() #求连续走最小或最大步数
	(np.abs(walk) >= 10).argmax() #求第一次连续一个方向走10步的位置
举例2:	
	nwalks = 5000
	nsteps = 1000
	draws = np.random.randint(0, 2, size=(nwalks,nsteps)) #形成一个二维数组
	steps = np.where(draws > 0, 1, -1)
	walks = steps.cumsum(1) #沿着1轴做累计和
	hits30 = (np.abs(walks) >= 30).any(1) #沿着1轴做任何一个元素为True就总结果为True,返回的hits30是一个5000行的一维数组,元素都是True和False
	crossing_times = (np.abs(walks[hits30]) >= 30).argmax(1) #walks[hits30]获取hits30中为True的行,比如有3000行,argmax沿着1轴求最大值第一次出现的位置索引
	crossing_times.mean() #请第一次出现位置的平均值

NumPy进阶:
数组构成
NumPy数组包含下面内容:
指向数据的指针
数据类型dtype
表示形状的元组
步长元组
比如np.ones((2,3,4),dtype=np.int32).strides是(48, 16, 4)
解析:
最后一个4是数据长度为4字节
第一个48表示344,表示每行的跨度是48字节
第二个16表示4*4,表示最小一维数组的跨度是16字节
dtype层次结构和类型判断
generic -> number -> integer -> unsigned int 各种字节的无符号数,下同
| | -> signed int
| -> inexact -> floating
| -> complex
-> character -> string _
| -> unicode_
-> bool _
-> object_

	np.issubdtype(obj.dtype, np.interger)
		通过issubdtype方法可以判断数组类型是否属于某一类型
	np.float64.mro()
		可以通过mro方法查看该类型的父类
	
C顺序和F顺序
	C顺序/行方向顺序,即C语言顺序
		首先遍历更高维度(在轴0上行进之前先在轴1上行进)
	F顺序/列方向顺序,即Fortran语言顺序
		首先遍历高低维度
	NumPy默认是C顺序,比如ravel()默认参数是C,如果ravel('F')就会返回F顺序的数据

数组的连接和分隔
	arr1,arr2都是(2,3)数组,那么np.concatenate([arr1,arr2], axis=0)就会连接成一个(4,3)数组, axis=1会连接成(2,6)数组
	arr是一个(5,2)数组,first, second, third = np.split(arr, [1,3]),会被分隔成3个数组,分隔位置就是1和3,first是一维,secode是1和2行的2维数组,third是2维
	
	所有连接分隔函数:
		concatenate, 通用连接函数
		vstack, row_stack, 按行堆叠,沿轴0
		hstack, 按列堆叠
		colum_stack, 类似hstack,但会先把一维数组转换为2维列向量
		dstack, 按深度堆叠数组,沿着轴2
		split, 沿指定轴分隔数组
		hsplit,vsplit,沿轴0和轴1分隔
	
	r_和c_堆叠助手:
		arr = np.arange(6)
		arr1 = arr.reshape((3,2))
		arr2 = np.random.randn((3,2))
		np.r_[arr1, arr2] #将返回一个(6,2)数组,类似vstack
		np.c_[np.r_[arr1,arr2], arr] #返回一个(6,3)数组,类似hstack 

数据重复
	repeat
		arr.repeat(2,axis=0),将arr所有元素重复2遍,并沿着0轴做扩展。如果arr是(2,2),重复后是(4,2)
		如果不指定axis,会被扁平化为一维数组
		arr.repeat([2,3], axis=0),如果arr是(2,2),重复后为(5,2),传入[2,3]数组分别指定第一行重复2次,第二行重复3次
		
	tile
		俗称瓷砖铺设,将原始数组理解成1个大瓷砖,然后重复这个瓷砖
		比如arr(2,2)
		np.tile(arr, 2),将变为(2,4),默认在列方向扩展
		np.tile(arr,(3,2)),将变为(6,4)
		tile和repeat区别是前者是将整个数组作为一个整体进行复制,而后者是对每个元素进行复制。所以后者重复的行或列会连续出现,而前者是间隔出现
	
神奇索引等价操作
	take
		take可以根据索引取对应轴的数据
		比如arr是(2,4),inds=[2,0,2,1]
		那么arr.take(inds, axis=1)就会得到(2,4)数组,4列分别是原数组的第2、0、2、1列
	
	put
		向数组赋值,put需要注意是不接受axis参数的,而是会做扁平化处理。
		比如arr.put(inds, [1,2,3,4])就会把inds里面索引的元素分别赋值为1、2、3、4.注意索引会做扁平化处理。默认按C顺序进行编号
		
广播机制
	广播需要慎重,仔细,容易出错
	广播规则:
		如果对于每个结尾维度(即从尾部开始的),轴长度都匹配,两个二维数组就是可以兼容广播的。之后,广播会在丢失的轴上进行。
		如果不是在轴0广播,而是其他轴上面广播,要求广播的轴维度为1。如果有多个轴为1,那么所有维度为1的轴都会广播。
	举例:
		arr是(4,3),那么arr.mean(0)是4,arr.mean(1)是3
		那么arr-arr.mean(0)就是(4,3)与3的运算,可以进行行方向的广播
		arr-arr.mean(1)就是(4,3)与4的运算,由于3和4不同,无法进行列方向的广播,这时进行arr.mean(1).reshape(4,1)变形,就是(4,3)与(4,1)运算,因为是1可以广播
	
	同理,多维数组也是可以广播的,比如(3,4,2)和(4,2)数组是可以沿着轴0广播。
	
    np.newaxis
		reshape可以加一个1维的轴。替代方案用np.newaxis插入一个新轴。
		arr如果是(3,4),变成(3,1,4)方法:arr[:,np.newaxis,:]
		其实np.newaxis就是None,直接用None其实也可以
	
	多维数组的广播
		arr是(2,3,4),和数组(2,1,4)进行运算时,会沿着1维的轴1进行广播。
		举例:求arr-轴2平均值
			arr - arr.mean(axis=2)[:,:,np.newaxis]
	
	举例:一个通用函数
		def demean_axis(arr, axis=0):
			indexer = [slice(None)] * arr.ndim   #slice(None)等同于[:],将切片扩展到多维[:,:,:]
			indexer[axis] = np.newaxis  #等同于[:,newaxis,:]
			return arr - arr.mean(axis)[indexer]
		
	通过数组索引完成广播赋值
		arr = np.zeros((4,3))
		arr[:] = 5  #arr所有元素将全部赋值为5
		
		col = np.array([1,2,3,4])
		arr[:] = col[:, np.newaxis] #col[:, np.newaxis]可以转为(4,1)数组, arr[:]索引全部列,最终arr所有3列的值相同都是1、2、3、4
		
		arr[:2] = [[8],[9]] # [[8],[9]]是一个(2,1)数组,arr的第一行全是8,第2行全是9
		
高阶ufunc用法
	在普通的ufunc运算后面可以再跟高阶的ufunc函数,比如np.add.reduce(arr)。
	reduce(x)
		聚合操作
		举例:
			arr=np.arange(10)
			np.add.reduce(arr)  #等同于arr.sum()就是求和
			
			np.logical_and.reduce(arr[:,:-1] < arr[:,1:], axis=1)
				等同于对每行求all方法。
	
	accumulate(x)
		累计聚合,两两相加
		举例:
			np.add.accumulate(np.arange(15).reshape((3,5)), axis=1) 会沿着轴1,对轴0做累计求和
	
	reduceat(x, bins)
		group by缩聚方法
		举例:
			np.add.reduceat(np.arange(10),[0,5,8])  #会对[0,5],[5,8],[8:10]分3组聚合
			也可以加axis参数
	
	outer(x,y)
		操作应用于x,y所有元素对,执行结果的维度是x和y的维度和,比如x和y是一维数组,那么运算完后就变成2维数组。
		举例:
			np.multiply.outer(np.arange(4),np.arange(5))
			得到一个(4,5)二维数组

	用python编写ufunc方法
		下面2个方法是用python编写ufunc方法,因为都是用python编写的,所以运行速度会很慢,比C语言的差可能1000倍
		numpy.frompyfunc
			举例:
				def add_element(x, y):
					return x + y
				add_them = np.frompyfunc(add_element, 2,1)  #2表示输入参数2个,1表示输出参数1个
				add_them(np.arange(8), np.arange(8)) #返回结果是一个object类型,而不是numpy类型对象
		
		numpy.vectorize
			这个可以指定返回值类型
			举例:
				add_them = np.vectorize(add_element, otypes=[np.float64]) #add_element是一个自定义python函数,otype是定义函数输出类型
				add_them(np.arange(8), np.arange(8))#返回float64类型
				

结构化
	numpy用的是同构数据,即所有数据类型都是dtype,同一类型。如果想表示异构或者表格数据也有方法。
	方法:
		使用(field_name, field_data_type)作为元组的列表传给构建数组时的dtype值
		dtype=[('x',np.float32),('y',np.int32)]
		arr=np.array([(1.5,6),(np.pi,-2)],dtype=dtype)
		arr将是一个一维数组,而且元素是2个。但是可以用arr['x']或者arr['x'][0]等方式来取值
	
	嵌套和多维字段
		dtype=[('x',np.int64,3),('y',np.int32)]
		arr=np.zeros(4,dtype=dtype)
		这样arr['x']或者arr[0]['x']等方式访问3个元素
		
		dtype=[('x', [('a', 'f8'), ('b', 'f4')]), ('y',np.int32)
		也可以这样嵌套定义
		
排序
	sort排序
		arr.sort()是原位排序,不形成新数组
		np.sort(arr)会形成新数组
		所有排序都是升序排序,如果要降序,可以用arr[:,::-1]方式获取
	
	间接排序
		argsort
			返回排序后的索引值
			np.array([5,0,1,3,2]).argsort()返回的是array([1,2,4,3,0])这个数组是索引,用arr[index]方式可以获取排序后的数组
			按第一行重新排序:
				arr[:,arr[0].argsort()] #arr[0].argsort()返回比如array([2, 1, 0, 4, 3], dtype=int64),这样类似arr[:,[2,1,0,4,3]],重新排列列
							
		numpy.lexsort
			和argsort类似,也是返回index。区别是numpy.lexsort可以完成多键排序
			举例:
				sorter = np.lexsort((first_name, last_name))
				注意,这里会先根据last_name进行排序,在有相同值时,会比较对应列的值大小,来决定最终排序。
				返回结果也是索引值,比如[1,2,3,0,4]
		
	稳定排序
		针对的是有相同元素的排序,当元素相同时,靠前的元素会排在前面
		举例:
			value.argsort(kind='mergesort')
		kind有3种可用排序选项:
			种类			速度		是否稳定	工作空间		最差情况
			'quicksort'		速度最快	不稳定		O				O(n^2)
			'mergesort'		速度中等	稳定		n/2				O(n log n)
			'heapsort'		速度低		不稳定 		O				O(n log n)
		
	分组排序
		numpy.partition和numpy.argpartition
		可用完成分段/分组排序,后者同argsort返回的是等价信息索引
		举例:
			np.partition(arr,3),会将arr分成2组,前面3个元素一组,后面的一组,其中前面3个是最小的3个元素。注意只是组间有排序,具体到组内元素是随机的不排序。
		
	在已排序数据中寻找插入位置
		numpy.searchsorted
			注意,必须是已经排序的数组
			举例:	
				arr.searchsorted([0,8,11,16])  #返回这4个值在arr数组中的插入位置索引
			可以用于分组:
				group=np.array([0,100,1000,5000,10000])
				group.searchsorted(data) #将data中元素归类到group中的区间
		
numba库
	http://numba.pydata
	建议好好研究下,该库使用LLVM将python代码编译成机器码,大大加快python执行速度
	举例1:
		from numba import vectorize
		
		@vectorize
		def nb_add(x, y):
			return x + y 
		
		x = np.arange(10)
		nb_add(x, x)
		nb_add.accumulate(x, 0)
	
	举例2:
		from numba import float64, njit
		@njit(float64(float64[:], float64[:]))
		def mean_distance(x, y):
			return (x - y).mean()
			
高阶数组的输入和输出
	内存映射文件mmap
		mmap = np.memmap('mymmap', dtype='float64', mode='w+', shape=(10000,10000))
		和打开文件类似,需要指定文件名、数据类型、打开模式、形状
		该文件会被映射到连续内存中,可以对其操作
		mmap.flush()  #将数据刷回到磁盘中
		
	

本文标签: 读书笔记 数据 python