将Series和DataFrame引入本地命名空间。
ipython --pylab In [1]: from pandas import Series, DataFrame In [2]: import pandas as pd
pandas的数据结构介绍
两个主要数据结构:Series和DataFrame。
Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。仅由一组数据即可产生最简单的Series。
In [3]: obj = Series([4, 7, -5, 3]) In [4]: obj Out[4]: 0 4 1 7 2 -5 3 3 dtype: int64
Series的字符串表现形式为:索引在左边,值在右边。由于我们没有为数据指定索引,于是会自动创建一个0到N-1(N为数据的长度)的整数型索引。可以通过Series的values和index属性获取其数组表示形式和索引对象。
In [5]: obj.values Out[5]: array([ 4, 7, -5, 3], dtype=int64) In [6]: obj.index Out[6]: RangeIndex(start=0, stop=4, step=1)
通常,我们希望所创建的Series带有一个可以对各个数据点进行标记的索引。
In [7]: obj2 = Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c']) In [8]: obj2 Out[8]: d 4 b 7 a -5 c 3 dtype: int64 In [9]: obj2.index Out[9]: Index([u'd', u'b', u'a', u'c'], dtype='object')
与普通NumPy数组相比,可以通过索引的方式选取Series中的单个或一组值。
In [10]: obj2['a'] Out[10]: -5 In [11]: obj2['d'] = 6 In [12]: obj2[['c', 'a', 'd']] Out[12]: c 3 a -5 d 6 dtype: int64
NumPy数组运算(如:根据布尔型数组进行过滤、标量乘法、应用数学函数等)都会保留索引和值之间的链接。
In [13]: obj2 Out[13]: d 6 b 7 a -5 c 3 dtype: int64 In [14]: obj2[obj2 > 0] Out[14]: d 6 b 7 c 3 dtype: int64 In [15]: obj2 * 2 Out[15]: d 12 b 14 a -10 c 6 dtype: int64 In [16]: np.exp(obj2) Out[16]: d 403.428793 b 1096.633158 a 0.006738 c 20.085537 dtype: float64
还可以将Series看成是一个定长的有序字典,因为它是索引值到数据值的一个映射。它可以用在许多原本需要字典参数的函数中。
In [17]: 'b' in obj2 Out[17]: True In [18]: 'e' in obj2 Out[18]: False
如果数据被存放在一个Python字典中,也可以直接通过这个字典来创建Series。
In [19]: sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000} In [20]: obj3 = Series(sdata) In [21]: obj3 Out[21]: Ohio 35000 Oregon 16000 Texas 71000 Utah 5000 dtype: int64
如果只传入一个字典,则结果Series中的索引就是原字典的键(有序排列)。
In [22]: states = ['California', 'Ohio', 'Oregon', 'Texas'] In [23]: obj4 = Series(sdata, index=states) In [24]: obj4 Out[24]: California NaN Ohio 35000.0 Oregon 16000.0 Texas 71000.0 dtype: float64
在这个例子中,sdata中跟states索引相匹配的那3个值会被找出来并放到相应的位置上,但由于"California"所对应的sdata值找不到,所以其结果九尾NaN(即“非数字”,not a number),在pandas中,用于表示缺失或NA值。pandas的isnull和notnull函数可用于检测缺失数据。
In [25]: pd.isnull(obj4) Out[25]: California True Ohio False Oregon False Texas False dtype: bool In [26]: pd.notnull(obj4) Out[26]: California False Ohio True Oregon True Texas True dtype: bool
Series也有类似的实例方法。
In [27]: obj4.isnull() Out[27]: California True Ohio False Oregon False Texas False
对于许多应用而言,Series最重要的一个功能是:它在算术运算中会自动对齐不同索引的数据。
In [28]: obj3 Out[28]: Ohio 35000 Oregon 16000 Texas 71000 Utah 5000 dtype: int64 In [29]: obj4 Out[29]: California NaN Ohio 35000.0 Oregon 16000.0 Texas 71000.0 dtype: float64 In [30]: obj3 + obj4 Out[30]: California NaN Ohio 70000.0 Oregon 32000.0 Texas 142000.0 Utah NaN dtype: float64
Series对象本身及其索引都有一个name属性,该属性跟pandas其它的关键功能关系非常密切。
In [31]: obj4.name = 'population' In [32]: obj4.index.name = 'state' In [33]: obj4 Out[33]: state California NaN Ohio 35000.0 Oregon 16000.0 Texas 71000.0 Name: population, dtype: float64
Series的索引可以通过赋值的方式就地修改。
In [34]: obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan'] In [35]: obj Out[35]: Bob 4 Steve 7 Jeff -5 Ryan 3 dtype: int64
DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以使不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共用同一个索引)。跟其他类型的数据结构相比(如:R的data.frame),DataFrame中面向行和面向列的操作基本上是平衡的。其实,DataFrame中的数据是以一个或多个二维块存放的(而不是列表、字典或别的一维数据结构)。
构建DataFrame的办法有很多,最常用的一种是直接传入一个由等长列表或NumPy数组组成的字典。
In [36]: data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], ....: 'year': [2000, 2001, 2002, 2001, 2002], ....: 'pop': [1.5, 1.7, 3.6, 2.4, 2.9]} In [37]: frame = DataFrame(data)
结果DataFrame会自动加上索引(跟Series一样),且全部列会被有序排列。
In [38]: frame Out[38]: pop state year 0 1.5 Ohio 2000 1 1.7 Ohio 2001 2 3.6 Ohio 2002 3 2.4 Nevada 2001 4 2.9 Nevada 2002
如果指定了列序列,则DataFrame的列就会按照指定顺序进行排列。
In [39]: DataFrame(data, columns=['year', 'state', 'pop']) Out[39]: year state pop 0 2000 Ohio 1.5 1 2001 Ohio 1.7 2 2002 Ohio 3.6 3 2001 Nevada 2.4 4 2002 Nevada 2.9
跟Series一样,如果传入的列在数据中找不到,就会产生NA值。
In [40]: frame2 = DataFrame(data, columns=['year', 'state', 'pop', 'debt'], ....: index=['one', 'two', 'three', 'four', 'five']) In [41]: frame2 Out[41]: year state pop debt one 2000 Ohio 1.5 NaN two 2001 Ohio 1.7 NaN three 2002 Ohio 3.6 NaN four 2001 Nevada 2.4 NaN five 2002 Nevada 2.9 NaN In [42]: frame2.columns Out[42]: Index([u'year', u'state', u'pop', u'debt'], dtype='object')
通过类似字典标记的方式或属性的方式,可以将DataFrame的列获取为一个Series。
In [43]: frame2['state'] Out[43]: one Ohio two Ohio three Ohio four Nevada five Nevada Name: state, dtype: object In [44]: frame2.year Out[44]: one 2000 two 2001 three 2002 four 2001 five 2002 Name: year, dtype: int64
注意,返回的Series拥有原DataFrame相同的索引,且其name属性也已经被相应地设置好了啦。行也可以通过位置或名称的方式进行获取,比如用索引字段loc (label based indexing)或iloc (positional indexing)。
In [45]: frame2.loc['three'] Out[45]: year 2002 state Ohio pop 3.6 debt NaN Name: three, dtype: object In [46]: frame2.iloc[3] Out[46]: year 2001 state Nevada pop 2.4 debt NaN Name: four, dtype: object
列可以通过赋值的方式进行修改。例如,可以给那个空的"debt"列赋上一个标量值或一组值。
In [47]: frame2['debt'] = 16.5 In [48]: frame2 Out[48]: year state pop debt one 2000 Ohio 1.5 16.5 two 2001 Ohio 1.7 16.5 three 2002 Ohio 3.6 16.5 four 2001 Nevada 2.4 16.5 five 2002 Nevada 2.9 16.5 In [49]: frame2['debt'] = np.arange(5.) In [50]: frame2 Out[50]: year state pop debt one 2000 Ohio 1.5 0.0 two 2001 Ohio 1.7 1.0 three 2002 Ohio 3.6 2.0 four 2001 Nevada 2.4 3.0 five 2002 Nevada 2.9 4.0
将列表或数组赋值给某个列时,其长度必须跟DataFrame的长度相匹配。如果赋值的是一个Series,就会精确匹配DataFrame的索引,所有的空位都将被填上缺失值。
In [51]: val = Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five']) In [52]: frame2['debt'] = val In [53]: frame2 Out[53]: year state pop debt one 2000 Ohio 1.5 NaN two 2001 Ohio 1.7 -1.2 three 2002 Ohio 3.6 NaN four 2001 Nevada 2.4 -1.5 five 2002 Nevada 2.9 -1.7
为不存在的列赋值会创建出一个新列。关键字del用于删除列。
In [54]: frame2['eastern'] = frame2.state == 'Ohio' In [55]: frame2 Out[55]: year state pop debt eastern one 2000 Ohio 1.5 NaN True two 2001 Ohio 1.7 -1.2 True three 2002 Ohio 3.6 NaN True four 2001 Nevada 2.4 -1.5 False five 2002 Nevada 2.9 -1.7 False In [56]: del frame2['eastern'] In [57]: frame2.columns Out[57]: Index([u'year', u'state', u'pop', u'debt'], dtype='object')
* 通过索引方式返回的列只是相应数据的视图而已,并不是副本。因此,对返回的Series所做的任何就地修改全都会反映到DataFrame上。通过Series的copy方法即可显示地复制列。
另一种常见的数据形式是嵌套字典(也就是字典的字典)。
In [58]: pop = {'Nevada': {2001: 2.4, 2002: 2.9}, ....: 'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
如果将它传给DataFrame,它就会被解释为:外层字典的键作为列,内层键则作为行索引。
In [59]: frame3 = DataFrame(pop) In [60]: frame3 Out[60]: Nevada Ohio 2000 NaN 1.5 2001 2.4 1.7 2002 2.9 3.6
也可以对该结果进行转置。
In [61]: frame3.T Out[61]: 2000 2001 2002 Nevada NaN 2.4 2.9 Ohio 1.5 1.7 3.6
内层字典的键会被合并、排序以形成最终的索引。如果显示指定了索引,则不会这样。
In [62]: DataFrame(pop, index=[2001, 2002, 2003]) Out[62]: Nevada Ohio 2001 2.4 1.7 2002 2.9 3.6 2003 NaN NaN
由Series组成的字典差不多也是一样的用法。
In [63]: pdata = {'Ohio': frame3['Ohio'][:-1], ....: 'Nevada': frame3['Nevada'][:2]} In [64]: DataFrame(pdata) Out[64]: Nevada Ohio 2000 NaN 1.5 2001 2.4 1.7
伐