1.重新索引
pandas对象的一个重要的方法就是reindex,作用是创建一个适应新索引的新对象。
>>> import numpy as np调用该Series的reindex将会根据新索引进行重排。如果某个索引值当前不存,就引入缺失值:
>>> import pandas as pd
>>> from pandas import Series,DataFrame
>>> obj=Series([4.5,7.2,-5.3,3.6],index=['d','b','a','c'])
>>> obj
d 4.5
b 7.2
a -5.3
c 3.6
dtype: float64
>>> obj1=obj.reindex(['a','b','c','d','e'])对于时间序列这样的有序数据,重新索引时可能需要做一些插值处理。method选项即可用达到此目的。例如:ffill可以实现向前值填充:
>>> obj1
a -5.3
b 7.2
c 3.6
d 4.5
e NaN
dtype: float64
>>> obj.reindex(['a','b','c','d','e'],fill_value=0) #指定缺失值
a -5.3
b 7.2
c 3.6
d 4.5
e 0.0
dtype: float64
>>> obj3=Series(['blue','purple','yellow'],index=[0,2,4])下面列出了可用的method选项。
>>> obj3.reindex(range(6))
0 blue
1 NaN
2 purple
3 NaN
4 yellow
5 NaN
dtype: object
>>> obj3.reindex(range(6),method='ffill')
0 blue
1 blue
2 purple
3 purple
4 yellow
5 yellow
dtype: object
参数 说明
ffill或pad 前向填充(或搬运)值
bfill或backfill 后向填充(或搬运)值
对于DataFrame,reindex可以修改(行)索引,列,或两个都修改。如果仅传入一个序列,则会重新索引行:
>>> frame=DataFrame(np.arange(9).reshape((3,3)),index=['a','c','d'],columns=['Ohio','Texas','California',]利用columns关键字可以重新索引列:
... )
>>> frame
Ohio Texas California
a 0 1 2
c 3 4 5
d 6 7 8
>>> frame1=frame.reindex(['a','b','c','d'])
>>> frame1
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
>>> frame.reindex(columns=['Texas','Cali','Ohio'])利用ix的标签的索引功能,重新索引任务可以变得简洁:
Texas Cali Ohio
a 1 NaN 0
c 4 NaN 3
d 7 NaN 6
>>> states=['Texas','Utah','California']
>>> index=['a','b','c','d']
>>> frame.ix[index,states]
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
2.删除指定轴上的项
使用drop方法删除某条轴上的一个或多个项,返回删除后的新对象。
>>> obj=Series(np.arange(5.),index=['a','b','c','d','e'])对于DataFrame,通过指定axis,可以删除任意轴上的索引值:
>>> obj1=obj.drop('c')
>>> obj1
a 0.0
b 1.0
d 3.0
e 4.0
dtype: float64
>>> data=DataFrame(np.arange(16).reshape((4,4)),index=['Ohio','Colorado','Utah','New York'],columns=['one','two','three','four'])
>>> data
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
>>> data.drop('two',axis=1)
one three four
Ohio 0 2 3
Colorado 4 6 7
Utah 8 10 11
New York 12 14 15
>>> data.drop('Ohio',axis=0)
one two three four
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15
3.索引、选取和过滤
Series索引 (obj[...])的工作方式类似于NumPy数组的索引,只不过Series的索引值不只是整数。例:
>>> obj=Series(np.arange(4.),index=['a','b','c','d'])利用标签的切片运算与普通的python切片运算不同,其末端是包含的(inclusive)
>>> obj['b']
1.0
>>> obj[1] #或许可以理解为数组的下标吧
1.0
>>> obj[2:4]
c 2.0
d 3.0
dtype: float64
>>> obj[obj<2]
a 0.0
b 1.0
dtype: float64
>>> obj['b':'c']设置值的方式如下:
b 1.0
c 2.0
dtype: float64
>>> obj['b':'c']=5对DataFrame进行索引其实就是获取一个或多个列:
>>> obj
a 0.0
b 5.0
c 5.0
d 3.0
dtype: float64
>>> data=DataFrame(np.arange(16).reshape((4,4)),选取行可以通过切片或布尔数组进行
... index=['Ohio','Colorado','Utah','New York'],columns=['one','two','three','four'])
>>> data[['three','one']]
three one
Ohio 2 0
Colorado 6 4
Utah 10 8
New York 14 12
>>> data[:2]
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
>>> data[data['three']>5]
one two three four
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15
另一种用法使通过布尔型DataFrame进行索引:
>>> data<5这段代码使得DataFrame在语法上像ndarray
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
>>> data[data<5]=0
>>> data
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的行上进行标签索引,我们引入专门的索引字段ix。使得你通过numpy式的标记法以及轴标签的从DataFrame中选取行和列的子集。这是重现索引的简单手段:
>>> data由上可以看出对DataFrame选取和重排有许多种方法,下表列出了大部分的索引和重排方式:
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
>>> data.ix['Colorado',['two','three']] #选取Colorado行,第two,three列
two 5
three 6
Name: Colorado, dtype: int32
>>> data.ix[['Colorado','Utah'],[3,0,1]] #选取Colorado行,第3,0,1列
four one two
Colorado 7 0 5
Utah 11 8 9
>>> data.ix[2] #选取第二行
one 8
two 9
three 10
four 11
Name: Utah, dtype: int32
>>> data.ix[data.three>5,:3] #选出three列大于5的行的前三列
one two three
Colorado 0 5 6
Utah 8 9 10
New York 12 13 14
4.算数运算和数据对齐
pandas最重要的一个功能是他可以对不同索引的对象进行算数运算。在将对象相加时,如果存在不同的索引,
则结果的索引就是该索引对的并集。来看一个简单的例子:
>>> s1=Series([7.3,-2.5,3.4,1.5],index=['a','c','d','e'])可以看到,自动的数据对其操作在不重叠的索引处引入了NA值。缺失值会在算术运算过程中传播。
>>> s2=Series([-2.1,3.6,-1.5,4,3.1],index=['a','c','e','f','g'])
>>> s1
a 7.3
c -2.5
d 3.4
e 1.5
dtype: float64
>>> s2
a -2.1
c 3.6
e -1.5
f 4.0
g 3.1
dtype: float64
>>> s1+s2 #
a 5.2
c 1.1
d NaN
e 0.0
f NaN
g NaN
dtype: float64
对于DataFrame,对齐操作会同时发生在行和列上:
>>> df1=DataFrame(np.arange(9.).reshape((3,3)),columns=list('bcd'),index=['Ohio','Texas','Colorado'])
>>> df2=DataFrame(np.arange(12.).reshape((4,3)),columns=list('bde'),index=['Utah','Ohio','Texas','Oregon'])
>>> df1
b c d
Ohio 0.0 1.0 2.0
Texas 3.0 4.0 5.0
Colorado 6.0 7.0 8.0
>>> df2
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
>>> df1+df2
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.在算数方法中填充值
在不同索引的对象进行算术运算时,你可能希望当一个对象中某个轴标签在另一个对象张找不到时填充一个值:
>>> df1=DataFrame(np.arange(12.).reshape((3,4)),columns=list('abcd'))由上可以看出,使用add方法和fill_value属性可以将没有重叠的位置填充上值。
>>> df2=DataFrame(np.arange(20.).reshape((4,5)),columns=list('abcde'))
>>> df1
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
>>> df2
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
>>> df1.add(df2,fill_value=0) #直接相加会产生NA值
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重新索引时,也可以指定一个填充值:
>>> df1.reindex(columns=df2.columns)pandas中的算数方法如下:
a b c d e
0 0.0 1.0 2.0 3.0 NaN
1 4.0 5.0 6.0 7.0 NaN
2 8.0 9.0 10.0 11.0 NaN
>>> df1.reindex(columns=df2.columns,fill_value=0)
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
方法 说明
add 用于加法(+)的方法
sub 用于减法(-)的方法
div 用于乘法(*)的方法
mul 用于除法(/)的方法
6.DataFrame和Series之间的运算
跟NumPy数组一样,DataFrame和Series的=之间的算术运算也是有明确规定的。
下面来计算一个二维数组与其某行之间的差:
>>> arr=np.arange(12.).reshape((3,4))使用arr-arr[0]就相当于用arr的每一行去减去arr的第一行,这种运算叫做广播。
>>> arr[0]
array([ 0., 1., 2., 3.])
>>> arr
array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
>>> arr-arr[0]
array([[ 0., 0., 0., 0.],
[ 4., 4., 4., 4.],
[ 8., 8., 8., 8.]])
DataFrame和Series之间的运算差不多也是如此:
>>> frame=DataFrame(np.arange(12.).reshape((4,3)),columns=list('bde'),index=['Utah','Ohio','Texas','Oregon']可以看到,和二维数组的运算是相似的。
... )
>>> series=frame.ix[0]
>>> frame
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
>>> series
b 0.0
d 1.0
e 2.0
Name: Utah, dtype: float64
>>> frame-series
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
如果你希望匹配行且在列上广播,则必须使用算术运算方法:
>>> series3=frame['d']通过设置axis属性来达到在列上传播。
>>> frame
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
>>> series3
Utah 1.0
Ohio 4.0
Texas 7.0
Oregon 10.0
Name: d, dtype: float64
>>> frame.sub(series3,axis=0)
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
7.函数应用和映射
Numpy的ufuncs(元素级数组方法)也可以用于操作pandas对象:
>>> frame=DataFrame(np.random.randn(4,3),columns=list('bde'),index=['Utah','Ohio','Texas','Oregon'])另一个常见的操作,将函数应用到由各列或行所形成的一维数组上。DataFrame的apply方法即可实现此功能:
>>> frame
b d e
Utah 0.778854 -0.519687 -1.185915
Ohio -2.189872 -0.812754 0.099398
Texas 0.227312 -0.839251 -1.382977
Oregon 0.518163 -0.506687 1.110223
>>> np.abs(frame)
b d e
Utah 0.778854 0.519687 1.185915
Ohio 2.189872 0.812754 0.099398
Texas 0.227312 0.839251 1.382977
Oregon 0.518163 0.506687 1.110223
>>> f=lambda x:x.max() - x.min() #apply方法不会经常使用,因为常用的函数都已经被实现为DataFrame的方法(如sum和mean)
>>> frame.apply(f) #将函数作用于每一列
b 2.968725
d 0.332564
e 2.493200
dtype: float64
>>> frame.apply(f,axis=1) #将函数作用于每一行
Utah 1.964769
Ohio 2.289270
Texas 1.610289
Oregon 1.616909
dtype: float64
除标量外,传递给apply的函数还可以返回由多个值组成的Series
>>> def f(x):使用applymap可以将函数作用到每一个元素上:
... return Series([x.min(),x.max()],index=['min','max'])
...
>>> frame.apply(f)
b d e
min -2.189872 -0.839251 -1.382977
max 0.778854 -0.506687 1.110223
>>> frame而Series中作用于每一个元素的方法是map方法
b d e
Utah 0.778854 -0.519687 -1.185915
Ohio -2.189872 -0.812754 0.099398
Texas 0.227312 -0.839251 -1.382977
Oregon 0.518163 -0.506687 1.110223
>>> format=lambda x:'%.2f' %x
>>> frame.applymap(format)
b d e
Utah 0.78 -0.52 -1.19
Ohio -2.19 -0.81 0.10
Texas 0.23 -0.84 -1.38
Oregon 0.52 -0.51 1.11
>>> frame['e'].map(format)
Utah -1.19
Ohio 0.10
Texas -1.38
Oregon 1.11
Name: e, dtype: object
8.排序和排名
根据条件对数据集排序也是一种重要的内置运算。要对行或列索引进行排序(按字典顺序),可以使用sort_index方法,它将返回一个已经排序的新对象:
>>> obj=Series(range(4),index=['d','a','b','c'])而对于DataFrame,则可以根据任意一个轴上的索引进行排序:
>>> obj.sort_index()
a 1
b 2
c 3
d 0
dtype: int64
>>> frame=DataFrame(np.arange(8).reshape((2,4)),index=['three','one'],columns=['d','a','b','c'])数据默认是按升序排列的,但也可以降序排序:
>>> frame.sort_index()
d a b c
one 4 5 6 7
three 0 1 2 3
>>> frame.sort_index(axis=1)
a b c d
three 1 2 3 0
one 5 6 7 4
>>> frame.sort_index(axis=1,ascending=False)在DataFrame上,你可能希望根据一个或多个列中的值进行排序。将一个或多个列的名字传递给by选项即可达到该目的:
d c b a
three 0 3 2 1
one 4 7 6 5
>>> frame=DataFrame({'b':[4,7,-3,2],'a':[0,1,0,1]})要根据多个列进行排序,传入名称的列表即可。
>>> frame
a b
0 0 4
1 1 7
2 0 -3
3 1 2
>>> frame.sort_index(by='b')
__main__:1: FutureWarning: by argument to sort_index is deprecated, pls use .sort_values(by=...)
a b
2 0 -3
3 1 2
0 0 4
1 1 7
排名(ranking)跟排序关系密切,且会增设一个排名值(从1开始,一直到数组中有效数据的数量),跟numpy.argsort产生的间接排序索引差不多,只不过它可以根据某种规则破坏平级关系。下面介绍Series和DataFrame的rank方法。默认下:rank是通过“为各组分配一个平均排名”的方式来破坏平级关系。
>>> obj=Series([7,-5,7,4,2,0,4])也可以根据值在原数据中出现的顺序给出排名:
>>> obj.rank()
0 6.5
1 1.0
2 6.5
3 4.5
4 3.0
5 2.0
6 4.5
dtype: float64
>>> obj
0 7
1 -5
2 7
3 4
4 2
5 0
6 4
dtype: int64
>>> obj.rank(method='first')也可以按降序进行排名:
0 6.0
1 1.0
2 7.0
3 4.0
4 3.0
5 2.0
6 5.0
dtype: float64
>>> obj.rank(ascending=False,method='max')DataFrame可以在行或列上计算排名:
0 2.0
1 7.0
2 2.0
3 4.0
4 5.0
5 6.0
6 4.0
dtype: float64
>>> frame=DataFrame({'b':[4.3,7,-3,2],'a':[0,1,0,1],'c':[-2,5,8,-2.5]})下面列出了method的可选项:
>>> frame
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
>>> frame.rank(axis=1)
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
method 说明
‘average’ 默认:在相等分组中,为各个值分配平均排‘’
‘min’ 使用整个分组的最小排名
‘max’ 使用整个分组的最大排名
‘first’ 按值在原始数据中的出现顺序分配排名
9.带有重复值的索引
我们看看下面这个简单的带有重复索引值的Series:
>>> obj=Series(range(5),index=['a','a','b','b','c'])索引的is_unique属性可以告诉你他的值是否是唯一的:
>>> obj
a 0
a 1
b 2
b 3
c 4
dtype: int64
>>> obj.index.is_unique对于重复的索引,数据选取的行为将会有些不同。如果某个索引对应的多个值,则返回一个Series,而对应单个值,则返回一个标量:
False
>>> frame.index.is_unique
True
>>> obj['a']对DataFrame的行进行索引时候也是如此:
a 0
a 1
dtype: int64
>>> obj['c']
4
>>> df=DataFrame(np.random.randn(4,3),index=['a','a','b','b'])
>>> df
0 1 2
a -1.932050 -1.271340 0.491396
a -0.105177 -0.169603 0.652282
b -0.111812 0.970321 -0.650144
b -0.706707 1.816764 -1.013891
>>> df.ix['b']
0 1 2
b -0.111812 0.970321 -0.650144
b -0.706707 1.816764 -1.013891
参考:
《利用python进行数据分析》