《用python进行数据分析》学习笔记

本篇文章主要内容来源于《利用python进行数据分析》第二版,主要是对学习资料的整理与补充,若是有疑问,欢迎指出~

引入

bookface

  本篇文章来源于Wes Mckinney 的《Python for Data Analysis.2nd edition》,我看的是SeanCheney对该书的中文翻译本,链接在开头已给出。

  目前可提供的链接如下:

  第二版和第一版的不同之处在于:

  • 包括Python教程内的所有代码升级为Python 3.6(第1版使用的是Python 2.7)
  • 更新了Anaconda和其它包的Python安装方法
  • 更新了Pandas为2017最新版
  • 新增了一章,关于更高级的Pandas工具,外加一些tips
  • 简要介绍了使用StatsModels和scikit-learn

python的一些特点

python的优点如下:

  • 作为一种胶水语言
      Python成为成功的科学计算工具的部分原因是,它能够轻松地集成C、C++以及Fortran代码。大部分现代计算环境都利用了一些Fortran和C库来实现线性代数、优选、积分、快速傅里叶变换以及其他诸如此类的算法。许多企业和国家实验室也利用Python来“粘合”那些已经用了多年的遗留软件系统。

  • 拥有丰富的库资源
      在数据分析、交互式计算以及数据可视化方面,Python将不可避免地与其他开源和商业的领域特定编程语言/工具进行对比,如R、MATLAB、SAS、Stata等。近年来,由于Python的库(例如pandas和scikit-learn)不断改良,使其成为数据分析任务的一个优选方案。结合其在通用编程方面的强大实力,我们完全可以只使用Python这一种语言构建以数据为中心的应用。

python的缺点如下:

  • 运行速度比编译型语言(java,c等)慢
      由于Python是一种解释型编程语言,因此大部分Python代码都要比用编译型语言(比如Java和C)编写的代码运行慢得多。由于程序员的时间通常都比CPU时间值钱,因此许多人也愿意对此做一些取舍。但是,在那些延迟要求非常小或高资源利用率的应用中(例如高频交易系统),耗费时间使用诸如C++这样更低级、更低生产率的语言进行编程也是值得的。

  • 对高并发、多线程的应用程序支持较差
      对于高并发、多线程的应用程序而言(尤其是拥有许多计算密集型线程的应用程序),Python并不是一种理想的编程语言。这是因为Python有一个叫做全局解释器锁(Global Interpreter Lock,GIL)的组件,这是一种防止解释器同时执行多条Python字节码指令的机制。虽然很多大数据处理应用程序为了能在较短的时间内完成数据集的处理工作都需要运行在计算机集群上,但是仍然有一些情况需要用单进程多线程系统来解决。
      这并不是说Python不能执行真正的多线程并行代码。例如,Python的C插件使用原生的C或C++的多线程,可以并行运行而不被GIL影响,只要它们不频繁地与Python对象交互。

重要的python库

库名简介功能
NumPy引入惯例:import numpy as np
Numerical Python的简称,是Python科学计算的基础包
①快速高效的多维数组对象ndarray;
②用于对数组执行元素级计算以及直接对数组执行数学运算的函数;
③用于读写硬盘上基于数组的数据集的工具;
④线性代数运算、傅里叶变换,以及随机数生成;
⑤成熟的C API, 用于Python插件和原生C、C++、Fortran代码访问NumPy的数据结构和计算工具。
pandas引入惯例:import pandas as pd
兼具NumPy高性能的数组计算功能以及电子表格和关系型数据库(如SQL)灵活的数据处理能力。
①有标签轴的数据结构,支持自动或清晰的数据对齐。这可以防止由于数据不对齐,或处理来源不同的索引不同的数据,所造成的错误;
②集成时间序列功能;
③相同的数据结构用于处理时间序列数据和非时间序列数据;
④保存元数据的算术运算和压缩;
⑤灵活处理缺失数据;
⑥合并和其它流行数据库(例如基于SQL的数据库)的关系操作。
matplolib引入惯例:import matplotlib.pyplot as plt
是最流行的用于绘制图表和其它二维数据可视化的Python库。
直接调用库即可绘图,很方便
scipy是一组专门解决科学计算中各种标准问题域的包的集合。主要包括下面这些包:
①scipy.integrate:数值积分例程和微分方程求解器;
②scipy.linalg:扩展了由numpy.linalg提供的线性代数例程和矩阵分解功能;
③scipy.optimize:函数优化器(最小化器)以及根查找算法;
④scipy.signal:信号处理工具;
⑤scipy.sparse:稀疏矩阵和稀疏线性系统求解器;
⑥scipy.special:SPECFUN(这是一个实现了许多常用数学函数(如伽玛函数)的Fortran库)的包装器;
⑦scipy.stats:标准连续和离散概率分布(如密度函数、采样器、连续分布函数等)、各种统计检验方法,以及更好的描述统计法
scikit-learnPython的通用机器学习工具包,与pandas、statsmodels和IPython一起,scikit-learn对于Python成为高效数据科学编程语言起到了关键作用。它的子模块包括:
①分类:SVM、近邻、随机森林、逻辑回归等等;
②回归:Lasso、岭回归等等;
③聚类:k-均值、谱聚类等等;
④降维:PCA、特征选择、矩阵分解等等;
⑤选型:网格搜索、交叉验证、度量;
⑥预处理:特征提取、标准化。
statsmodels引入惯例:import statsmodels as sm
包含经典统计学和经济计量学的算法,是一个统计分析包。
包括如下子模块:
①回归模型:线性回归,广义线性模型,健壮线性模型,线性混合效应模型等等;
②方差分析(ANOVA);
③时间序列分析:AR,ARMA,ARIMA,VAR和其它模型;
④非参数方法:核密度估计,核回归;
⑤统计模型结果可视化。

python基础

  python基础的学习推荐廖雪峰的python教程(点击进入)。教程涵盖了python中常用的知识点,是作为快速入门教程的不错选择。里面的资料整理的很完整,在这一部分就不搬运了。
  ps:ipython很好用,基本包含了ide常用的功能,推荐!

NumPy基础:数组及矢量运算

概述

  NumPy(Numerical Python的简称)是Python数值计算最重要的基础包。大多数提供科学计算的包都是用NumPy的数组作为构建基础。
  NumPy本身并没有提供多么高级的数据分析功能,理解NumPy数组以及面向数组的计算将有助于你更加高效地使用诸如pandas之类的工具。我们需要注意的特点之一就是它可以高效处理大数组的数据,体现于:

  1. 数组占用的内存更少。
      因为NumPy是在一个连续的内存块中存储数据,独立于其他Python内置对象。NumPy的C语言编写的算法库可以操作内存,而不必进行类型检查或其它前期工作。比起Python的内置序列,NumPy数组使用的内存更少。

  2. 对数组的计算更方便。NumPy可以在整个数组上执行复杂的计算,而不需要Python的for循环

NumPy的ndarray:一种多维数组对象

  ndarray,即N维数组对象,该对象是一个快速灵活的大数据集容器。这种数组对整块数据的数学运算的语法跟标量元素之间的运算一样。下面是其的一个简单的使用示例:

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
#引入numpy
In [12]: import numpy as np

# 产生一些随机数
In [13]: data = np.random.randn(2, 3)
In [14]: data
Out[14]:
array([[-0.2047, 0.4789, -0.5194],
[-0.5557, 1.9658, 1.3934]])

#对数组进行一些简单的运算
In [15]: data * 10
Out[15]:
array([[ -2.0471, 4.7894, -5.1944],
[ -5.5573, 19.6578, 13.9341]])

In [16]: data + data
Out[16]:
array([[-0.4094, 0.9579, -1.0389],
[-1.1115, 3.9316, 2.7868]])

#查看数组的一些元属性
In [17]: data.shape
Out[17]: (2, 3)

In [18]: data.dtype
Out[18]: dtype('float64')

ps:书中提到的‘数组’,‘numpy数组’,‘ndarray’基本上都是指ndarray对象

创建ndarray

  1. array函数
      创建数组最简单的方法是使用array函数,它接受一切序列型的对象(包括其他数组),然后产生一个新的含有传入数据的numpy数组。
1
2
3
4
5
6
7
8
9
10
11
12
13
#使用array函数创建一维数组
In [19]: data1 = [6, 7.5, 8, 0, 1]
In [20]: arr1 = np.array(data1)
In [21]: arr1
Out[21]: array([ 6. , 7.5, 8. , 0. , 1. ])

#使用array函数创建二维数组
In [22]: data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]
In [23]: arr2 = np.array(data2)
In [24]: arr2
Out[24]:
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
  1. arange函数
      arange是Python内置函数range的数组版。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#使用arange函数创建一维数组
In [20]: arr1 = np.arange(10)
In [21]: arr1
Out[21]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

#使用array函数创建有一定规律一维数组
In [23]: arr2 = np.arange(2,6)
In [24]: arr2
Out[24]:
array([2,3,4,5])

In [25]: arr3 = np.arange(1,11,2)
In [26]: arr3
Out[26]:
array([1,3,5,7,9])
  1. zeros函数,ones函数和empty函数
      除np.array之外,还有一些函数也可以新建数组。比如,zeros和ones分别可以创建指定长度或形状的全0或全1数组。empty可以创建一个没有任何具体值的数组。要用这些方法创建多维数组,只需传入一个表示形状的元组即可:
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
#zeros函数
In [29]: np.zeros(10)
Out[29]: array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
In [30]: np.zeros((3, 6))
Out[30]:
array([[ 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0.]])

#empty函数(多数情况下,它返回的是一些未初始化的垃圾值)
In [31]: np.empty((2, 3, 2))
Out[31]:
array([[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]]])

#ones函数
In [32]: np.ones(10)
Out[32]: array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
In [33]: np.zeros((3, 6))
Out[33]:
array([[ 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1.]])

  下面列出了一些数组创建函数。由于NumPy关注的是数值计算,因此,如果没有特别指定,数据类型基本都是float64(浮点数)。

函数说明
array将输入数据(列表、元组、数组或其他序列类型)转换为ndarray。要么推断出dtype,要么指定dtype。默认直接复制输入数据
asarray将输入转换为ndarray,如果输入本身就是一个ndarray就不进行复制
arange类似于内置的range,但返回的是一个ndarray,而不是列表
ones,ones_like根据指定的形状和dtype创建一个全1的数组。ones_like以另一个数组为参数,并根据其形状和dtype创建一个全1数组
zeros,zeros_like类似于ones和ones_like,只不过产生的是全0数组而已
empty,empty_like创建新数组,只分配内存空间但不填充任何值
full,full_like用fill value 中的所有值,根据指定的形状和dtype创建一个数组。
eye,identity创建一个正方的N*N单位矩阵(对角线为1,其余为0)

ndarray的数据类型

  dtype(数据类型)是一个特殊的对象,它含有ndarray将一块内存解释为特定数据类型所需的信息。多数情况下,它们直接映射到相应的机器表示,这使得“读写磁盘上的二进制数据流”以及“集成低级语言代码(如C、Fortran)”等工作变得更加简单。数值型dtype的命名方式相同:一个类型名(如float或int),后面跟一个用于表示各元素位长的数字。标准的双精度浮点值(即Python中的float对象)需要占用8字节(即64位)。因此,该类型在NumPy中就记作float64。下面列出了numpy所支持的所有数据类型。

类型类型代码说明
int8、uint8i1、u1有符号和无符号的8位(1个字节)整型
int16、uint16i2、u2有符号和无符号的16位(2个字节)整型
int32、uint32i4、u4有符号和无符号的32位(4个字节)整型
int64、uint64i8、u8有符号和无符号的64位(8个字节)整型
float16f2半精度浮点数
float32f4或f标准的单精度浮点数。与C的float兼容
float64f8或d标准的双精度浮点数。与C的double和python的float对象兼容
float128f16或g扩展精度浮点数
complex64,complex128,complex256c8、c16、c32分别用两个32位、64位或128位浮点数表示的复数
bool?存储True和False值的布尔类型
objectOPython对象类型
stringS固定长度的字符串类型(每个字符一个字节)。例如,要创建一个长度为10的字符串,应使用S10
unicodeU固定长度的unicode类型(字节数由平台决定)。跟字符串的定义方式一样(如U10)

  操作dtype,python提供了以下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#改变数组的dtype
In [37]: arr = np.array([1, 2, 3, 4, 5])
In [38]: arr.dtype
Out[38]: dtype('int64')
In [39]: float_arr = arr.astype(np.float64)
In [40]: float_arr.dtype
Out[40]: dtype('float64')

#指定数组的dtype(将数字字符串转换为数字类型)
In [44]: numeric_strings = np.array(['1.25', '-9.6', '42'], dtype=np.string_)
In [45]: numeric_strings.astype(float)
Out[45]: array([ 1.25, -9.6 , 42. ])

#以字符串的形式指定dtype
In [49]: empty_uint32 = np.empty(8, dtype='u4')
In [50]: empty_uint32
Out[50]:
array([ 0, 1075314688, 0, 1075707904, 0,
1075838976, 0, 1072693248], dtype=uint32)

ndarray数组的基本操作

数组的运算与索引

数组的基本运算

  数组很重要,因为它使你不用编写循环即可对数据执行批量运算。NumPy用户称其为矢量化(vectorization)。具体的运算如下:

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
32
33
34
35
36
37
38
39
#大小相等的数组之间的任何算术运算都会将运算应用到元素级
In [51]: arr = np.array([[1., 2., 3.], [4., 5., 6.]])
In [52]: arr
Out[52]:
array([[ 1., 2., 3.],
[ 4., 5., 6.]])
In [53]: arr * arr
Out[53]:
array([[ 1., 4., 9.],
[ 16., 25., 36.]])
In [54]: arr - arr
Out[54]:
array([[ 0., 0., 0.],
[ 0., 0., 0.]])


#数组与标量的算术运算会将标量值传播到各个元素:
In [55]: 1 / arr
Out[55]:
array([[ 1. , 0.5 , 0.3333],
[ 0.25 , 0.2 , 0.1667]])
In [56]: arr ** 0.5
Out[56]:
array([[ 1. , 1.4142, 1.7321],
[ 2. , 2.2361, 2.4495]])

#大小相同的数组之间的比较会生成布尔值数组:
In [57]: arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])
In [58]: arr2
Out[58]:
array([[ 0., 4., 1.],
[ 7., 2., 12.]])

In [59]: arr2 > arr
Out[59]:
array([[False, True, False],
[ True, False, True]], dtype=bool)

#不同大小的数组之间的运算叫做广播(broadcasting),在这里暂时不深入探讨

索引

  和python的list操作相似,numpy对ndarray提供了索引和切片的支持,并且拥有更强的可操作性。其提供的不仅仅是对一维数组对索引操作,对于二维、三维甚至是多维都适用。总的来说,可以分为批量的索引(切片)和离散的索引两个部分来说明:
  切片的基本操作可以从以下代码看出:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
##切片示例##

##对一维数组的操作
#创建一个一维数组
In [60]: arr = np.arange(10)
In [61]: arr
Out[61]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

#对数组进行切片
In [62]: arr[5]
Out[62]: 5
In [63]: arr[5:8]
Out[63]: array([5, 6, 7])

#可以将切片赋值给另一个变量(类型也是一个数组),并进行操作
In [64]: arr_slice = arr[5:8]
In [65]: arr_slice = 12
In [66]: arr_slice
Out[66]: array([12, 12, 12])
In [67]: arr
Out[67]: array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])

##对二维数组的操作
#创建一个二维数组
In [72]: arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

#对数组进行索引
In [73]: arr2d[2]
Out[73]: array([7, 8, 9])

#对于子元素的索引,下面两种方式是等价的
In [74]: arr2d[0][2]
Out[74]: 3
In [75]: arr2d[0, 2]
Out[75]: 3

#对数组进行切片
In [76]: arr2d[:2] #对其中一维进行切片
Out[76]:
array([[1, 2, 3],
[4, 5, 6]])
In [77]: arr2d[:2, 1:] #对两个维度进行切片
Out[77]:
array([[2, 3],
[5, 6]])

#对切片进行赋值也会扩散到整个选区
In [78]: arr2d[:2, 1:] = 0
In [79]: arr2d
Out[79]:
array([[1, 0, 0],
[4, 0, 0],
[7, 8, 9]])

#######################################
##对于更高维数组的操作,和以上的操作类似##
#######################################

  对二维数组的切片选区,如下图所示:
二维数组切片

注:在上面所有这些选取数组子集的例子中,返回的数组都是视图。

  对数组进行离散的索引可以从以下代码看出:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
##离散的索引示例##

##使用布尔数组索引
#产生一个布尔数组

In [98]: names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
In [99]: names
Out[99]:
array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'],
dtype='<U4')
In [100]: names == 'Bob'
Out[100]:
array([ True, False, False, True, False, False, False],
dtype=bool)

#使用布尔数组索引
In [101]: data = np.random.randn(7, 4)
In [102]: data
Out[101]:
array([[ 0.0929, 0.2817, 0.769 , 1.2464],
[ 1.0072, -1.2962, 0.275 , 0.2289],
[ 1.3529, 0.8864, -2.0016, -0.3718],
[ 1.669 , -0.4386, -0.5397, 0.477 ],
[ 3.2489, -1.0212, -0.5771, 0.1241],
[ 0.3026, 0.5238, 0.0009, 1.3438],
[-0.7135, -0.8312, -2.3702, -1.8608]])
In [102]: data[names == 'Bob'] #注:布尔型数组的长度必须跟被索引的轴长度一致。
Out[102]:
array([[ 0.0929, 0.2817, 0.769 , 1.2464],
[ 1.669 , -0.4386, -0.5397, 0.477 ]])

#布尔数组的一些常用操作
In [103]: data[names == 'Bob'] #使用‘==’,‘<’,'>'等
Out[103]:
array([[ 0.0929, 0.2817, 0.769 , 1.2464],
[ 1.669 , -0.4386, -0.5397, 0.477 ]])

In [106]: names != 'Bob' #使用'!=' 、'~'
Out[106]:
array([False, True, True, False, True, True, True],
dtype=bool)
In [107]: data[~(names == 'Bob')]
Out[107]:
array([[ 1.0072, -1.2962, 0.275 , 0.2289],
[ 1.3529, 0.8864, -2.0016, -0.3718],
[ 3.2489, -1.0212, -0.5771, 0.1241],
[ 0.3026, 0.5238, 0.0009, 1.3438],
[-0.7135, -0.8312, -2.3702, -1.8608]])

In [110]: mask = (names == 'Bob') | (names == 'Will') #使用逻辑运算符‘|、&’等
In [111]: mask
Out[111]:
array([ True, False, True, True, True, False, False],
dtype=bool)
In [112]: data[mask]
Out[112]:
array([[ 0.0929, 0.2817, 0.769 , 1.2464],
[ 1.3529, 0.8864, -2.0016, -0.3718],
[ 1.669 , -0.4386, -0.5397, 0.477 ],
[ 3.2489, -1.0212, -0.5771, 0.1241]])

##花式索引##
#花式索引(Fancy indexing)是一个NumPy术语,它指的是利用整数数组进行索引

#定义一个数组
In [117]: arr = np.empty((8, 4))
In [118]: for i in range(8):
.....: arr[i] = i
In [119]: arr
Out[119]:
array([[ 0., 0., 0., 0.],
[ 1., 1., 1., 1.],
[ 2., 2., 2., 2.],
[ 3., 3., 3., 3.],
[ 4., 4., 4., 4.],
[ 5., 5., 5., 5.],
[ 6., 6., 6., 6.],
[ 7., 7., 7., 7.]])

#以特定顺序选取行子集
In [120]: arr[[4, 3, 0, 6]]
Out[120]:
array([[ 4., 4., 4., 4.],
[ 3., 3., 3., 3.],
[ 0., 0., 0., 0.],
[ 6., 6., 6., 6.]])
In [121]: arr[[-3, -5, -7]] #使用负数索引将会从末尾开始选取行
Out[121]:
array([[ 5., 5., 5., 5.],
[ 3., 3., 3., 3.],
[ 1., 1., 1., 1.]])

#一次传入多个索引数组时,取对应列的单个元素
In [123]: arr
Out[123]:
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, 5, 7, 2], [0, 3, 1, 2]]
Out[124]:
array([ 4, 23, 29, 10])

#####################################################
##注:花式索引跟切片不一样,它总是将数据复制到新数组中。##
#####################################################

利用数组进行数据处理

数组转置和轴对换

  对数组元素位置的操作,最基本的就是重塑函数reshape。

1
2
3
4
5
6
7
#使用reshape函数重塑数组
In [126]: arr = np.arange(15).reshape((3, 5))
In [127]: arr
Out[127]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])

  然后就是数组转置和轴对换

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
##数组转置的使用
In [126]: arr = np.arange(15).reshape((3, 5))
In [127]: arr
Out[127]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
In [128]: arr.T
Out[128]:
array([[ 0, 5, 10],
[ 1, 6, 11],
[ 2, 7, 12],
[ 3, 8, 13],
[ 4, 9, 14]])

##轴对换的使用
#transpose函数
#这里,第一个轴被换成了第二个,第二个轴被换成了第一个,最后一个轴不变。
In [132]: arr = np.arange(16).reshape((2, 2, 4))
In [133]: arr
Out[133]:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
In [134]: arr.transpose((1, 0, 2))
Out[134]:
array([[[ 0, 1, 2, 3],
[ 8, 9, 10, 11]],
[[ 4, 5, 6, 7],
[12, 13, 14, 15]]])

#swapaxes函数(交换两个轴)
In [135]: arr
Out[135]:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
In [136]: arr.swapaxes(1, 2)
Out[136]:
array([[[ 0, 4],
[ 1, 5],
[ 2, 6],
[ 3, 7]],
[[ 8, 12],
[ 9, 13],
[10, 14],
[11, 15]]])

注:在这里,返回的都是源数据的视图(不会进行任何复制操作)

快速的元素级数组函数:通用函数

  通用函数(即ufunc)是一种对ndarray中的数据执行元素级运算的函数。你可以将其看做简单函数(接受一个或多个标量值,并产生一个或多个标量值)的矢量化包装器。许多ufunc都是简单的元素级变体,如sqrt和exp:

  其使用方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
In [137]: arr = np.arange(10)
In [138]: arr
Out[138]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [139]: np.sqrt(arr)
Out[139]:
array([ 0. , 1. , 1.4142, 1.7321, 2. , 2.2361, 2.4495,
2.6458, 2.8284, 3. ])

In [140]: np.exp(arr)
Out[140]:
array([ 1. , 2.7183, 7.3891, 20.0855, 54.5982,
148.4132, 403.4288, 1096.6332, 2980.958 , 8103.0839])

下面是一些常见的ufunc,都可以通过类似以上的方法操作数组元素

函数说明
abs、fabs计算整数、浮点数或复数的绝对值。对于非复数值,可以使用更快的fabs
sqrt计算各元素的平方根。相当于arr**5
square计算各元素的平方。相当于arr**2
exp计算各元素的指数
log,log10,log2,log1p分别为底数为e、10、2、(1+x)的log
sign计算各元素的正负号:1(正数)、0(零)、-1(负数)
ceil计算各元素的ceiling值,即大于等于该值的最小整数
floor计算各元素的floor值,即小于等于该值的最大整数
rint将各元素值四舍五入到最接近的整数,保留dtype
modf将数组的小数和正数部分以两个独立数组的形式返回
isnan返回一个表示“哪些值是NaN(这不是一个数字)”的布尔型数组
isfinite,isinf分别返回一个表示“是否有穷(非inf,非NaN)”或“是否是无穷”的布尔型数组
cos,cosh,sin,sinh,tan,tanh普通型和双曲型三角函数
arccos,arccosh,arcsin,arcsinh,
arctan,arctanh
反三角函数
logical_not计算各元素 not x 的真值。相当于 -arr
add将数组中对应的元素相加
subtract从第一个数组中减去第二个数组中的元素
multiply数组元素相乘
divide,floor_divide除法或向下圆整除法(丢弃余数)
power对第一个数组中的元素A,第二个数组中对应的元素B,计算
maximun,fmax元素级的最大值计算。fmax将忽略NaN
minimum,fmin元素级的最小值计算。fmin将忽略NaN
mod元素级的求模计算(除法的余数)
copysign将第二个数组中的值的符号复制给第一个数组中的值
greater,greater_equal,less,less_equal,
equal,not_equal
执行元素级的比较运算,最终产生布尔型数组。相当于>,>=,<,<=,==,!=
logical_and,logical_or,logical_xor执行元素级的真值逻辑运算,相当于&,|,^

  NumPy数组使你可以将许多种数据处理任务表述为简洁的数组表达式(否则需要编写循环)。用数组表达式代替循环的做法,通常被称为矢量化。一般来说,矢量化数组运算要比等价的纯Python方式快上一两个数量级(甚至更多),尤其是各种数值计算。下面将其分为简单的几类:

  • 数值类api
函数名说明
sum对数组中的全部或某轴向的元素求和,零长度的数组的sum为0
mean算术平均数。零长度的数组的mean为Nan
std,var分别为标准差和方差,自由度默认为n
min,max最大值和最小值
argmin,argmax分别为最大元素和最小元素的索引
cumsum所有元素的累计和
cumprod所有元素的累计积
  • 元素操作类api
函数名说明
where传入三个参数A,B,C,返回一个数组。若A真返回B中的元素,否则返回C中的元素
any若数组中全为false或全为0或数组为空,返回False,否则返回true
all数组中全为true才返回True
sort对数组的任意一个轴进行排序,默认为升序
  • 集合操作类api
函数名说明
unique(x)计算x中的唯一元素,并返回有序结果
intersect1d(x,y)计算x和y中的公共元素,并返回有序结果
union1d(x,y)计算并集,并返回有序结果
in1d(x,y)得到一个表示“x的元素是否包含于y”的布尔型数组
setdiff1d(x,y)集合的差,即元素在x中且不在y中
setxor1d(x,y)集合的对称差,即不同时存在于两个数组中的元素的集合

数组文件的输入输出

  NumPy能够读写磁盘上的文本数据或二进制数据。这一小节只讨论NumPy的内置二进制格式,因为更多的用户会使用pandas或其它工具加载文本或表格数据.其使用如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
In [213]: arr = np.arange(10)
# 单个数组的保存与读取
In [214]: np.save('some_array', arr)
In [215]: np.load('some_array.npy')
Out[215]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

#多个数组的保存与读取
In [216]: np.savez('array_archive.npz', a=arr, b=arr)
In [217]: arch = np.load('array_archive.npz')
In [218]: arch['b']
Out[218]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# 保存并压缩多个数组
In [219]: np.savez_compressed('arrays_compressed.npz', a=arr, b=arr)

线性代数

  线性代数(如矩阵乘法、矩阵分解、行列式以及其他方阵数学等)是任何数组库的重要组成部分。不像某些语言(如MATLAB),通过对两个二维数组相乘得到的是一个元素级的积,而不是一个矩阵点积。因此,NumPy提供了一个用于矩阵乘法的dot函数(既是一个数组方法也是numpy命名空间中的一个函数):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
In [223]: x = np.array([[1., 2., 3.], [4., 5., 6.]])

In [224]: y = np.array([[6., 23.], [-1, 7], [8, 9]])

In [225]: x
Out[225]:
array([[ 1., 2., 3.],
[ 4., 5., 6.]])

In [226]: y
Out[226]:
array([[ 6., 23.],
[ -1., 7.],
[ 8., 9.]])

In [227]: x.dot(y)
Out[227]:
array([[ 28., 64.],
[ 67., 181.]])

# PS:x.dot(y)等价于np.dot(x, y)

  同时,numpy的linalg库提供了线性代数函数的支持

函数说明
diag一以为数组的形式返回方阵的对角线(或非对角线)元素,或将一维数组转换为方阵(非对角线元素为0)
dot矩阵乘法
trace计算对角线元素的和
det计算矩阵行列式
eig计算方阵的本征值和本征向量
inv计算方阵的逆
pinv计算矩阵的Moore-Penrose伪逆
qr计算QR分解
svd计算奇异值分解(SVD)
solve解线性方程组Ax = b,其中A为一个方阵
lstsq计算Ax=b的最小二乘解

伪随机数生成

  numpy.random模块对Python内置的random进行了补充,增加了一些用于高效生成多种概率分布的样本值的函数。

函数说明
seed确定随机数生成器的种子
permutation返回一个序列的随机排列或返回一个随机排列的范围
shuffle对一个序列就地随机排列
rand产生均匀分布的样本值
randint从给定的上下范围内随机选取整数
randn产生标准正态分布(平均值为0,标准差为1)的样本值
binomial产生二项分布的样本值
normal产生正态(高斯)分布的样本值
beta产生Beta分布的样本值
chisquare产生卡方分布的样本值
gamma产生Gamma分布的样本值
uniform产生在[0,1)中均匀分布的样本值

pandas 入门

pass

数据加载、存储与文件格式

  数据分析的第一步是访问数据,这一章主要介绍pandas的数据输入与输出。输入输出通常可以划分为几个大类:读取文本文件和其他更高效的磁盘存储格式,加载数据库中的数据,利用WEB API操作网络资源。

文本格式数据的读写

  pandas提供了一些将表格型数据读取为DataFrame对象的函数,下面是一些常用的函数:

函数说明
read_csv从文件、URL、文件型对象中加载带分隔符的数据。默认分隔符为逗号
read_table从文件、URL、文件型对象中加载带分隔符的数据。默认分隔符为制表符(‘\t’)
read_fwf读取定宽列格式数据(也就是说,没有分隔符)
read_clipboard读取剪贴板中的数据,可以看做read_table的剪贴板版,在将网页转换为表格时很有用
read_excel从Excel XLS 或XLSX file 读取表格数据
read_hdf读取pandas写的HDF5文件
read_html读取HTML文档中的所有表格
read_json读取JSON字符串中的数据
read_msgpack二进制格式编码的pandas数据
read_pickle读取Python pickle格式中存储的任意对象
read_sas读取存储于SAS系统自定义存储格式的SAS数据集
read_sql(使用SQLAlchemy)读取SQL查询结果为pandas的DataFrame
read_stata读取Stata文件格式的数据集
read_feather读取Feather二进制文件格式

&emsp 以上函数中可配置的参数有很多,大体可分为以下几类:

  • 索引:将一个或多个列当做返回的DataFrame处理,以及是否从文件、用户获取列名。
  • 类型推断和数据转换:包括用户定义值的转换、和自定义的缺失值标记列表等。
  • 日期解析:包括组合功能,比如将分散在多个列中的日期时间信息组合成结果中的单个列。
  • 迭代:支持对大文件进行逐块迭代。
  • 不规整数据问题:跳过一些行、页脚、注释或其他一些不重要的东西(比如由成千上万个逗号隔开的数值数据)。

    &emsp 通过代码我们可以看到一些常用的用法。

1
2


大体上来讲,read_csv`read_table`函数的参数有:

参数名说明
path表示文件系统位置、URL、文件型对象的字符串

逐块读取文本文件

To be continue….

感谢你的阅读!