Reindexing
处理pandas对象的一个重要的方法是reindex,就是把索引重新命名。比如:
In [1]: import pandas as pd
In [2]: obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
In [3]: obj
Out[3]:
d 4.5
b 7.2
a -5.3
c 3.6
dtype: float64
In [4]: obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])
In [5]: obj2 #缺失值会显示NaN
Out[5]:
a -5.3
b 7.2
c 3.6
d 4.5
e NaN
dtype: float64
在重新命名索引的同时,你可以进行值的填补,通过method
这一参数设置可以实现:
In [6]: obj3 = pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])
In [7]: obj3
Out[7]:
0 blue
2 purple
4 yellow
dtype: object
In [8]: obj3.reindex(range(6),method='ffill')
Out[8]:
0 blue
1 blue
2 purple
3 purple
4 yellow
5 yellow
dtype: object
上面是对Series数据结构进行操作,那么对于DateFrame数据结构来说,reindex
可以改变行的索引,也可以改变列的索引:
In [10]: import numpy as np
In [11]: frame = pd.DataFrame(np.arange(9).reshape((3, 3)),
...: index=['a', 'c', 'd'],
...: columns=['Ohio', 'Texas', 'California'])
In [12]: frame
Out[12]:
Ohio Texas California
a 0 1 2
c 3 4 5
d 6 7 8
In [13]: frame2 = frame.reindex(['a', 'b', 'c', 'd'])
In [14]: frame2
Out[14]:
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
In [15]: states = ['Texas', 'Utah', 'California']
In [16]: frame.reindex(columns=states)
Out[16]:
Texas Utah California
a 1 NaN 2
c 4 NaN 5
d 7 NaN 8
Dropping Entries from an Axis
从坐标轴中删除条目,也就是删除一行或者多行,用drop
功能实现,首先看一个Series的例子:
In [18]: obj = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])
In [19]: obj
Out[19]:
a 0.0
b 1.0
c 2.0
d 3.0
e 4.0
dtype: float64
In [20]: new_obj = obj.drop('c')
In [21]: new_obj
Out[21]:
a 0.0
b 1.0
d 3.0
e 4.0
dtype: float64
In [23]: obj.drop(['d','c'])
Out[23]:
a 0.0
b 1.0
e 4.0
dtype: float64
再看一下从DataFrame里删除某一行或者多行:
In [24]: data = pd.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.drop(['Colorado','Ohio'])
Out[26]:
one two three four
Utah 8 9 10 11
New York 12 13 14 15
删除某一列:
#方法一
In [27]: data.drop('two',axis=1)
Out[27]:
one three four
Ohio 0 2 3
Colorado 4 6 7
Utah 8 10 11
New York 12 14 15
#方法二
In [28]: data.drop(['two','four'],axis='columns')
Out[28]:
one three
Ohio 0 2
Colorado 4 6
Utah 8 10
New York 12 14
Function Application and Mapping
Numpy的一些功能也适用于pandas的对象:
比如,对一个DataFrame里的元素取绝对值:
In [37]: frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'),
...: index=['Utah', 'Ohio', 'Texas', 'Oregon'])
In [38]: frame
Out[38]:
b d e
Utah -0.572804 0.721932 -0.444059
Ohio 0.703145 -0.214176 -1.101471
Texas 0.874537 -0.498817 1.475840
Oregon -0.122831 -0.582037 -0.465144
In [39]: np.abs(frame)
Out[39]:
b d e
Utah 0.572804 0.721932 0.444059
Ohio 0.703145 0.214176 1.101471
Texas 0.874537 0.498817 1.475840
Oregon 0.122831 0.582037 0.465144
求dataframe里每一列里最大值与最小值的差:
In [40]: f = lambda x: x.max() - x.min()
In [41]: frame.apply(f)
Out[41]:
b 1.447342
d 1.303969
e 2.577311
dtype: float64
求dataframe每一行的最大值与最小值的差:
In [42]: frame.apply(f, axis='columns') #这里你没看错,写的是columns,但是求的是每行里的最大值与最小值的差
Out[42]:
Utah 1.294737
Ohio 1.804616
Texas 1.974657
Oregon 0.459206
dtype: float64
上面的apply
功能只是求出差值,并不能返回每一行或者每一列的最大值和最小值是多少,下面这种方法可以实现这个要求:
In [43]: def f(x):
...: return pd.Series([x.min(),x.max()],index=['min', 'max'])
...:
In [44]: frame.apply(f)
Out[44]:
b d e
min -0.572804 -0.582037 -1.101471
max 0.874537 0.721932 1.475840
Sorting and Ranking
根据某些条件进行筛选dataset也是一个重要的内置功能。可以通过行索引和列索引进行字典的筛选,使用sort_index
方法,返回一个新的对象:
#对Series进行sorting
In [45]: obj = pd.Series(range(4), index=['d', 'a', 'b', 'c'])
In [46]: obj
Out[46]:
d 0
a 1
b 2
c 3
dtype: int64
In [47]: obj.sort_index()
Out[47]:
a 1
b 2
c 3
d 0
dtype: int64
#对dataframe进行sorting
In [48]: frame = pd.DataFrame(np.arange(8).reshape((2, 4)),
...: index=['three', 'one'],
...: columns=['d', 'a', 'b', 'c'])
In [49]: frame
Out[49]:
d a b c
three 0 1 2 3
one 4 5 6 7
In [50]: frame.sort_index()
Out[50]:
d a b c
one 4 5 6 7
three 0 1 2 3
按照轴来排序:
In [51]: frame.sort_index(axis=1) #轴1就是对列进行排序
Out[51]:
a b c d
three 1 2 3 0
one 5 6 7 4
In [52]: frame.sort_index(axis=0) #轴0就是对行进行排序
Out[52]:
d a b c
one 4 5 6 7
three 0 1 2 3
根据降序排列:
In [53]: frame.sort_index(axis=1, ascending=False)
Out[53]:
d c b a
three 0 3 2 1
one 4 7 6 5
按照某一列进行降序排列:
In [54]: frame.sort_values(by='b',ascending=False)
Out[54]:
d a b c
one 4 5 6 7
three 0 1 2 3
下面是ranking的用法了,这里有点绕,我尽量用“人话”解释清楚:
In [59]: obj = pd.Series([7, -5, 7, 4, 2, 0, 4])
In [60]: obj.rank()
Out[60]:
0 6.5
1 1.0
2 6.5
3 4.5
4 3.0
5 2.0
6 4.5
dtype: float64
上面是一个Series的ranking,根据有些文章里解释的意思,大家可以感受一下:
排名(ranking ) 跟排序关系密切, 且它会增设一个排名值(从1开始, 一直到数组中有效数据的数量)。它跟numpy.argsort产生的间接拍下索引差不多, 只不过它可以根据某种规则破坏平级关系。接下来介绍Series和Dataframe 的rank方法。默认情况下, rank是通过”为各组分配一个平均排名“的方式破坏平级关系的。
反正我是没看懂。。。也可能是我水平有限,实际上上面的obj.rank()功能可以这样理解:
[7, -5, 7, 4, 2, 0, 4]里最小值是-5,所以索引为1的元素就是“1.0”。然后排第二小的是0,那么0的索引值是5的位置就是“2.0”。接着排第3的2也比较好理解。之后有两个“4”,这两个“4”分别排第4和第5(并列),那么ranking的值就是4和5的平均数4.5。最后,两个7的排名分别是6和7(并列),所以在对应的索引位置是6和7的平均数6.5。
然后来看一下dataframe的ranking:
In [61]: frame = pd.DataFrame({'b': [4.3, 7, -3, 2], 'a': [0, 1, 0, 1],
...: 'c': [-2, 5, 8, -2.5]})
In [62]: frame
Out[62]:
b a c
0 4.3 0 -2.0
1 7.0 1 5.0
2 -3.0 0 8.0
3 2.0 1 -2.5
In [64]: frame.rank()
Out[64]:
b a c
0 3.0 1.5 2.0
1 4.0 3.5 3.0
2 1.0 1.5 4.0
3 2.0 3.5 1.0
Axis Indexes with Duplicate Labels
到目前为止,我们看到的所有示例都有唯一的axis索引值。而许多panda函数(如reindex
)要求标签是唯一,但这不是强制性的。比如:
In [65]: obj = pd.Series(range(5), index=['a', 'a', 'b', 'b', 'c'])
In [66]: obj
Out[66]:
a 0
a 1
b 2
b 3
c 4
dtype: int64
In [67]: obj.index.is_unique #检查索引值是否唯一
Out[67]: False