一.基本功能

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

In [14]: obj3=Series(['red','yellow','blue'],index=[0,2,4])

In [15]: obj3
Out[15]:
0 red
2 yellow
4 blue
dtype: object

In [16]: obj3.reindex(range(6),method='ffill')
Out[16]:
0 red
1 red
2 yellow
3 yellow
4 blue
5 blue
dtype: object

下表列出了可用的method选项,其实我们有时需要比前向和后向填充更为精准的插值方式。

参数                                                     说明

ffill或pad                                     前向填充(或搬运)值

bfill或backfill                                后向填充(或搬运)值

 

对于DataFrame,reindex可以修改(行)索引、列、或两个都修改。如果仅传入一个序列,则会重新索引行:

In [19]: frame=DataFrame(np.arange(9).reshape((3,3)),index=['a','b','c'],column
...: s=['Calvin','Kobe','Michale'])

In [20]: frame
Out[20]:
  Calvin Kobe Michale
a   0       1            2
b   3       4            5
c 6 7 8

In [21]: frame2=frame.reindex(['b','c','d','e'])

In [22]: frame2
Out[22]:
   Calvin Kobe Michale
b  3.0   4.0      5.0
c  6.0    7.0      8.0
d NaN NaN NaN
e NaN NaN NaN

使用columns关键字即可重新索引列:

In [23]: name=['Calvin','Kobe','KD']

In [24]: frame.reindex(columns=name)
Out[24]:
  Calvin Kobe KD
a  0       1      NaN
b  3       4      NaN
c  6       7      NaN

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

In [26]: frame.reindex(index=['a','b','c','d'],method='ffill',columns=name)
Out[26]:
   Calvin Kobe KD
a    0       1       0
b    3       4       3
c    6       7       6
d    6       7       6

 

下表列出了reindex函数的各参数及说明

参数                            说明

index           用作索引的新序列。既可以是Index实例,也可以是其他序列型的Python数据结构,index会被完全使用,就像没有任何复制一样

method        插值(填充)方式,具体参数见上表

fill_value      在重新索引的过程中,需要引入缺失值时使用的替代值

limit              前向或后向填充时的最大值充量

level             在MultiIndex的指定级别上匹配简单索引,否则选取其子集

copy             默认为True,无论如何复制;如果为False,则新旧相等就不复制

 

丢弃指定轴上的项

丢弃某条轴上的一个或多个项很简单,只要有一个索引数组或列表即可。由于需要执行一些数据整理和集合逻辑,所以drop方法返回的是一个指定轴上删除了指定值的新对象

In [30]: obj=Series(np.arange(5),index=['a','b','c','d','e'])

In [31]: obj
Out[31]:
a 0
b 1
c 2
d 3
e 4
dtype: int32

In [32]: new_obj=obj.drop('c')

In [33]: new_obj
Out[33]:
a 0
b 1
d 3
e 4
dtype: int32

In [34]: new_obj=obj.drop(['c','d'])

In [35]: new_obj
Out[35]:
a 0
b 1
e 4
dtype: int32

 

对于DataFrame,可以删除任意轴上的索引值:

In [6]: data=DataFrame(np.arange(16).reshape((4,4)),index=['CA','FL','HW','NY']
...: ,columns=['one','two','three','four'])

In [7]: data
Out[7]:
      one two three four
CA   0     1      2     3
FL    4     5      6     7
HW  8     9     10   11
NY  12    13   14   15

#删除索引值为CA,FL的行

In [9]: data.drop(['CA','FL'])
Out[9]:
       one two three four
HW   8     9    10    11
NY   12   13   14   15

In [10]: data
Out[10]:
       one two three four
CA   0      1     2      3
FL    4      5     6      7
HW  8      9    10    11
NY 12     13   14    15

#删除指定列(要加上轴)

In [12]: data.drop(['one','three'],axis=1)
Out[12]:
      two   four
CA   1      3
FL    5      7
HW  9     11
NY  13    15

 

索引、选取和过滤

Series索引的工作方式类似于Numpy数组的索引,只不过Series的索引值不只是整数

In [13]: obj=Series(np.arange(4),index=['a','b','c','d'])

In [14]: obj
Out[14]:
a 0
b 1
c 2
d 3
dtype: int32

In [15]: obj['c']
Out[15]: 2

In [16]: obj[0]
Out[16]: 0

#字母标签包含末端

In [17]: obj['a':'c']
Out[17]:
a 0
b 1
c 2
dtype: int32 

#数字标签跟python切片运算一样,不包含末端

In [18]: obj[0:2]
Out[18]:
a 0
b 1
dtype: int32

In [19]: obj[0:3]
Out[19]:
a 0
b 1
c 2
dtype: int32

In [20]: obj[[1,3]]
Out[20]:
b 1
d 3
dtype: int32

对DataFrame进行索引其实就是获取一个或多个列

In [26]: data=DataFrame(np.arange(16).reshape((4,4)),index=['CA','FL','HW','NY']
...: ,columns=['one','two','three','four'])

In [27]: data
Out[27]:
      one two three four
CA   0     1     2      3
FL    4     5     6      7
HW  8     9    10    11
NY  12   13    14   15

 

In [28]: data['one']
Out[28]:
CA 0
FL 4
HW 8
NY 12
Name: one, dtype: int32

In [30]: data[['three','one']]
Out[30]:
      three one
CA   2      0
FL    6      4
HW 10     8
NY  14     12

#通过切片或布尔型数组选取行:

In [31]: data[:2]
Out[31]:
      one two three four
CA    0    1    2       3
FL     4    5    6       7

In [32]: data[0:2]
Out[32]:
      one two three four
CA   0     1     2       3
FL    4     5     6       7

In [33]: data[data['two']>4]
Out[33]:
      one two three four
FL    4     5     6      7
HW  8     9    10    11
NY  12   13    14   15

#另一种用法是通过布尔型DataFrame进行索引

In [35]: data<5
Out[35]:
        one two three four
CA True True True True
FL True False False False
HW False False False False
NY False False False False

In [36]: data[data<5]=0

In [37]: data
Out[37]:
     one two three four
CA   0    0     0      0
FL    0    5     6      7
HW  8    9    10    11
NY  12  13    14   15

 

为了在DataFrame的行上进行标签索引,我们引入专门的索引字段loc,iloc。它使你可以通过Numpy式的标记法以及轴标签从DataFrame中选取行和列的子集,之前提到过这也是一种重新索引的简单手段:

loc-----通过行标签索引行数据

iloc-----通过行号索引行数据

In [56]: data.loc[['FL','NY'],['one','two']]   #通过loc索引行为'FL','NY',列为'one','two'的数据
Out[56]:
    one two
FL   0    5
NY 12  13

#通过iloc索引第一行数据

In [58]: data.iloc[:1]
Out[58]:
     one two three four
CA  0     0      0    0

 

#算术运算和数据对齐

pandas最重要的一个功能是,它可以对不同索引的对象进行算术运算。在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。

 

In [1]: import numpy as np

In [2]: from pandas import Series,DataFrame

In [3]: s1=Series([1.2,-2.8,3.4,1.5],index=['a','c','d','e'])

In [4]: s2=Series([3.1,4.3,-5,6,4.8],index=['a','c','e','f','g'])

In [5]: s1
Out[5]:
a 1.2
c -2.8
d 3.4
e 1.5
dtype: float64

In [6]: s2
Out[6]:
a 3.1
c 4.3
e -5.0
f 6.0
g 4.8
dtype: float64

 

将它们相加就会产生:

In [7]: s1+s2
Out[7]:
a 4.3
c 1.5
d NaN
e -3.5
f NaN
g NaN

dtype: float64

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

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

In [8]: df1=DataFrame(np.arange(9).reshape((3,3)),columns=list('bcd'),index=['C
...: A','FL','NY'])

In [9]: df2=DataFrame(np.arange(12).reshape((4,3)),columns=list('bde'),index=['
...: UT','CA','NY','TE'])

In [10]: df1
Out[10]:
      b c d
CA 0 1 2
FL 3 4 5
NY 6 7 8

In [11]: df2
Out[11]:
      b d e
UT 0 1 2
CA 3 4 5
NY 6 7 8
TE 9 10 11

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

In [12]: df1+df2
Out[12]:
       b     c     d     e
CA 3.0 NaN 6.0 NaN
FL NaN NaN NaN NaN
NY 12.0 NaN 15.0 NaN
TE NaN NaN NaN NaN
UT NaN NaN NaN NaN

#在算术方法中填充值

在对不同索引的对象进行算术运算时,我们可能希望当一个对象中某轴标签在另一个对相中找不到时填充一个特殊值(比如0):

In [14]: df1=DataFrame(np.arange(12).reshape((3,4)),columns=list('abcd'))

In [16]: df2=DataFrame(np.arange(20).reshape((4,5)),columns=list('abcde'))

In [17]: df1
Out[17]:
   a b c d
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11

In [19]: df2
Out[19]:
   a b c d e
0 0 1 2 3 4
1 5 6 7 8 9
2 10 11 12 13 14
3 15 16 17 18 19

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

In [20]: df1+df2
Out[20]:
    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 [21]: df1.add(df2,fill_value=0)
Out[21]:
     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 [22]: df1.reindex(columns=df2.columns,fill_value=0)
Out[22]:
   a b c d e
0 0 1 2 3 0
1 4 5 6 7 0
2 8 9 10 11 0

下表列出了常用的算术方法

方法                           说明

add                        用于加法(+)的方法

sub                         用于减法(-)的方法

div                          用于除法(/)的方法

mul                         用于乘法(*)的方法

 

#DataFrame和Series之间的运算

 跟Numpy数组一样,DataFrame和Series之间算术运算也是有明确规定的,看下例计算一个二维数组与其某行之间的差:

In [25]: arr=np.arange(12).reshape((3,4))

In [26]: arr
Out[26]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])

In [27]: arr[0]
Out[27]: array([0, 1, 2, 3])

In [28]: arr-arr[0]
Out[28]:
array([[0, 0, 0, 0],
[4, 4, 4, 4],
[8, 8, 8, 8]])

这就叫做广播。DataFrame和Series之间的运算差不多也是如此:

In [29]: frame=DataFrame(np.arange(12).reshape((4,3)),columns=list('bde'),index
...: =['UT','CA','TE','NY'])

In [30]: series=frame.iloc[0]

In [31]: frame
Out[31]:
      b d e
UT 0 1 2
CA 3 4 5
TE 6 7 8
NY 9 10 11

In [32]: series
Out[32]:
b 0
d 1
e 2
Name: UT, dtype: int32

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

In [36]: frame-series
Out[36]:
      b d e
UT 0 0 0
CA 3 3 3
TE 6 6 6
NY 9 9 9

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

In [37]: series2=Series(range(3),index=['b','e','f'])

In [38]: series2
Out[38]:
b 0
e 1
f 2
dtype: int64

In [39]: frame+series2
Out[39]:
        b    d      e     f
UT 0.0 NaN 3.0 NaN
CA 3.0 NaN 6.0 NaN
TE 6.0 NaN 9.0 NaN
NY 9.0 NaN 12.0 NaN

如果希望匹配行且在列上广播,则必须使用算术运算方法。例如:

In [43]: series3=frame['d']

In [44]: series3
Out[44]:
UT 1
CA 4
TE 7
NY 10
Name: d, dtype: int32

In [45]: frame
Out[45]:
      b d e
UT 0 1 2
CA 3 4 5
TE 6 7 8
NY 9 10 11

In [46]: frame.sub(series3,axis=0)
Out[46]:
       b d e
UT -1 0 1
CA -1 0 1
TE -1 0 1
NY -1 0 1

传入的轴号就是希望匹配的轴。在本例中,我们的目的是匹配DataFrame的行索引并进行广播。