利用python进行数据分析之pandas入门

转自https://zhuanlan.zhihu.com/p/26100976python

 

目录:

5.1 pandas 的数据结构介绍
5.1.1 Series
5.1.2 DataFrame
5.1.3索引对象
5.2基本功能 
5.2.1从新索引
5.2.2丢弃指定轴上的项
5.2.3索引、选取和过滤
5.2.4算术运算和数据对齐
5.2.4.1在算术方法中填充值
5.2.4.2 DataFrame和Series之间的运算
5.2.5函数应用和映射
5.2.6排序和排名
5.2.7带有重复的轴索引
5.3汇总和计算描述性统计
5.3.1相关系数和协方差
5.3.2惟一值、值计数以及成员资格
5.4处理缺失数据
5.4.1滤除缺失数据
5.4.2填充缺失数据
5.5层次化索引
5.5.1重排分级顺序
5.5.2根据级别汇总统计
5.5.3使用DataFrame的列
5.6其余有关pandas的话题
5.6.1整数索引



第5章 pandas入门 

pandas 引入约定

数组

In [1]: from pandas import Series,DataFrame In [2]: import pandas as pd 


5.1 pandas 的数据结构介绍

要使用pandas,首先要熟悉他的两个主要的数据结构:Series和DataFrame。

5.1.1 Series

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 


serice 的字符串表现形式为:索引在左边,值在右边。
因为咱们没有为数据指定索引,因而会自动建立一个0到N-1(N位数据的长度)的整数的索引。
能够经过series的values和index属性获取其数组表现形式和索引对象。

数据结构

In [6]: obj.values #表现形式 Out[6]: array([ 4, 7, -5, 3], dtype=int64) In [7]: obj.index #索引对象 Out[7]: RangeIndex(start=0, stop=4, step=1) 


一般咱们但愿所建立的Series带有一个能够对各个数据点进行标记的索引:app

In [11]: obj2['a'] Out[11]: -5 In [12]: obj2['d']=6 In [13]: obj2[['c','a','d']] Out[13]: c 3 a -5 d 6 dtype: int64 


NumPy数组运算(若根据布尔型数组进行过滤,标量乘法,应用数学函数等)都会保留索引和值之间的连接:

dom

In [14]: obj2 Out[14]: d 6 b 7 a -5 c 3 dtype: int64 In [15]: obj2[obj2>0] Out[15]: d 6 b 7 c 3 dtype: int64 In [16]: obj2*2 Out[16]: d 12 b 14 a -10 c 6 dtype: int64 In [19]: np.exp(obj2) Out[19]: d 403.428793 b 1096.633158 a 0.006738 c 20.085537 dtype: float64 


咱们也能够将Serice当作一个定长的有序字典,由于它是索引值到数据值的一个映射。能够用在许多本来须要字典参数的函数中:

函数

In [20]: 'b' in obj2 Out[20]: True In [21]: 'e' in obj2 Out[21]: False 


若是数据被存放在一个python字典中,能够直接经过这个字典来建立Series学习

In [4]: sdata={'Ohio':35000,'Texas':71000,'Oregon':16000,'Utah':5000} In [5]: obj3=Series(sdata) In [6]: obj3 Out[6]: Ohio 35000 Oregon 16000 Texas 71000 Utah 5000 dtype: int64 


只传入一个字典,则结果Series中索引就是原字典的键(有序排列)spa

In [7]: states=['California','Ohio','Oregon','Texas'] In [8]: obj4=Series(sdata,index=states) In [9]: obj4 Out[9]: California NaN #“California ”的值找不到,结果用NaN来代替。 Ohio 35000.0 Oregon 16000.0 Texas 71000.0 dtype: float64 


pandas的isnull和notnull函数能够用于检测缺失数据:设计

In [10]: pd.isnull(obj4) Out[10]: California True Ohio False Oregon False Texas False dtype: bool In [11]: pd.notnull(obj4) Out[11]: California False Ohio True Oregon True Texas True dtype: bool 


Series也有相似的实例方法:

In [12]: obj4.isnull() Out[12]: California True Ohio False Oregon False Texas False dtype: bool 


Series重要的一个功能是:它在算术中会自动对齐不一样索引的数据。

In [13]: obj3 Out[13]: Ohio 35000 Oregon 16000 Texas 71000 Utah 5000 dtype: int64 In [14]: obj4 Out[14]: California NaN Ohio 35000.0 Oregon 16000.0 Texas 71000.0 dtype: float64 In [15]: obj3+obj4 Out[15]: California NaN Ohio 70000.0 Oregon 32000.0 Texas 142000.0 Utah NaN dtype: float64 


Series对象自己及其索引都有一个name属性,该属性跟pandas其余关键功能关系很是密切:

In [16]: obj4.name='population' In [17]: obj4.index.name='state' In [18]: obj4 Out[18]: state California NaN Ohio 35000.0 Oregon 16000.0 Texas 71000.0 Name: population, dtype: float64 


Series 的索引能够经过赋值的方式就地修改:

In [20]: obj=Series([4,7,-5,3]) In [21]: obj.index=['Bob','Steve','Jeff','Ryan'] In [22]: obj Out[22]: Bob 4 Steve 7 Jeff -5 Ryan 3 dtype: int64 


5.1.2 DataFrame
DataFrame是一个表格型的数据结构,含有一组有序的列,每列能够是不一样的值类型(数值,字符串,布尔值等)
DataFrame既有行索引也有列索引,能够被看作是由Series组成的字典。
跟其余的相似的数据结构相比(如R的data.frame),DataFrame中面向行和列的操做基本是平衡的。

DataFrame中的数据是以一个或多个二维块存放的。

构建DataFrame的办法有不少,最经常使用的一种是直接传入一个由等长列表或numpy组成的数组组成的字典:

In [5]: from pandas import Series,DataFrame In [6]: import pandas as pd In [7]: 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 [8]: frame=DataFrame(data) 


结果DataFrame'会自动加上索引(跟Series同样),且所有列会被有序排列:

In [10]: frame Out[10]: 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 [11]: DataFrame(data,columns=['year','state','pop']) Out[11]: 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 [11]: frame2=DataFrame(data,columns=['year','state','pop','debt'] ...: ,index=['one','two','three','four','five']) In [12]: frame2 Out[12]: 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 [26]: frame2.columns Out[26]: Index([u'years', u'state', u'pop', u'debt'], dtype='object') 


经过相似于字典标记的方式或属性的方式,能够将DataFrame的列获取为一个Series:

In [27]: frame2['state'] Out[27]: one Ohio two Ohio three Ohio four Nevada five Nevada Name: state, dtype: object In [18]: frame2.year Out[18]: one 2000 two 2001 three 2002 four 2001 five 2002 Name: year, dtype: int64 


注意,返回的Series拥有原DataFrame相同的索引,且其name属性也已经被相应的设置好了。
行也能够经过位置或名称的方式来进行获取。

In [19]: frame2.ix['three'] Out[19]: year 2002 state Ohio pop 3.6 debt NaN Name: three, dtype: object 


列能够经过赋值的方式进行修改。以下,咱们能够给空的”debt“列赋值一个标量或一组值。

In [20]: frame2['debt']=16.5 In [21]: frame2 Out[21]: 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 [24]: frame2['debt']=np.arange(5.) In [25]: frame2 Out[25]: 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 [26]: val=Series([-1.2,-1.5,-1.7],index=['two','four','five']) In [27]: frame2['debt']=val In [28]: frame2 Out[28]: 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 [29]: frame2['eastern']=frame2.state=='Ohio' In [30]: frame2 Out[30]: 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 [31]: del frame2['eastern'] In [32]: frame2.columns Out[32]: Index([u'year', u'state', u'pop', u'debt'], dtype='object') 


另外一种常见的数据形式是嵌套字典(也就是字典的字典):

In [33]: pop={'Nevada':{2001:2.4,2002:2.9},'Ohio':{2000:1.5,2001:1.7, ...: 2002:3.6}} 


将它传给DataFrame,就会被解释为:外层字典的键做为列,内层键做为行索引。

In [34]: frame3=DataFrame(pop) In [35]: frame3 Out[35]: Nevada Ohio 2000 NaN 1.5 2001 2.4 1.7 2002 2.9 3.6 


也能够对结果进行转置:

In [36]: frame3.T Out[36]: 2000 2001 2002 Nevada NaN 2.4 2.9 Ohio 1.5 1.7 3.6 


内层字典的键会被合并、排序以及造成最终的索引。若指定了显式索引,则不会这样:

In [37]: DataFrame(pop,index=[2001,2002,2003]) Out[37]: Nevada Ohio 2001 2.4 1.7 2002 2.9 3.6 2003 NaN NaN 


由Series组成的字典差很少也是同样的用法:

In [40]: pdata={'Ohio':frame3['Ohio'][:-1],'Nevada':frame3['Nevada'][:2]} In [41]: DataFrame(pdata) Out[41]: Nevada Ohio 2000 NaN 1.5 2001 2.4 1.7 


若是设置了Data.Frame的index属性和columns的name属性,

In [42]: frame3.index.name='year';frame3.columns.name='state' In [43]: frame3 Out[43]: state Nevada Ohio year 2000 NaN 1.5 2001 2.4 1.7 2002 2.9 3.6 In [44]: frame3.values Out[44]: array([[ nan, 1.5], [ 2.4, 1.7], [ 2.9, 3.6]]) In [45]: frame3.values Out[45]: array([[ nan, 1.5], [ 2.4, 1.7], [ 2.9, 3.6]]) 


5.1.3索引对象
pandas的索引对象负责管理标签和其余元数据(好比轴名称等)。构建Series或DataFrame时,所用到的任何数组或其余序列的标签都会被转换成一个Index:

In [2]: import numpy as np In [3]: import pandas as pd In [5]: from pandas import Series,DataFrame In [6]: obj=Series(range(3),index=['a','b','c']) In [7]: index=obj.index In [8]: index Out[8]: Index([u'a', u'b', u'c'], dtype='object') In [9]: index[1:] Out[9]: Index([u'b', u'c'], dtype='object') 


Index对象是不可修改的,所以用户不能对其修改:

In [10]: index[1]='d' --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-10-d3f90986bdb1> in <module>() ----> 1 index[1]='d' H:\Anaconda2-4.3.0.1\lib\site-packages\pandas\indexes\base.pyc in __setitem__(self, key, value) 1402 1403 def __setitem__(self, key, value): -> 1404 raise TypeError("Index does not support mutable operations") 1405 1406 def __getitem__(self, key): TypeError: Index does not support mutable operations 


不可修改性很是重要,由于这样才能使得index对象在多个数据结构之间安全共享:

In [12]: index=pd.Index(np.arange(3)) In [13]: obj2=Series([1.5,-2.5,0],index=index) In [14]: obj2=Series([1.5,-2.5,0],index=index) In [16]: obj2.index is index Out[16]: True 



除了长得像数组,index的功能也相似一个固定大小的集合:

In [43]: frame3 Out[43]: state Nevada Ohio year 2000 NaN 1.5 2001 2.4 1.7 2002 2.9 3.6 In [46]: 'Ohio' in frame3.columns Out[46]: True In [47]: 2003 in frame3.index Out[47]: False 


5.2基本功能 
介绍操做Series和DataFrame中的数据的基本手段。

5.2.1从新索引
pandas对象的一个重要的方法就是reindex,做用是建立一个适应新索引的新对象。

In [33]: import pandas as pd from pandas import Series,DataFrame In [34]: obj=Series([4.5,7.2,-5.3,3.6],index=['d','b','a','c']) In [35]: obj Out[35]: d 4.5 b 7.2 a -5.3 c 3.6 dtype: float64 


调用该Series的reindex将会根据新索引进行重排。若是某个索引值当前不存,就引入缺失值:

In [36]: obj2=obj.reindex(['a','b','c','d','e']) In [37]: obj2 Out[37]: a -5.3 b 7.2 c 3.6 d 4.5 e NaN dtype: float64 In [38]: obj.reindex(['a','b','c','d','e'],fill_value=0) Out[38]: a -5.3 b 7.2 c 3.6 d 4.5 e 0.0 dtype: float64 


对于时间序列这样的有序数据,从新索引时可能须要作一些插值处理。method选项便可用达到此目的。例如:ffill能够实现向前值填充:

In [39]: obj3=Series(['blue','purple','yellow'],index=[0,2,4]) In [40]: obj3.reindex(range(6),method='ffill') Out[40]: 0 blue 1 blue 2 purple 3 purple 4 yellow 5 yellow dtype: object 


下表中列出了可用的method选项。
参数 说明
fill或pad 前向填充(或搬运)值
bfill或backfill 后向填充(或搬运)值

对于DataFrame,reindex能够修改(行)索引,列,或两个都修改。若是仅传入一个序列,则会从新索引行:

In [41]: frame=DataFrame(np.arange(9).reshape((3,3)),index=['a','c','d'],columns=['Ohio','Texas','California',]) In [52]: frame Out[53]: Ohio Texas California a 0 1 2 c 3 4 5 d 6 7 8 In [54]: frame2=frame.reindex(['a','b','c','d']) In [55]:frame2 Out[55]: Ohio Texas California a 0.0 1.0 2.0 b NaN NaN NaN c 3.0 4.0 5.0 d 6.0 7.0 8.0 


使用columns关键字便可以从新索引。

In [56]: states=['Texas','Utah','California'] frame.reindex(columns=states) Out[57]: Texas Utah California a 1 NaN 2 c 4 NaN 5 d 7 NaN 8 


也能够同时对行和列进行从新索引,而插值则只能按行应用(即轴0):

frame.reindex(index=['a','b','c','d'],method='ffill',columns=states) Out[58]: Texas Utah California a 1 NaN 2 b 1 NaN 2 c 4 NaN 5 d 7 NaN 8 


利用ix的标签的=索引功能,从新索引任务能够变得简洁:

frame.ix[['a','b','c','d'],states] Out[59]: Texas Utah California a 1.0 NaN 2.0 b NaN NaN NaN c 4.0 NaN 5.0 d 7.0 NaN 8.0 



5.2.2丢弃指定轴上的项
丢弃某条轴上的一个或多个项,只要有一个索引数组或列表便可。
因为须要执行一些数据整理和集合逻辑,因此drop方法返回的是一个在指定轴上删除了指定值的新对象:

In [60]: obj=Series(np.arange(5.),index=['a','b','c','d','e']) In [61]: new_obj=obj.drop('c') In [62]: new_obj Out[62]: a 0.0 b 1.0 d 3.0 e 4.0 dtype: float64 In[63]: obj.drop(['d','c']) Out[63]: a 0.0 b 1.0 e 4.0 dtype: float64 


对于DataFrame,能够删除任意轴上的索引值:

In [66]: data=DataFrame(np.arange(16).reshape((4,4)),index=['Ohio','Colorado','Utah','New York'],columns=['one','two','three','four']) In[67]: data.drop(['Colorado','Ohio']) Out[67]: one two three four Utah 8 9 10 11 New York 12 13 14 15 In [68]: data.drop('two',axis=1) Out[68]: one three four Ohio 0 2 3 Colorado 4 6 7 Utah 8 10 11 New York 12 14 15 In [69]: data.drop(['two','four'],axis=1) Out[69]: one three Ohio 0 2 Colorado 4 6 Utah 8 10 New York 12 14 


5.2.3索引、选取和过滤
Series索引 (obj[...])的工做方式相似于NumPy数组的索引,只不过Series的索引值不仅是整数。例:

In [5]: obj=Series(np.arange(4.),index=['a','b','c','d']) In [6]: obj['b'] Out[6]: 1.0 In [7]: obj[1] Out[7]: 1.0 In [8]: obj[2:4] Out[8]: c 2.0 d 3.0 dtype: float64 In [10]: obj[['b','a','d']] Out[10]: b 1.0 a 0.0 d 3.0 dtype: float64 In [11]: obj[[1,3]] Out[11]: b 1.0 d 3.0 dtype: float64 In [12]: obj[obj<2] Out[12]: a 0.0 b 1.0 dtype: float64 


利用标签的切片运算与普通的python切片运算不一样,其末端是包含的(inclusive)

In [19]: obj['b':'c'] Out[19]: b 1.0 c 2.0 dtype: float64 


设置方式以下:

In [20]: obj['b':'c']=5 In [21]: obj Out[21]: a 0.0 b 5.0 c 5.0 d 3.0 dtype: float64 


如你所见,对DataFrame进行索引其实就是获取一个或多个列:

In [24]: data=DataFrame(np.arange(16).reshape((4,4)),
index=['Ohio','Colorado','Utah','New York'],columns=['one','two','three','four'])

In [25]: data
Out[25]:
          one  two  three  four
Ohio        0    1      2     3
Colorado    4    5      6     7
Utah        8    9     10    11
New York   12   13     14    15

In [26]: data['two']
Out[26]:
Ohio         1
Colorado     5
Utah         9
New York    13
Name: two, dtype: int32

In [28]: data[['three','one']]
Out[28]:
          three  one
Ohio          2    0
Colorado      6    4
Utah         10    8
New York     14   12

In [30]: data[['three','one']]
Out[30]:
          three  one
Ohio          2    0
Colorado      6    4
Utah         10    8
New York     14   12


这种索引方式有几个特殊状况。首先经过切片或布尔数组进行选取行:

In [29]: data[:2] Out[29]: one two three four Ohio 0 1 2 3 Colorado 4 5 6 7 In [31]: data[data['three']>5] Out[31]: one two three four Colorado 4 5 6 7 Utah 8 9 10 11 New York 12 13 14 15 


另外一种用法使经过布尔型DataFrame进行索引:

In [32]: data<5 Out[32]: one two three four Ohio True True True True Colorado True False False False Utah False False False False New York False False False False In [33]: data[data<5]=0 In [34]: data Out[34]: one two three four Ohio 0 0 0 0 Colorado 0 5 6 7 Utah 8 9 10 11 New York 12 13 14 15 


这段代码使得DataFrame在语法上像ndarray
为了在DataFrame的行上进行标签索引,咱们引入专门的索引字段ix。使得你经过numpy式的标记法以及轴标签的从DataFrame中选取行和列的子集。这是重现索引的简单手段:

In [35]: data.ix['Colorado',['two','three']]
Out[35]:
two      5
three    6
Name: Colorado, dtype: int32

In [36]: data.ix[['Colorado','Utah'],[3,0,1]]
Out[36]:
          four  one  two
Colorado     7    0    5
Utah        11    8    9

In [37]: data.ix[2]
Out[37]:
one       8
two       9
three    10
four     11
Name: Utah, dtype: int32

In [38]: data.ix[:'Utah','two']
Out[38]:
Ohio        0
Colorado    5
Utah        9
Name: two, dtype: int32

In [39]: data.ix[data.three>5,:3]
Out[39]:
          one  two  three
Colorado    0    5      6
Utah        8    9     10
New York   12   13     14


5.2.4算术运算和数据对齐

In [5]: s1=Series([7.3,-2.5,3.4,1.5],index=['a','c','d','e']) In [6]: s2=Series([-2.1,3.6,-1.5,4,3.1],index=['a','c','e','f','g']) In [7]: s1 Out[7]: a 7.3 c -2.5 d 3.4 e 1.5 dtype: float64 In [8]: s2 Out[8]: a -2.1 c 3.6 e -1.5 f 4.0 g 3.1 dtype: float64 


把他们相加:

In [9]: s1+s2 Out[9]: a 5.2 c 1.1 d NaN e 0.0 f NaN g NaN dtype: float64 


自动的数据对其操做在不重叠的索引处引入了NA值。缺失值会在算术运算过程当中传播。

对于DataFrame,对齐操做会同时发生在行和列上:

In [6]: df1=DataFrame(np.arange(9.).reshape((3,3)),columns=list('bcd'),index=['Ohio','Texas','Colorado']) In [7]: df2=DataFrame(np.arange(12.).reshape((4,3)),columns=list('bde'),index=['Utah','Ohio','Texas','Oregon']) In [8]: df1 Out[8]: b c d Ohio 0.0 1.0 2.0 Texas 3.0 4.0 5.0 Colorado 6.0 7.0 8.0 In [9]: df2 Out[9]: b d e Utah 0.0 1.0 2.0 Ohio 3.0 4.0 5.0 Texas 6.0 7.0 8.0 Oregon 9.0 10.0 11.0 


将他们相加后,会返回一个新的DataFrame,其索引和列为原来的那两个DataFrame的并集:

In [10]: df1+df2 Out[10]: b c d e Colorado NaN NaN NaN NaN Ohio 3.0 NaN 6.0 NaN Oregon NaN NaN NaN NaN Texas 9.0 NaN 12.0 NaN Utah NaN NaN NaN NaN 


5.2.4.1在算术方法中填充值
在不一样索引的对象进行算术运算时,你可能但愿当一个对象中某个轴标签在另外一个对象张找不到时填充一个特殊值:

In [20]: df1=DataFrame(np.arange(12.).reshape((3,4)),columns=list('abcd')) In [21]: df2=DataFrame(np.arange(20.).reshape((4,5)),columns=list('abcde')) In [22]: df1 Out[22]: a b c d 0 0.0 1.0 2.0 3.0 1 4.0 5.0 6.0 7.0 2 8.0 9.0 10.0 11.0 In [23]: df2 Out[23]: a b c d e 0 0.0 1.0 2.0 3.0 4.0 1 5.0 6.0 7.0 8.0 9.0 2 10.0 11.0 12.0 13.0 14.0 3 15.0 16.0 17.0 18.0 19.0 


将他们相加时,没有重叠的位置就会产生NA值:

In [24]: df1+df2 Out[24]: a b c d e 0 0.0 2.0 4.0 6.0 NaN 1 9.0 11.0 13.0 15.0 NaN 2 18.0 20.0 22.0 24.0 NaN 3 NaN NaN NaN NaN NaN 


使用df1的add方法,传入df2以及一个fill_value参数:

In [26]: df1.add(df2,fill_value=0) Out[26]: a b c d e 0 0.0 2.0 4.0 6.0 4.0 1 9.0 11.0 13.0 15.0 9.0 2 18.0 20.0 22.0 24.0 14.0 3 15.0 16.0 17.0 18.0 19.0 


对Series或DataFrame从新索引时,也能够指定一个填充值:

In [28]: df1.reindex(columns=df2.columns,fill_value=0) Out[28]: a b c d e 0 0.0 1.0 2.0 3.0 0 1 4.0 5.0 6.0 7.0 0 2 8.0 9.0 10.0 11.0 0 


表5-7 灵活的算术方法
方法 说明
add 用于加法(+)的方法
sub 用于减法(-)的方法
div 用于乘法(*)的方法
mul 用于除法(/)的方法

5.2.4.2 DataFrame和Series之间的运算
跟NumPy数组同样,DataFrame和Series的=之间的算术运算也是有明确规定的。
下面来计算一个二维数组与其某行之间的差:

In [29]: arr=np.arange(12.).reshape((3,4)) In [30]: arr Out[30]: array([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.]]) In [31]: arr[0] Out[31]: array([ 0., 1., 2., 3.]) In [32]: arr-arr[0] Out[32]: array([[ 0., 0., 0., 0.], [ 4., 4., 4., 4.], [ 8., 8., 8., 8.]]) 


上面的运算就叫作,广播。
DataFrame和Series之间的运算差很少也是如此:

In [33]: frame=DataFrame(np.arange(12.).reshape((4,3)),columns=list('bde'),index=['Utah','Ohio','Texas','Oregon']) In [34]: series=frame.ix[0] In [35]: frame Out[35]: b d e Utah 0.0 1.0 2.0 Ohio 3.0 4.0 5.0 Texas 6.0 7.0 8.0 Oregon 9.0 10.0 11.0 In [36]: series Out[36]: b 0.0 d 1.0 e 2.0 Name: Utah, dtype: float64 


默认状况下,DataFrame和Series之间的算术运算符将Series的索引匹配到DataFrame的列,而后沿着行一直向下广播:

In [37]: frame - series Out[37]: b d e Utah 0.0 0.0 0.0 Ohio 3.0 3.0 3.0 Texas 6.0 6.0 6.0 Oregon 9.0 9.0 9.0 


若是某个索引值在DataFrame的列或Series的索引中找不到,则参与运算的两个对象就会被从新索引以造成并集:

In [38]: series2=Series(range(3),index=['b','e','f']) In [39]: frame+series2 Out[39]: b d e f Utah 0.0 NaN 3.0 NaN Ohio 3.0 NaN 6.0 NaN Texas 6.0 NaN 9.0 NaN Oregon 9.0 NaN 12.0 NaN 


若是你但愿匹配行且在列上广播,则必须使用算术运算方法:

In [40]: series3=frame['d'] In [41]: frame Out[41]: b d e Utah 0.0 1.0 2.0 Ohio 3.0 4.0 5.0 Texas 6.0 7.0 8.0 Oregon 9.0 10.0 11.0 In [42]: series3 Out[42]: Utah 1.0 Ohio 4.0 Texas 7.0 Oregon 10.0 Name: d, dtype: float64 In [43]: frame.sub(series3,axis=0) Out[43]: b d e Utah -1.0 0.0 1.0 Ohio -1.0 0.0 1.0 Texas -1.0 0.0 1.0 Oregon -1.0 0.0 1.0 


传入的轴号就是但愿匹配的轴。

5.2.5函数应用和映射
Numpy的ufuncs(元素级数组方法)也能够用于操做pandas对象:

In [44]: frame=DataFrame(np.random.randn(4,3),columns=list('bde'),index=['Utah','Ohio','Texas','Oregon']) In [45]: frame Out[45]: b d e Utah -0.172344 1.823441 -0.067380 Ohio -0.338604 -0.189082 -0.145676 Texas 1.310289 -0.518146 -0.231740 Oregon -1.880954 -0.400772 0.228320 In [46]: np.abs(frame) Out[46]: b d e Utah 0.172344 1.823441 0.067380 Ohio 0.338604 0.189082 0.145676 Texas 1.310289 0.518146 0.231740 Oregon 1.880954 0.400772 0.228320 


另外一个常见的操做,将函数应用到由各列或行所造成的一维数组上。DataFrame的apply方法便可实现此功能:

In [47]: f=lambda x:x.max() - x.min()

In [48]: frame.apply(f)
Out[48]:
b 3.191243
d 2.341587
e 0.460059
dtype: float64

In [49]: frame.apply(f,axis=1)
Out[49]:
Utah 1.995785
Ohio 0.192928
Texas 1.828435
Oregon 2.109274
dtype: float64


除标量外,传递给apply的函数还能够返回由多个值组成的Series:

In [52]: def f(x): ...: return Series([x.min(),x.max()],index=['min','max']) ...: In [53]: frame.apply(f) Out[53]: b d e min -1.880954 -0.518146 -0.23174 max 1.310289 1.823441 0.22832 


此外,元素级的python函数也是能够用的。
假如想获得frame中各个浮点数的格式化字符串,使用applymap便可:

In [54]: format=lambda x:'%.2f' %x In [55]: frame.applymap(format) Out[55]: b d e Utah -0.17 1.82 -0.07 Ohio -0.34 -0.19 -0.15 Texas 1.31 -0.52 -0.23 Oregon -1.88 -0.40 0.23 


之因此叫作applymap,是由于Series有一个用于应用元素级函数的map的方法:

In [56]: frame['e'].map(format) Out[56]: Utah -0.07 Ohio -0.15 Texas -0.23 Oregon 0.23 Name: e, dtype: object 


5.2.6排序和排名
根据条件对数据集排序也是一种重要的内置运算。要对行或列索引进行排序(按字典顺序),可使用sort_index方法,它将返回一个已经排序的新对象:

In [57]: obj=Series(range(4),index=['d','a','b','c']) In [58]: obj.sort_index() Out[58]: a 1 b 2 c 3 d 0 dtype: int64 


而对于DataFrame,则能够根据任意一个轴上的索引进行排序:

In [59]: frame=DataFrame(np.arange(8).reshape((2,4)),index=['three','one'],columns=['d','a','b','c']) In [60]: frame.sort_index() Out[60]: d a b c one 4 5 6 7 three 0 1 2 3 In [61]: frame.sort_index(axis=1) Out[61]: a b c d three 1 2 3 0 one 5 6 7 4 


数据默认是按升序排列的,但也能够降序排序:

In [64]: frame.sort_index(axis=1,ascending=False) Out[64]: d c b a three 0 3 2 1 one 4 7 6 5 


若要按值对Series进行排序,可使用order方法:

In [65]: obj=Series([4,7,-3,2]) In [66]: obj.order() Out[66]: 2 -3 3 2 0 4 1 7 dtype: int64 


在排序的时候,缺失值默认都会被放在了Series的末尾:

In [67]: obj=Series([4,np.nan,7,np.nan,-3,2]) In [68]: obj.order() Out[68]: 4 -3.0 5 2.0 0 4.0 2 7.0 1 NaN 3 NaN dtype: float64 


在DataFrame上,你可能但愿根据一个或多个列中的值进行排序。将一个或多个列的名字传递给by选项便可达到该目的:

In [69]: frame=DataFrame({'b':[4,7,-3,2],'a':[0,1,0,1]}) In [70]: frame Out[70]: a b 0 0 4 1 1 7 2 0 -3 3 1 2 In [71]: frame.sort_index(by='b') Out[71]: a b 2 0 -3 3 1 2 0 0 4 1 1 7 


要根据多个列进行排序,传入名称的列表便可:

In [73]: frame.sort_index(by=['a','b']) Out[73]: a b 2 0 -3 0 0 4 3 1 2 1 1 7 


排名(ranking)跟排序关系密切,且会增设一个排名值(从1开始,一直到数组中有效数据的数量),跟numpy.argsort产生的间接排序索引差很少,只不过它能够根据某种规则破坏平级关系。

下面介绍Series和DataFrame的rank方法。默认下:rank是经过“为各组分配一个平均排名”的方式来破坏平级关系。

In [75]: obj=Series([7,-5,7,4,2,0,4]) In [76]: obj.rank() Out[76]: 0 6.5 1 1.0 2 6.5 3 4.5 4 3.0 5 2.0 6 4.5 dtype: float64 


也能够根据值在原数据中出现的顺序给出排名:

In [77]: obj.rank(method='first') Out[77]: 0 6.0 1 1.0 2 7.0 3 4.0 4 3.0 5 2.0 6 5.0 dtype: float64 


也能够按降序进行排名:

In [78]: obj.rank(ascending=False,method='max') Out[78]: 0 2.0 1 7.0 2 2.0 3 4.0 4 5.0 5 6.0 6 4.0 dtype: float64 


表5-8 列出了全部用于破坏平级关系的method选项。DataFrame能够在行或列上计算排名:

In [79]: frame=DataFrame({'b':[4.3,7,-3,2],'a':[0,1,0,1],'c':[-2,5,8,-2.5]}) In [80]: frame Out[80]: a b c 0 0 4.3 -2.0 1 1 7.0 5.0 2 0 -3.0 8.0 3 1 2.0 -2.5 In [81]: frame.rank(axis=1) Out[81]: a b c 0 2.0 3.0 1.0 1 1.0 3.0 2.0 2 2.0 1.0 3.0 3 2.0 3.0 1.0 


表5-8 :排名时用于破坏平级关系的method选项
method 说明
‘average’ 默认:在相等分组中,为各个值分配平均排‘’
‘min’ 使用整个分组的最小排名
‘max’ 使用整个分组的最大排名
‘first’ 按值在原始数据中的出现顺序分配排名

5.2.7带有重复的轴索引
咱们看看下面这个简单的带有重复索引值的Series:

In [82]: obj=Series(range(5),index=['a','a','b','b','c']) In [83]: obj Out[83]: a 0 a 1 b 2 b 3 c 4 dtype: int64 


索引的is_unique属性能够告诉你他的值是不是惟一的:

In [84]: obj.index.is_unique Out[84]: False 


对于重复的索引,数据选取的行为将会有些不一样。若是某个索引对应的多个值,则返回一个Series,而对应单个值,则返回一个标量:

In [85]: obj['a'] Out[85]: a 0 a 1 dtype: int64 In [86]: obj['c'] Out[86]: 4 


对DataFrame的行进行索引时候也是如此:

In [87]: df=DataFrame(np.random.randn(4,3),index=['a','a','b','b']) In [88]: df Out[88]: 0 1 2 a 0.056598 1.592208 -0.576368 a 0.842511 -0.085418 0.818032 b 1.347421 -0.239196 -0.543597 b -0.598395 0.966395 0.285722 In [89]: df.ix['b'] Out[89]: 0 1 2 b 1.347421 -0.239196 -0.543597 b -0.598395 0.966395 0.285722 


5.3汇总和计算描述性统计
pandas对象拥有一组经常使用的数学和统计方法。他们大部分都属于约简和汇总统计,用于从Series中提取单个值(如mean或sum)或从DataFrame的行或列中提取一个Series。跟对应的NumPy数组方法相比,他们都是基于没有缺失数据的假设而构建的。

下面是一个简单的DataFrame:

In [90]: df=DataFrame([[1.4,np.nan],[7.1,-4.5],[np.nan,np.nan],[0.75,-1.3]],index=['a','b','c','d'],columns=['one','two']) In [91]: df Out[91]: one two a 1.40 NaN b 7.10 -4.5 c NaN NaN d 0.75 -1.3 


调用DataFrame的sum方法将会返回一个含有列的小计的Series:

In [92]: df.sum() Out[92]: one 9.25 two -5.80 dtype: float64 


传入axis=1 将会按行进行求和计算:

In [93]: df.sum(axis=1) Out[93]: a 1.40 b 2.60 c 0.00 d -0.55 dtype: float64 


NA值将会被自动剔除,除非整个切片都是NA。经过skipna选项能够禁用该功能:

In [94]: df.mean(axis=1,skipna=False) Out[94]: a NaN b 1.300 c NaN d -0.275 dtype: float64 


表5-9给出了约简方法经常使用选项

有些方法(如idxmin和idxmax)返回的是间接统计(好比达到最大值或最小值的索引):

In [95]: df.idxmax() Out[95]: one b two d dtype: object 


一些方法则是累计型的:

In [96]: df.cumsum() Out[96]: one two a 1.40 NaN b 8.50 -4.5 c NaN NaN d 9.25 -5.8 


还有一些方法,既不是约简型也不是累计型。

In [97]: df.describe() Out[97]: one two count 3.000000 2.000000 mean 3.083333 -2.900000 std 3.493685 2.262742 min 0.750000 -4.500000 25% 1.075000 -3.700000 50% 1.400000 -2.900000 75% 4.250000 -2.100000 max 7.100000 -1.300000 


对于非数值型的数据,describe会产生另外一种汇总统计:

In [98]: obj=Series(['a','a','b','c']*4) In [99]: obj.describe() Out[99]: count 16 unique 3 top a freq 8 dtype: object 


表5-10列出了全部与描述统计相关的方法。

5.3.1相关系数和协方差

有些汇总统计(如先关系数和协方差)是经过参数计算出来的。

5.3.2惟一值、值计数以及成员资格
从一维Series的值中抽取信息。如下这个Series为例:

In [107]: obj=Series(['c','a','d','a','a','b','b','c','c']) 


第一个函数是unique,能够获得Sseries中的惟一数组:

In [108]: uniques=obj.unique() In [109]: uniques Out[109]: array(['c', 'a', 'd', 'b'], dtype=object) 


返回值的惟一未排序的,若是须要的话,能够对结果再次进行排序(unique.sort())
value_counts 用于计算一个Series中各值出现的频率:

In [110]: obj.value_counts() Out[110]: c 3 a 3 b 2 d 1 dtype: int64 


为了方便查看,结果Series是按值频率降序排列的。
value_counts 仍是一个顶级的pandas方法,可用于任何数组的或序列:

In [111]: pd.value_counts(obj.values,sort=False) Out[111]: a 3 c 3 b 2 d 1 dtype: int64 


最后isin,它用于判断矢量化最集合的成员资格,可用于选取Series中或DataFrame列中的数据的子集:

In [112]: mask=obj.isin(['b','c']) In [113]: mask Out[113]: 0 True 1 False 2 False 3 False 4 False 5 True 6 True 7 True 8 True dtype: bool In [114]: obj[mask] Out[114]: 0 c 5 b 6 b 7 c 8 c dtype: object 


有时,你可能须要获得DataFrame中多个相关的一张柱状图。

In [115]: data=DataFrame({'Qu1':[1,3,4,3,4],'Qu2':[2,3,1,2,3],'Qu3':[1,5,2,4,4]}) In [116]: data Out[116]: Qu1 Qu2 Qu3 0 1 2 1 1 3 3 5 2 4 1 2 3 3 2 4 4 4 3 4 In [117]: result=data.apply(pd.value_counts).fillna(0) In [118]: result Out[118]: Qu1 Qu2 Qu3 1 1.0 1.0 1.0 2 0.0 2.0 1.0 3 2.0 2.0 0.0 4 2.0 0.0 2.0 5 0.0 0.0 1.0 


5.4处理缺失数据
处理缺失数据(missing data)在大部分的数据分析应用中很常见。pandas的设计目标之一就是让缺失数据的处理任务尽可能轻松。

pandas使用浮点数NaN(Not a Number)表示浮点和非浮点数组中的缺失数据。只是一个便于检测出来的标记而已:

In [119]: string_data=Series(['aardvark','arrichoke',np.nan,'avocado']) In [120]: string_data Out[120]: 0 aardvark 1 arrichoke 2 NaN 3 avocado dtype: object In [121]: string_data.isnull() Out[121]: 0 False 1 False 2 True 3 False dtype: bool 



python内置的None值也会被当作NA处理:

In [123]: string_data.isnull() Out[123]: 0 True 1 False 2 True 3 False dtype: bool 


5.4.1滤除缺失数据
对于一个Series,dropna返回一个仅含有非空数据的和索引值的Series:

In [124]: from numpy import nan as NA In [125]: data=Series([1,NA,3.5,NA,7]) In [126]: data.dropna() Out[126]: 0 1.0 2 3.5 4 7.0 dtype: float64 


还能够经过布尔型索引达到这个目的:

In [127]: data[data.notnull()] Out[127]: 0 1.0 2 3.5 4 7.0 dtype: float64 


对于DataFrame对象,若是但愿丢弃全NA或NA的行货列,dropna默认丢弃任何含有缺失值的行:

In [129]: data=DataFrame([[1.,6.5,3.],[1.,NA,NA],[NA,NA,NA],[NA,6.5,3.]]) In [130]: cleaned=data.dropna() In [131]: data Out[131]: 0 1 2 0 1.0 6.5 3.0 1 1.0 NaN NaN 2 NaN NaN NaN 3 NaN 6.5 3.0 In [132]: cleaned Out[132]: 0 1 2 0 1.0 6.5 3.0 


传入how=‘all’ 将只丢弃全为NA的那些行:

In [133]: data.dropna(how='all') Out[133]: 0 1 2 0 1.0 6.5 3.0 1 1.0 NaN NaN 3 NaN 6.5 3.0 


要用这种方式丢弃列,只需传入axis=1便可:

In [134]: data[4]=NA In [135]: data Out[135]: 0 1 2 4 0 1.0 6.5 3.0 NaN 1 1.0 NaN NaN NaN 2 NaN NaN NaN NaN 3 NaN 6.5 3.0 NaN In [136]: data.dropna(axis=1,how='all') Out[136]: 0 1 2 0 1.0 6.5 3.0 1 1.0 NaN NaN 2 NaN NaN NaN 3 NaN 6.5 3.0 


另外一个滤出DataFrame行的问题涉及时间序列数据。
假设你只想留下一部分观测数据,能够用thresh参数实现此目的:

In [137]: df=DataFrame(np.random.randn(7,3)) In [138]: df.ix[:4,1]=NA;df.ix[:2,2]=NA In [139]: df Out[139]: 0 1 2 0 0.452896 NaN NaN 1 1.071009 NaN NaN 2 -0.135804 NaN NaN 3 0.010116 NaN 0.064880 4 -1.038639 NaN -0.756553 5 0.738134 -1.505505 -0.052306 6 -1.712077 0.386785 0.436945 In [140]: df.dropna(thresh=3) Out[140]: 0 1 2 5 0.738134 -1.505505 -0.052306 6 -1.712077 0.386785 0.436945 


5.4.2填充缺失数据
若是不想滤除数据,而是但愿填充数据。
经过一个常数来fillna就会将缺失值替换为那个常数值:

In [141]: df.fillna(0) Out[141]: 0 1 2 0 0.452896 0.000000 0.000000 1 1.071009 0.000000 0.000000 2 -0.135804 0.000000 0.000000 3 0.010116 0.000000 0.064880 4 -1.038639 0.000000 -0.756553 5 0.738134 -1.505505 -0.052306 6 -1.712077 0.386785 0.436945 


经过一个字典调用fillna,就能够实现对不一样的列填充不一样的值:

In [142]: df.fillna({1:0.5,3:-1}) Out[142]: 0 1 2 0 0.452896 0.500000 NaN 1 1.071009 0.500000 NaN 2 -0.135804 0.500000 NaN 3 0.010116 0.500000 0.064880 4 -1.038639 0.500000 -0.756553 5 0.738134 -1.505505 -0.052306 6 -1.712077 0.386785 0.436945 


fillna默认会返回新对象,可是也能够对现有的对象进行修改:

In [143]: _=df.fillna(0,inplace=True) In [144]: df Out[144]: 0 1 2 0 0.452896 0.000000 0.000000 1 1.071009 0.000000 0.000000 2 -0.135804 0.000000 0.000000 3 0.010116 0.000000 0.064880 4 -1.038639 0.000000 -0.756553 5 0.738134 -1.505505 -0.052306 6 -1.712077 0.386785 0.436945 


对reindex有效的那些插值方法也能够用于fillna:

In [145]: df=DataFrame(np.random.randn(6,3)) In [146]: df.ix[2:,1]=NA;df.ix[4:,2]=NA In [147]: df Out[147]: 0 1 2 0 0.501394 -1.735750 0.197643 1 2.099104 1.441581 0.743717 2 -0.451567 NaN -0.150315 3 -0.032894 NaN 0.418310 4 1.285966 NaN NaN 5 -0.058611 NaN NaN In [148]: df.fillna(method='ffill') Out[148]: 0 1 2 0 0.501394 -1.735750 0.197643 1 2.099104 1.441581 0.743717 2 -0.451567 1.441581 -0.150315 3 -0.032894 1.441581 0.418310 4 1.285966 1.441581 0.418310 5 -0.058611 1.441581 0.418310 In [149]: df.fillna(method='ffill',limit=2) Out[149]: 0 1 2 0 0.501394 -1.735750 0.197643 1 2.099104 1.441581 0.743717 2 -0.451567 1.441581 -0.150315 3 -0.032894 1.441581 0.418310 4 1.285966 NaN 0.418310 5 -0.058611 NaN 0.418310 


只要稍微动脑子,就能够利用fillna的=实现许多的别的功能。
好比,传入Series的平均值或中位数:

In [150]: data=Series([1.,NA,3.5,NA,7]) In [151]: data.fillna(data.mean()) Out[151]: 0 1.000000 1 3.833333 2 3.500000 3 3.833333 4 7.000000 dtype: float64 


5.5层次化索引
层次化索引,是你能在一个轴上拥有多个(两个以上)索引级别。
即能以低纬度形式处理高纬度数据。

咱们来建立一个Series,并用一个由列表或数组组成的列表做为索引:

In [152]: data=Series(np.random.randn(10),index=[['a','a','a','b','b','b','c','c','d','d'],[1,2,3,1,2,3,1,2,2,3]]) In [153]: data Out[153]: a 1 0.024162 2 0.969526 3 -0.215712 b 1 1.136933 2 -0.158487 3 0.482377 c 1 -0.551888 2 -1.090750 d 2 -0.073204 3 -1.217613 dtype: float64 



这就是带有MultiIndex 索引的Series 的格式输出格式。索引之间的“间隔”表示“直接使用上面的标签”:

In [154]: data.index Out[154]: MultiIndex(levels=[[u'a', u'b', u'c', u'd'], [1, 2, 3]], labels=[[0, 0, 0, 1, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 1, 2, 0, 1, 1, 2]]) 


对于一个层次化索引的对象,选取数据子集的操做很简单:

data['b'] Out[155]: 1 1.136933 2 -0.158487 3 0.482377 dtype: float64 data['b':'c'] Out[156]: b 1 1.136933 2 -0.158487 3 0.482377 c 1 -0.551888 2 -1.090750 dtype: float64 data.ix[['b','d']] Out[158]: b 1 1.136933 2 -0.158487 3 0.482377 d 2 -0.073204 3 -1.217613 dtype: float64 


甚至还能够在“内层”中进行选取:

In [159]: data[:,2] Out[159]: a 0.969526 b -0.158487 c -1.090750 d -0.073204 dtype: float64 


层次化索引的在数据重塑和基于分组的操做(如透视表生成)中扮演重要角色。好比说,这段数据能够经过unstack方法被从新安排到一个DataFrame中:

n [160]: data.unstack() Out[160]: 1 2 3 a 0.024162 0.969526 -0.215712 b 1.136933 -0.158487 0.482377 c -0.551888 -1.090750 NaN d NaN -0.073204 -1.21761 


unstack的逆运算是stack:

In [161]: data.unstack().stack() Out[161]: a 1 0.024162 2 0.969526 3 -0.215712 b 1 1.136933 2 -0.158487 3 0.482377 c 1 -0.551888 2 -1.090750 d 2 -0.073204 3 -1.217613 dtype: float64 


对于一个DataFrame,每条轴均可以分层索引:

In [162]: frame=DataFrame(np.arange(12).reshape((4,3)),index=[['a','a','b','b'],[1,2,1,2]],columns=[['Ohio','Ohio','Colorado'],['Green','Red','Green']]) In [163]: frame Out[163]: Ohio Colorado Green Red Green a 1 0 1 2 2 3 4 5 b 1 6 7 8 2 9 10 11 


各层均可以有名字(能够是字符串,也能够是python对象)。若是指定了名称,他们就会显示在控制台输出中:

In [164]: frame.index.names=['key1','key2'] In [165]: frame.columns.names=['state','color'] In [166]: frame Out[166]: state Ohio Colorado color Green Red Green key1 key2 a 1 0 1 2 2 3 4 5 b 1 6 7 8 2 9 10 11 


有了分部的列索引,所以能够选取列分组:

In [167]: frame['Ohio'] Out[167]: color Green Red key1 key2 a 1 0 1 2 3 4 b 1 6 7 2 9 10 


能够单独的建立MultiIndex 而后复用,上面那个DataFrame中的(分级)列能够这样建立:

In [168]: MultiIndex.from_arrays([['Ohio','Ohio','Colorado'],['Green','Red','Green']],names=['state','color']) 


5.5.1重排分级顺序
若是须要调整某条轴上各级别的顺序,或根据指定界级别上的值对数据进行排序。swaplevel接受两个级别编号或名称,并返回一个互换级别的新对象(但数据不会发生变化):

In [169]: frame.swaplevel('key1','key2') Out[169]: state Ohio Colorado color Green Red Green key2 key1 1 a 0 1 2 2 a 3 4 5 1 b 6 7 8 2 b 9 10 11 


而sortleval则根据单个级别中的值对数据进行排序(稳定的)。交流级别时,经常也会用到sortlevel,这样最终的结果就是有序的了:

In [170]: frame.sortlevel(1) Out[170]: state Ohio Colorado color Green Red Green key1 key2 a 1 0 1 2 b 1 6 7 8 a 2 3 4 5 b 2 9 10 11 In [172]: frame.swaplevel(0,1).sortlevel(0) Out[172]: state Ohio Colorado color Green Red Green key2 key1 1 a 0 1 2 b 6 7 8 2 a 3 4 5 b 9 10 11 


5.5.2根据级别汇总统计
许多对DataFrame 和Series的描述和汇总统计都有一个leve选项,用于指定在某条轴上对求和的级别,再也上面的那个DataFrame为例子,咱们根据行或列上的级别进行求和:

In [173]: frame.sum(level='color',axis=1) Out[173]: color Green Red key1 key2 a 1 2 1 2 8 4 b 1 14 7 2 20 10 In [174]: frame.sum(level='key2') Out[174]: state Ohio Colorado color Green Red Green key2 1 6 8 10 2 12 14 16 

5.5.3使用DataFrame的列
将DataFrame的一个或多个列当作行索引来用,或者可能但愿将行索引变成DataFrame要的列。

In [14]: frame=DataFrame({'a':range(7),'b':range(7,0,-1), 'c':['one','one','one','two','two','two','two'],'d':[0,1,2,0,1,2,3]}) In [15]: frame Out[15]: a b c d 0 0 7 one 0 1 1 6 one 1 2 2 5 one 2 3 3 4 two 0 4 4 3 two 1 5 5 2 two 2 6 6 1 two 3 


DataFrame的set_index函数会将一个或多个列转换为行索引,并建立一个新的DataFrame:

In [17]: frame2 Out[17]: a b c d one 0 0 7 1 1 6 2 2 5 two 0 3 4 1 4 3 2 5 2 3 6 1 


默认状况下,那些列会从DataFrame中移除,可是也能够将其保留:

In [18]: frame.set_index(['c','d'],drop=False) Out[18]: a b c d c d one 0 0 7 one 0 1 1 6 one 1 2 2 5 one 2 two 0 3 4 two 0 1 4 3 two 1 2 5 2 two 2 3 6 1 two 3 


reset_index的功能跟set_index恰好相反,层次化索引的级别会被转移到列里面:

In [20]: frame2.reset_index() Out[20]: c d a b 0 one 0 0 7 1 one 1 1 6 2 one 2 2 5 3 two 0 3 4 4 two 1 4 3 5 two 2 5 2 6 two 3 6 1 


5.6其余有关pandas的话题
5.6.1整数索引
操做由整数索引的pandas对象经常会让新手抓狂,由于他们跟内置的python数据结构(如列表和元组)在索引语义上有些不一样。
例如,你可能认为下面的代码不会报错。

In [24]: ser=Series(np.arange(3.)) In [25]: ser[-1] --------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-25-3cbe0b873a9e> in <module>() ----> 1 ser[-1] pandas\src\hashtable_class_helper.pxi in pandas.hashtable.Int64HashTable.get_item (pandas\hashtable.c:85 08)() KeyError: -1L 


虽然pandas会“求助于”整数索引,可是没有哪一种方法可以既不引入bug,又能解决问题的。
咱们有一个含有0,1,2的索引,可是很难推断出用户想要什么:

In [26]: ser Out[26]: 0 0.0 1 1.0 2 2.0 dtype: float64 


相反,对于一个非整数索引,就没有这样的歧义:

In [30]: ser2=Series(np.arange(3.),index=['a','b','c']) In [31]: ser2[-1] Out[31]: 2.0 


为了保持良好的一致性,若是你的轴索引含有索引器,那么根据整数进行数据选取的操做蒋老是面向标签的。这也包括用ix进行切片:

In [32]: ser.ix[:1] Out[32]: 0 0.0 1 1.0 dtype: float64 


若是须要可靠的,不考虑索引类型的,基于位置的索引,可使用Series 的 iget_value 方法和DataFrame的irow和icol方法:

In [33]: ser3=Series(range(3),index=[-5,1,3]) In [35]: ser3.iget_value(2) Out[35]: 2 In [37]: frame=DataFrame(np.arange(6).reshape(3,2),index=[2,0,1]) In [38]: frame.irow(0) Out[38]: 0 0 1 1 Name: 2, dtype: int32 



声明:

以上学习笔记来自

《利用python进行数据分析》Wes McKinney 编著 唐学韬等译 机械工业出版社

相关文章
相关标签/搜索