Pandas索引操作的相关方法比较

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方法。它们都有自己的使用场景,并且它们之间的性能也有所不同。在实际使用中,我们需要结合具体的需求,选择适当的方法。

后端开发标签