本博客为《利用Python进行数据分析》的读书笔记,请勿转载用于其他商业用途。
1、重建索引
reindex是Pandas对象的重要方法,该方法用于创建一个符合新索引的新对象。例:
obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
print(obj)
#
d 4.5
b 7.2
a -5.3
c 3.6
dtype: float64
Series调用reindex方法时,会将数据按照新的索引进行排列,如果某个索引值之前并不存在,则会引入缺失值:
obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])
print(obj2)
#
a -5.3
b 7.2
c 3.6
d 4.5
e NaN
dtype: float64
对于顺序数据,比如时间序列,在重建索引时可能会需要进行插值或填值。method可选参数允许我们使用诸如ffill等方法在重建索引时插值,ffill方法会将值前向填充:
obj3= pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])
print(obj3)
obj3 = obj3.reindex(range(6), method='ffill')
print(obj3)
#
0 blue
2 purple
4 yellow
dtype: object
0 blue
1 blue
2 purple
3 purple
4 yellow
5 yellow
dtype: object
在DataFrame中,reindex可以改变行索引、列索引,也可以同时改变二者。当仅传入一个序列时,结果中的行会重建索引:
frame = pd.DataFrame(np.arange(9).reshape((3, 3)), index=['a', 'c', 'd'], columns=['Ohio', 'Texas', 'California'])
print(frame)
frame2 = frame.reindex(['a', 'b', 'c', 'd'])
print(frame2)
#
Ohio Texas California
a 0 1 2
c 3 4 5
d 6 7 8
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关键字重建索引:
states = ['Texas', 'Utah', 'California']
frame3 = frame.reindex(columns = states)
print(frame3)
#
Texas Utah California
a 1 NaN 2
c 4 NaN 5
d 7 NaN 8
我们可以使用loc进行更为简洁的标签索引:
frame3 = frame.loc[['a', 'b', 'c', 'd'], states]
print(frame3)
#
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
reindex方法的参数
参数 描述 index 新建作为索引的序列,可以是索引实例或任意其他序列型Python数据结构,索引使用时无需复制 method 插值方式;‘ffill’为前向填充,而‘bfill’为 后向填充 fill_value 通过重新索引引入缺失数据时使用的替代值 limit 当前向或后向填充式,所需填充的最大尺寸间隙(以元素数量) tolerance 当前向或后向填充时,所需填充的不精确匹配下的最大尺寸间隙(以绝对数字距离) level 匹配MultiIndex级别的简单索引;否则选择子集 copy 如果为True,及时新索引等于旧索引,也总是复制底层数据;如果是False,则在索引相同时不要复制数据
2、轴向上删除条目
如果我们已经拥有索引数组或不含条目的列表,在轴向上删除一个或更多的条目就非常容易,但这样需要一些数据操作和集合逻辑,drop方法会返回一个含有指示值或轴向上删除值的新对象:
obj = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])
print(obj)
#
a 0.0
b 1.0
c 2.0
d 3.0
e 4.0
dtype: float64
new_obj = obj.drop('c')
print(new_obj)
print(obj.drop(['d', 'c']))
print(obj)
#
a 0.0
b 1.0
d 3.0
e 4.0
dtype: float64
a 0.0
b 1.0
e 4.0
dtype: float64
在DataFrame中,索引值可以从轴向上删除。为了表明这个特性,我们首先创建一个示例DataFrame:
data = pd.DataFrame(np.arange(16).reshape((4, 4)),
index=['Ohio', 'Colorado', 'Utah', 'New York'],
columns=['one', 'two', 'three', 'four'])
print(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
在调用drop时使用标签序列会根据行标签删除值:
data1 = data.drop(['Colorado', 'Ohio'])
print(data1)
#
one two three four
Utah 8 9 10 11
New York 12 13 14 15
我们可以通过传递axis=1或axis=‘columns’来从列中删除值:
data2 = data.drop('two', axis=1)
print(data2)
#
one three four
Ohio 0 2 3
Colorado 4 6 7
Utah 8 10 11
New York 12 14 15
data3 = data.drop(['two', 'four'], axis='columns')
print(data3)
#
one three
Ohio 0 2
Colorado 4 6
Utah 8 10
New York 12 14
很多函数,例如drop,会修改Series或DataFrame的尺寸或形状,这些方法直接操作原对象而不返回新对象:
obj = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])
obj.drop('c', inplace=True)
print(obj)
#
a 0.0
b 1.0
d 3.0
e 4.0
dtype: float64
注意inplace属性,它会清除被删除的数据。
3、索引、选择与过滤
Series的索引(obj[...])与NumPy数组索引的功能类似,只不过Series的索引值可以不仅仅是整数。相关示例如下:
obj = pd.Series(np.arange(4.), index=['a', 'b', 'c', 'd'])
print(obj)
print(obj['b'])
print(obj[1])
print(obj[2:4])
print(obj[['b', 'a', 'd']])
print(obj[[1, 3]])
print(obj[obj<2])
#
a 0.0
b 1.0
c 2.0
d 3.0
dtype: float64
1.0
1.0
c 2.0
d 3.0
dtype: float64
b 1.0
a 0.0
d 3.0
dtype: float64
b 1.0
d 3.0
dtype: float64
a 0.0
b 1.0
dtype: float64
普通的Python切片中是不包含尾部的,Series的切片与之不同:
需要注意的是,在上一个例子中,如果切片是取数字的话,结果与Python切片一样,是不包含的
print(obj['b':'c'])
#
b 1.0
c 2.0
dtype: float64
使用这些方法设值时会修改Series相应的部分:
obj['b':'c'] = 5
print(obj)
#
a 0.0
b 5.0
c 5.0
d 3.0
dtype: float64
使用单个值或序列,可以从DataFrame中索引出一个或多个列:
data = pd.DataFrame(np.arange(16).reshape((4,4)),
index=['Ohio', 'Colorado', 'Utah', 'New York'],
columns=['one', 'two', 'three', 'four'])
print(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
print(data['two'])
print(data[['three', 'one']])
#
Ohio 1
Colorado 5
Utah 9
New York 13
Name: two, dtype: int32
three one
Ohio 2 0
Colorado 6 4
Utah 10 8
New York 14 12
这种索引方式也有特殊案例。首先,可以根据一个布尔值数组切片或选择数据:
print(data[:2])
print(data[data['three'] > 5])
#
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
one two three four
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15
行选择语法data[ :2]非常方便。传递单个元素或一个列表到[ ]符号中可以选择列。另一个用例是使用布尔值DataFrame进行索引,布尔值DataFrame可以是对标量值进行比较产生的:
print(data < 5)
data[data < 5] = 0
print(data)
#
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
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在语法上更像是NumPy二维数组。
使用loc和iloc选择数据
loc和iloc允许我们使用轴标签(loc)和整数标签(iloc)以NumPy风格的语法从DataFrame中选出数组的行和列的子集。
我们通过标签选出单行多列的数据作为基础示例:
obj = data.loc['Colorado', ['two', 'three']]
print(obj)
#
two 5
three 6
Name: Colorado, dtype: int32
然后我们使用整数标签iloc进行类似的数据选择:
obj2 = data.iloc[2, [3, 0, 1]]
print(obj2)
#
four 11
one 8
two 9
Name: Utah, dtype: int32
此处iloc[2, [3,0,1]]代表的意识是,第2行,因此选择到‘Utah’,然后第3、0、1列,分别对应11、8、9。
obj = data.iloc[2]
print(obj)
obj2 = data.iloc[[1, 2], [3, 0, 1]]
print(obj2)
#
one 8
two 9
three 10
four 11
Name: Utah, dtype: int32
four one two
Colorado 7 4 5
Utah 11 8 9
这里需要特别注意的是,loc和iloc后面用中括号[ ]而不是小括号()。
除了单个标签或标签列之外,索引功能还可以用于切片:
obj = data.loc[:'Utah', 'two']
print(obj)
#
Ohio 1
Colorado 5
Utah 9
Name: two, dtype: int32
能取到Utah州,但是取不到第1列……好吧……
obj = data.iloc[:, :3][data.three > 5]
print(obj)
#
one two three
Colorado 4 5 6
Utah 8 9 10
New York 12 13 14
因此,有多种方式可以选择、重排pandas对象中的数据。