Pandas是Python中一个非常常用的数据处理库,而Pandas的核心是关于DataFrame、Series和Index对象的操作。其中Index对象作为Pandas数据结构的重要组成部分,经常需要对其进行操作。本文将会介绍一些常见的Pandas索引操作方法及其使用场景,以及它们之间的比较。
1. iloc 和 loc
1.1 iloc
iloc是通过整数位置进行访问的方法,我们可以用它来选取一个DataFrame或Series中的数据。
假设有一个数据框df如下所示:
import pandas as pd
import numpy as np
data = {'name': ['Lucy', 'John', 'Tom', 'Lily', 'Jack'],
'age': [18, 19, 25, 22, 31],
'gender': ['F', 'M', 'M', 'F', 'M'],
'height': [168, 175, 180, 160, 170]}
df = pd.DataFrame(data)
print(df)
输出结果为:
name age gender height
0 Lucy 18 F 168
1 John 19 M 175
2 Tom 25 M 180
3 Lily 22 F 160
4 Jack 31 M 170
要选取第1行(从0开始计数),我们可以使用iloc方法:
print(df.iloc[1])
输出结果为:
name John
age 19
gender M
height 175
Name: 1, dtype: object
相应地,如果我们想要选取第2—4行和第1、3列的数据,可以这样做:
print(df.iloc[1:4, [0, 2]])
输出结果为:
name gender
1 John M
2 Tom M
3 Lily F
1.2 loc
loc是通过标签进行访问的方法,我们可以用它访问行标签和列标签指定的数据。与iloc不同,iloc使用整数索引,而loc使用标签索引。
continents = pd.Series(['Asia', 'Europe', 'Africa'], index=[4, 5, 6])
预测代码输出结果:
area population gpd continents
BJ
1000
1200000000
10000
Asia
SH
3000
13000000
NaN
Asia
SZ
NA
6000000
NaN
Asia
GZ
4000
NA
NaN
Europe
# 创建数据框
data = {'area': [1000, 3000, np.nan, 4000],
'population': [1200000000, 13000000, 6000000, np.nan],
'gpd': [10000, np.nan, np.nan, np.nan],
'continents': ['Asia', 'Asia', 'Asia', 'Europe']}
df = pd.DataFrame(data, index=['BJ', 'SH', 'SZ', 'GZ'])
print(df)
# 使用loc选取'Bj'所在行的数据
print(df.loc['BJ'])
# 使用loc选取'BJ'和'SH'所在的行和'area'列的数据
print(df.loc[['BJ', 'SH'], 'area'])
上述代码的输出结果分别为:
area 1000
population 1.2e+09
gpd 10000
continents Asia
Name: BJ, dtype: object
BJ 1000.0
SH 3000.0
Name: area, dtype: float64
1.3 iloc和loc的区别
iloc和loc的区别主要在于,iloc使用整数索引,而loc使用标签索引。因此,iloc可以使用Python索引方法(如[start:end:step]语法),而loc不能。
2. ix 方法已不推荐使用,建议使用 iloc 和 loc
ix方法可以同时使用整数和标签进行访问,但是它在Pandas的新版本中已经不推荐使用了,而是建议使用iloc和loc。
假设我们有一个数据框df,现在我们想要选取第1—3行和第1、4列的数据,可以使用ix方法:
print(df.ix[1:3, [0, 3]])
输出结果为:
name height
1 John 175
2 Tom 180
3 Lily 160
虽然ix可以同时使用整数和标签进行访问,但是这种方法容易混淆,而且可能因为不同版本的Pandas库而引起不同的结果。因此,在实际使用中,我们建议使用iloc和loc方法进行选取。
3. at 和 iat
at和iat方法都是用于访问数据的方法,但是它们并不像loc和iloc那样返回一个新的DataFrame或Series对象,而是直接返回一个标量。因此,它们的速度比loc和iloc更快。
3.1 at
at方法用于根据标签访问一个数据框或Series的标量值。
假设有一个数据框df如下所示:
data = {'name': ['Lucy', 'John', 'Tom', 'Lily', 'Jack'],
'age': [18, 19, 25, 22, 31],
'gender': ['F', 'M', 'M', 'F', 'M'],
'height': [168, 175, 180, 160, 170]}
df = pd.DataFrame(data, index=['a', 'b', 'c', 'd', 'e'])
print(df)
输出结果为:
name age gender height
a Lucy 18 F 168
b John 19 M 175
c Tom 25 M 180
d Lily 22 F 160
e Jack 31 M 170
如果我们要访问第1行(从0开始计数)和第2列的标量值,可以使用at方法:
print(df.at['a', 'age'])
输出结果为:
18
3.2 iat
iat方法用于根据整数位置访问一个数据框或Series的标量值。
现在我们用同样的数据框df和位置坐标来访问标量值。
print(df.iat[0, 1])
输出结果为:
18
3.3 at和iat的区别
at和iat的区别主要在于,at使用标签索引,而iat使用整数索引。与loc、iloc方法的区别类似,at和iat也有相应的性能优劣。如果我们需要选取数据框中的大量数据,使用at和iat方法通常比loc和iloc方法更快。
4. get_loc和get_indexer
get_loc和get_indexer方法都是Index对象的方法,用于查找标签和位置信息。
4.1 get_loc
get_loc方法用于查找某个标签在Index中的位置,从0开始计数。
假设有一个Series如下所示:
s = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])
print(s)
输出结果为:
a 10
b 20
c 30
d 40
e 50
dtype: int64
如果我们想知道‘d’所在的位置,可以使用get_loc方法:
print(s.index.get_loc('d'))
输出结果为:
3
4.2 get_indexer
get_indexer方法用于查找给定的标签列表在Index中的位置,从0开始计数。它返回一个数组,该数组中的元素表示每个标签在Index中的位置。
假设有一个Series如下所示:
s = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])
print(s)
输出结果为:
a 10
b 20
c 30
d 40
e 50
dtype: int64
如果我们想知道['a', 'd', 'e']分别在Index中的位置,可以使用get_indexer方法:
labels = ['a', 'd', 'e']
print(s.index.get_indexer(labels))
输出结果为:
[0 3 4]
5. reindex 方法
reindex方法用于对DataFrame或Series重新索引。默认情况下,reindex方法会创建一个新的对象,并将原始对象中的数据按照新的索引进行重新排序。
假设有一个Series如下所示:
s = pd.Series([10, 20, 30, 40, 50], index=[1, 2, 3, 4, 5])
print(s)
输出结果为:
1 10
2 20
3 30
4 40
5 50
dtype: int64
现在,我们想要将这个Series的索引范围从[1,5]变为[0,6],并缺省缺失值。
可以使用reindex方法完成如下操作:
new_index = range(0, 7)
s = s.reindex(index=new_index, fill_value=0)
print(s)
输出结果为:
0 0
1 10
2 20
3 30
4 40
5 50
6 0
dtype: int64
从输出结果可以看出,原始Series中的数据被重新排序,并缺省缺失值。
5.1 forward fill 和 backward fill
有时,我们需要对缺失值进行填充。对于序列数据,我们可以使用fillna填充缺失值。而对于DataFrame,我们可以使用ffill和bfill方法分别进行向前填充和向后填充。
假设有一个DataFrame如下所示:
data = {'name': ['Lucy', 'John', 'Tom', 'Lily', 'Jack'],
'age': [18, np.nan, 25, np.nan, 31],
'gender': ['F', 'M', 'M', 'F', 'M'],
'height': [168, 175, np.nan, np.nan, 170]}
df = pd.DataFrame(data)
print(df)
输出结果为:
name age gender height
0 Lucy 18.0 F 168.0
1 John NaN M 175.0
2 Tom 25.0 M NaN
3 Lily NaN F NaN
4 Jack 31.0 M 170.0
如果我们要向前填充缺失值,可以使用ffill方法,如下所示:
df.ffill(inplace=True)
print(df)
输出结果为:
name age gender height
0 Lucy 18.0 F 168.0
1 John 18.0 M 175.0
2 Tom 25.0 M 175.0
3 Lily 25.0 F 175.0
4 Jack 31.0 M 170.0
从输出结果可以看出,缺失值现在被填充为前面的值。
如果我们要向后填充缺失值,可以使用bfill方法,如下所示:
df.bfill(inplace=True)
print(df)
输出结果为:
name age gender height
0 Lucy 18.0 F 168.0
1 John 25.0 M 175.0
2 Tom 25.0 M 170.0
3 Lily 31.0 F 170.0
4 Jack 31.0 M 170.0
从输出结果可以看出,缺失值现在被填充为后面的值。
6. drop 方法
drop方法用于删除某些标签或轴。
假设有一个DataFrame如下所示:
data = {'name': ['Lucy', 'John', 'Tom', 'Lily', 'Jack'],
'age': [18, 19, 25, 22, 31],
'gender': ['F', 'M', 'M', 'F', 'M'],
'height': [168, 175, 180, 160, 170]}
df = pd.DataFrame(data)
print(df)
输出结果为:
name age gender height
0 Lucy 18 F 168
1 John 19 M 175
2 Tom 25 M 180
3 Lily 22 F 160
4 Jack 31 M 170
如果我们想要删除‘gender’列,可以使用drop方法:
df.drop('gender', axis=1, inplace=True)
print(df)
输出结果为:
name age height
0 Lucy 18 168
1 John 19 175
2 Tom 25 180
3 Lily 22 160
4 Jack 31 170
从输出结果可以看出,'gender'列已经被删除。
6.1 drop标签和轴
drop方法的参数有两个,第一个是要删除的标签或轴,第二个是轴的方向。其中,轴可以是0或1,分别表示行和列。
如果axis=0,表示要删除的是行标签;如果axis=1,表示要删除的是列标签。
另外,如果inplace=True,表示在原始DataFrame中直接删除,不返回一个新的DataFrame对象。
总结
本文介绍了Pandas中一些常用的索引操作方法,包括iloc、loc、ix、at、iat、get_loc、get_indexer、reindex、ffill、bfill和drop方法。它们都有自己的使用场景,并且它们之间的性能也有所不同。在实际使用中,我们需要结合具体的需求,选择适当的方法。