pandas对象的一个重要的方法就是reindex,作用是创建一个适应新索引的新对象。
>>> import numpy as np
>>> 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
调用该Series的reindex将会根据新索引进行重排。如果某个索引值当前不存,就引入缺失值:
>>> obj1=obj.reindex(['a','b','c','d','e'])
>>> 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
对于时间序列这样的有序数据,重新索引时可能需要做一些插值处理。method选项即可用达到此目的。例如:ffill可以实现向前值填充:
>>> obj3=Series(['blue','purple','yellow'],index=[0,2,4])
>>> 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
下面列出了可用的method选项。
对于DataFrame,reindex可以修改(行)索引,列,或两个都修改。如果仅传入一个序列,则会重新索引行:
>>> frame=DataFrame(np.arange(9).reshape((3,3)),index=['a','c','d'],columns=['Ohio','Texas','California',]
... )
>>> 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
利用columns关键字可以重新索引列:
>>> frame.reindex(columns=['Texas','Cali','Ohio'])
Texas Cali Ohio
a 1 NaN 0
c 4 NaN 3
d 7 NaN 6
利用ix的标签的索引功能,重新索引任务可以变得简洁:
>>> 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
使用drop方法删除某条轴上的一个或多个项,返回删除后的新对象。
>>> obj=Series(np.arange(5.),index=['a','b','c','d','e'])
>>> obj1=obj.drop('c')
>>> obj1
a 0.0
b 1.0
d 3.0
e 4.0
dtype: float64
对于DataFrame,通过指定axis,可以删除任意轴上的索引值:
>>> 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
Series索引 (obj[...])的工作方式类似于NumPy数组的索引,只不过Series的索引值不只是整数。例:
>>> obj=Series(np.arange(4.),index=['a','b','c','d'])
>>> 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
利用标签的切片运算与普通的python切片运算不同,其末端是包含的(inclusive)
>>> obj['b':'c']
b 1.0
c 2.0
dtype: float64
设置值的方式如下:
>>> obj['b':'c']=5
>>> obj
a 0.0
b 5.0
c 5.0
d 3.0
dtype: float64
对DataFrame进行索引其实就是获取一个或多个列:
>>> 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
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在语法上像ndarray
>>> 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
>>> 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
由上可以看出对DataFrame选取和重排有许多种方法,下表列出了大部分的索引和重排方式:
pandas最重要的一个功能是他可以对不同索引的对象进行算数运算。在将对象相加时,如果存在不同的索引,
则结果的索引就是该索引对的并集。来看一个简单的例子:
>>> s1=Series([7.3,-2.5,3.4,1.5],index=['a','c','d','e'])
>>> 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
可以看到,自动的数据对其操作在不重叠的索引处引入了NA值。缺失值会在算术运算过程中传播。
>>> 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
在不同索引的对象进行算术运算时,你可能希望当一个对象中某个轴标签在另一个对象张找不到时填充一个值:
>>> df1=DataFrame(np.arange(12.).reshape((3,4)),columns=list('abcd'))
>>> 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
由上可以看出,使用add方法和fill_value属性可以将没有重叠的位置填充上值。
类似的,对Series或DataFrame重新索引时,也可以指定一个填充值:
>>> df1.reindex(columns=df2.columns)
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
pandas中的算数方法如下:
跟NumPy数组一样,DataFrame和Series的=之间的算术运算也是有明确规定的。
下面来计算一个二维数组与其某行之间的差:
>>> arr=np.arange(12.).reshape((3,4))
>>> 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.]])
使用arr-arr[0]就相当于用arr的每一行去减去arr的第一行,这种运算叫做广播。
>>> 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']
>>> 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
通过设置axis属性来达到在列上传播。
Numpy的ufuncs(元素级数组方法)也可以用于操作pandas对象:
>>> frame=DataFrame(np.random.randn(4,3),columns=list('bde'),index=['Utah','Ohio','Texas','Oregon'])
>>> 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
另一个常见的操作,将函数应用到由各列或行所形成的一维数组上。DataFrame的apply方法即可实现此功能:
>>> f=lambda x:x.max() - x.min() #
>>> 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方法不会经常使用,因为常用的函数都已经被实现为DataFrame的方法(如sum和mean)
>>> def f(x):
... 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
使用applymap可以将函数作用到每一个元素上:
>>> 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
>>> 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
而Series中作用于每一个元素的方法是map方法
>>> frame['e'].map(format)
Utah -1.19
Ohio 0.10
Texas -1.38
Oregon 1.11
Name: e, dtype: object
根据条件对数据集排序也是一种重要的内置运算。要对行或列索引进行排序(按字典顺序),可以使用sort_index方法,它将返回一个已经排序的新对象:
>>> obj=Series(range(4),index=['d','a','b','c'])
>>> obj.sort_index()
a 1
b 2
c 3
d 0
dtype: int64
而对于DataFrame,则可以根据任意一个轴上的索引进行排序:
>>> 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)
d c b a
three 0 3 2 1
one 4 7 6 5
在DataFrame上,你可能希望根据一个或多个列中的值进行排序。将一个或多个列的名字传递给by选项即可达到该目的:
>>> 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
要根据多个列进行排序,传入名称的列表即可。
>>> 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')
0 2.0
1 7.0
2 2.0
3 4.0
4 5.0
5 6.0
6 4.0
dtype: float64
DataFrame可以在行或列上计算排名:
>>> frame=DataFrame({'b':[4.3,7,-3,2],'a':[0,1,0,1],'c':[-2,5,8,-2.5]})
>>> 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的可选项:
method 说明
‘average’ 默认:在相等分组中,为各个值分配平均排‘’
‘min’ 使用整个分组的最小排名
‘max’ 使用整个分组的最大排名
‘first’ 按值在原始数据中的出现顺序分配排名
我们看看下面这个简单的带有重复索引值的Series:
>>> obj=Series(range(5),index=['a','a','b','b','c'])
>>> obj
a 0
a 1
b 2
b 3
c 4
dtype: int64
索引的is_unique属性可以告诉你他的值是否是唯一的:
>>> obj.index.is_unique
False
>>> frame.index.is_unique
True
对于重复的索引,数据选取的行为将会有些不同。如果某个索引对应的多个值,则返回一个Series,而对应单个值,则返回一个标量:
>>> obj['a']
a 0
a 1
dtype: int64
>>> obj['c']
4
对DataFrame的行进行索引时候也是如此:
>>> 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进行数据分析》