本书主要讲解数据分析的关键项目:NumPy、matplotlib和pandas。
对于高并发、多线程的应用程序而言(尤其是拥有许多计算密集型线程的应用程序),Python并不是一种理想的编程语言。这是因为Python有一个叫做全局解释器锁(Global Interpreter Lock,GIL)的东西,这是一种防止解释器同时执行多条Python字节码指令的机制。
pandas兼具NumPy高性能的数组计算功能以及电子表格和关系型数据库(如SQL)灵活的数据处理功能。对于金融行业的用户,pandas提供了大量适用于金融数据的高性能时间序列功能和工具。
对于使用R语言进行统计计算的用户,肯定不会对DataFrame这个名字感到陌生,因为它源自于R的data.frame对象。
第3章 IPython:一种交互式计算和开发环境
jupyter的tab键可以补全函数名等,还能补全文件路径(显示文件系统下的内容)。
shift+enter 执行命令。
尾部加问号,可以起到help的作用,如 pandas.read_sql_query?
尾部加两个问号,可以查看源代码,如 pandas.read_sql_query?
联合使用*和问号,对库检索功能,如pandas.*d_*?
基本性能分析:%prun和%run -p
第4章 NumPy基础:数组和矢量计算
NumPy(Numerical Python的简称)是Python科学计算的基础包,它是本书所介绍的几乎所有高级工具的构建基础。对于数值型数据,NumPy数组在存储和处理数据时要比内置的Python数据结构高效得多。
NumPy本身并没有提供多么高级的数据分析功能,理解NumPy数组以及面向数组的计算将有助于你更加高效地使用诸如pandas之类的工具。
NumPy最重要的一个特点就是其N维数组对象(即ndarray),该对象是一个快速而灵活的大数据集容器。
arange是Python内置函数range的数组版
NumPy数组使你可以将许多种数据处理任务表述为简洁的数组表达式(否则需要编写循环)。用数组表达式代替循环的做法,通常被称为矢量化。一般来说,矢量化数组运算要比等价的纯Python方式快上一两个数量级(甚至更多),尤其是各种数值计算。
可以通过数组上的一组数学函数对整个数组或某个轴向的数据进行统计计算。sum、平均数mean以及标准差std等聚合计算(aggregation,通常叫做约简(reduction))既可以当做数组的实例方法调用,也可以当做顶级NumPy函数使用
用np.loadtxt或更为专门化的np.genfromtxt将数据加载到普通的NumPy数组中。这些函数都有许多选项可供使用:指定各种分隔符、针对特定列的转换器函数、需要跳过的行数等。
第5章 pandas入门
pandas是基于NumPy构建的,让以NumPy为中心的应用变得更加简单。
pandas引入约定:
In [1]: from pandas import Series, DataFrame
In [2]: import pandas as pd
你首先就得熟悉它的两个主要数据结构:Series和DataFrame。
Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。仅由一组数据即可产生最简单的Series:
In [4]: obj = Series([4, 7, -5, 3])
In [5]: obj
Out[5]:
0 4
1 7
2 -5
3 3
DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共用同一个索引)。跟其他类似的数据结构相比(如R的data.frame),DataFrame中面向行和面向列的操作基本上是平衡的。其实,DataFrame中的数据是以一个或多个二维块存放的(而不是列表、字典或别的一维数据结构)。
构建DataFrame的办法有很多,最常用的一种是直接传入一个由等长列表或NumPy数组组成的字典。
指定列显示顺序
In [39]: DataFrame(data, columns=['year', 'state', 'pop'])
指定索引名称
In [40]: frame2 = DataFrame(data, columns=['year', 'state', 'pop', 'debt'],index=['one', 'two', 'three', 'four', 'five'])
读取列数据:返回的Series拥有原DataFrame相同的索引,且其name属性也已经被相应地设置好了。
In [43]: frame2['state']
In [43]: frame2['state','year']
In [44]: frame2.year
读取表头
In [44]: frame2.columns
读索引
In [44]: frame2.index
读取行:ix已经被loc和iloc替代,loc可以使用数字索引和标签索引,iloc只能使用数字索引
links.iloc[[6,9,2,1]]
links.loc[[6,9,2,1]]
frame2.loc[['four','two']]
删除列
In [55]: del frame2['eastern']
Index对象是不可修改的(immutable),但可以有很多其他操作,如计算交集、并集、差集、append等
Series删除行
In [94]: obj = Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])
In [95]: new_obj = obj.drop('c')
In [97]: obj.drop(['d', 'c'])
DataFrame删除行或列
In [99]: data.drop(['Colorado', 'Ohio'])
In [100]: data.drop('two', axis=1)
[101]: data.drop(['two', 'four'], axis=1)
筛选行:列three上的值大于5的行
In [117]: data[data['three'] > 5]
同时筛选行和列:前边的list是行索引,后边的list是列名
frame2.loc[['four','two'],['year','pop']]
元素级的Python函数也是可以用的。
In [167]: frame.applymap(format)
根据索引排序
In [172]: frame.sort_index()
In [173]: frame.sort_index(axis=1)
In [174]: frame.sort_index(axis=1, ascending=False)
最常用的,类似数据表,按某一列进行排序
In [181]: frame.sort_index(by='b')
In [182]: frame.sort_index(by=['a', 'b'])
调用DataFrame的sum方法将会返回一个含有列或行小计的Series,NA值会自动被排除
In [200]: df.sum()
In [201]: df.sum(axis=1)
有些方法(如idxmin和idxmax)返回的是间接统计(比如达到最小值或最大值的索引)
In [203]: df.idxmax()
一次性产生多个汇总统计
In [205]: df.describe()
得到Series中的唯一值数组
In [218]: uniques = obj.unique()
value_counts用于计算一个Series中各值出现的频率
In [220]: obj.value_counts()
value_counts还是一个顶级pandas方法,可用于任何数组或序列
In [221]: pd.value_counts(obj.values, sort=False)
pandas使用浮点值NaN(Not a Number)表示浮点和非浮点数组中的缺失数据。它只是一个便于被检测出来的标记而已。
对于DataFrame对象,事情就有点复杂了。你可能希望丢弃全NA或含有NA的行或列。dropna默认丢弃任何含有缺失值的行
In [239]: cleaned = data.dropna()
传入how='all'将只丢弃全为NA的那些行或列
In [242]: data.dropna(how='all')
In [245]: data.dropna(axis=1, how='all')
通过一个常数调用fillna就会将缺失值替换为那个常数值
In [250]: df.fillna(0)
通过一个字典调用fillna,就可以实现对不同的列填充不同的值:
In [251]: df.fillna()
层次化索引(hierarchical indexing)是pandas的一项重要功能,它使你能在一个轴上拥有多个(两个以上)索引级别。
第6章 数据加载、存储与文件格式
用正则表达式\s+表示数量不等的空格分隔符
In [859]: result = pd.read_table('ch06/ex3.txt', sep='\s+')
跳过特定行
In [862]: pd.read_csv('ch06/ex4.csv', skiprows=[0, 2, 3])
在处理很大的文件时,或找出大文件中的参数集以便于后续处理时,你可能只想读取文件的一小部分或逐块对文件进行迭代。
逐块读取文件,需要设置chunksize(行数)
In [874]: chunker = pd.read_csv('ch06/ex6.csv', chunksize=1000)
将数据写出到文本格式
In [880]: data.to_csv('ch06/out.csv')
In [885]: data.to_csv(sys.stdout, index=False, cols=['a', 'b', 'c'])
pandas的ExcelFile类支持读取存储在Excel 2003(或更高版本)中的表格型数据。由于ExcelFile用到了xlrd和openpyxl包。
In [962]: sql.read_sql('select * from test', con)
使用read_sql可以替代read_sql_table和read_sql_query(官方文档有说明)
第7章 数据规整化:清理、转换、合并、重塑
pandas.merge可根据一个或多个键将不同DataFrame中的行连接起来。SQL或其他关系型数据库的用户对此应该会比较熟悉,因为它实现的就是数据库的连接操作。
pandas.concat可以沿着一条轴将多个对象堆叠到一起。
两个数据集的连接键同名时
In [20]: pd.merge(df1, df2, on='key')
两个数据集的连接键不同名时
In [23]: pd.merge(df3, df4, left_on='lkey', right_on='rkey')
默认情况下,merge做的是"inner"连接;结果中的键是交集。其他方式还有"left"、"right"以及"outer"。外连接求取的是键的并集,组合了左连接和右连接的效果
In [24]: pd.merge(df1, df2, how='outer')
merge有一个更实用的suffixes选项,用于指定附加到左右两个DataFrame对象的重叠列名上的字符串
In [35]: pd.merge(left, right, on='key1', suffixes=('_left', '_right'))
轴向连接:另一种数据合并运算也被称作连接(concatenation)、绑定(binding)或堆叠(stacking)。默认情况下,concat是在axis=0上工作的,最终产生一个新的Series。
In [64]: pd.concat([s1, s2, s3])
轴向旋转(pivot)
移除了重复行
In [129]: data.drop_duplicates()
以上这两个方法默认会判断全部列,你也可以指定部分列进行重复项判断
In [131]: data.drop_duplicates(['k1'])
对不同的值进行不同的替换
In [143]: data.replace([-999, -1000], [np.nan, 0])
为了便于分析,连续数据常常被离散化或拆分为“面元”(bin)。如将年龄数据划分为“18到25”、“26到35”、“35到60”以及“60以上”几个面元。
In [153]: ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
In [154]: bins = [18, 25, 35, 60, 100]
In [155]: cats = pd.cut(ages, bins)
Series有一些能够跳过NA值的字符串操作方法。通过Series的str属性即可访问这些方法。
第9章 数据聚合与分组运算
pandas提供了一个灵活高效的gruopby功能,它使你能以一种自然的方式对数据集进行切片、切块、摘要等操作。像SQL这样的查询语言所能执行的分组运算的种类很有限。由于Python和pandas强大的表达能力,我们可以执行复杂得多的分组运算。
第10章 时间序列
pandas提供了一组标准的时间序列处理工具和数据算法。因此,你可以高效处理非常大的时间序列,轻松地进行切片/切块、聚合、对定期/不定期的时间序列进行重采样等。
重采样(resampling)指的是将时间序列从一个频率转换到另一个频率的处理过程。将高频率数据聚合到低频率称为降采样(downsampling),而将低频率数据转换到高频率则称为升采(upsampling)。并不是所有的重采样都能被划分到这两个大类中。例如,将W-WED(每周三)转换为W-FRI既不是降采样也不是升采样。
第9、10章有时间还要重读
领取专属 10元无门槛券
私享最新 技术干货