我有一个 pandas DataFrame,其中一列是出租车行驶的行程距离。我在用着
此列上的 value_counts()
以便查看最常见的行程距离。
b = df['trip_distance'].value_counts()
对象 b 是 pandas Series 对象。为了完整起见,本系列的前 5 行是
1.00 21815
0.90 18915
0.80 18449
1.10 18263
1.20 17823
这意味着最常见的行程距离为 1,出现了 21815 次,其余相同。
但是,如果我输入 b[0:4]
而不是打印该系列的前 4 个元素,它会找到与 0
行程距离相对应的元素,并开始打印所有行程距离,直到达到行程距离 4。当然,如果行程距离 4 在行程距离 0 之前,则返回一个空 Series。
尽管如此,当我在自定义系列上尝试时
a = pd.Series([3, 1, 2, 3, 4, 4, 5]).value_counts()
打印a
给出
4 2
3 2
5 1
2 1
1 1
当我尝试对这个系列进行切片时,即当我输入 a[0, 3]
时,我得到了预期的结果
4 2
3 2
5 1
有谁知道为什么会这样吗? 我知道这可以使用 iloc/loc 来完成,我只是好奇为什么切片在一个列表中有效,但在另一个列表中无效。
提前致谢。
最佳答案
在对 Series 中的值(或数据帧中的行)进行索引时,我始终建议您使用 .loc
和 .iloc
索引访问器。本质上,通过使用这些访问器,您明确告诉 pandas loc
:“此切片将基于索引的顺序”或 iloc
:“此切片将基于关于值的顺序”。当您不使用 loc/iloc (例如您的情况)并且有数字索引时,棘手的部分就会出现。当您不使用其中任何一个时,pandas 会尝试推断您是指索引顺序还是值的顺序。本质上,如果您使用一系列数字进行切片,pandas 会假设您正在尝试使用值的位置 - 忽略索引。
import pandas as pd
data = pd.Series([5,6,7,8,9], index=range(10, 15))
print(data)
10 5
11 6
12 7
13 8
14 9
dtype: int64
使用.loc
从索引中获取与切片“a”到“c”相对应的值:
# Slice based on the index values 11 to 13
data.loc[11:13]
11 6
12 7
13 8
dtype: int64
但是,如果我们想要基于其在系列中的位置的值,我们可以使用iloc
。您还会注意到,iloc
生成的切片不包含最终值(例如,我们仅返回元素 1 和 2,并在下面的示例中省略 3)。而在上面使用 loc 的示例中,我们返回了索引中对应于 11、12 和 13 的元素。
data.iloc[1:3]
11 6
12 7
dtype: int64
既然已经说过了,我希望你明白为什么这意味着什么非常不清楚:
data[11:13]
我们是否要求 pandas 在索引中找到值 11 到 13 存在的位置并给我们该切片?或者我们要的是这个系列的第 12 个和第 13 个元素?在本例中,pandas 使用了后者(见下文)。但是,我鼓励您始终使用 loc
或 .iloc
切片为 Series 或 DataFrame,以避免这种歧义。
data[11:13]
Series([], dtype: int64)
这只是为了对基于整数的索引进行切片。您的问题来自 pandas 如何实现 float 类型索引(这是真正的思维扭曲):
data.index = data.index.astype("float")
print(data)
10.0 5
11.0 6
12.0 7
13.0 8
14.0 9
dtype: int64
现在突然之间,您可以执行此操作,它会返回值,就像您使用 .loc
一样:
data[11:13]
11.0 6
12.0 7
13.0 8
dtype: int64
那么什么给出了呢?本质上,必须做出决定。需要某种类型的默认行为来切片为系列,不幸的是,它依赖于索引,这使得它在索引数据类型之间感觉不稳定。值得庆幸的是,通过使用 loc
和 iloc
,您可以避免所有这些困惑。
关于python - 与 pandas 系列切片的混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64325834/