【发布时间】:2017-06-11 01:27:51
【问题描述】:
我对以下行为感到困惑。当我有这样的数据框时:
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(6, 4), columns=list('ABCD'), index=list('bcdefg'))
如下所示:
A B C D
b -0.907325 0.211740 0.150066 -0.240011
c -0.307543 0.691359 -0.179995 -0.334836
d 1.280978 0.469956 -0.912541 0.487357
e 1.447153 -0.087224 -0.176256 1.319822
f 0.660994 -0.289151 0.956900 -1.063623
g -1.880520 1.099098 -0.759683 -0.657774
我收到预期错误
TypeError: cannot do slice indexing on with these indexer [3] of type 'int'
当我使用.loc 尝试以下切片时:
print df.loc[3:, ['C', 'D']]
这是预期的,因为我传递了一个整数作为索引,而不是 index 中包含的字母之一。
但是,如果我现在尝试
df.loc[3:, ['C', 'D']] = 10
它工作正常并给我输出:
A B C D
b -0.907325 0.211740 0.150066 -0.240011
c -0.307543 0.691359 -0.179995 -0.334836
d 1.280978 0.469956 -0.912541 0.487357
e 1.447153 -0.087224 10.000000 10.000000
f 0.660994 -0.289151 10.000000 10.000000
g -1.880520 1.099098 10.000000 10.000000
我的问题是为什么在打印某些内容时相同的命令会失败,以及为什么在分配值时它会起作用。当我检查.loc 的文档字符串时,我原以为这总是会导致上面提到的错误(尤其是粗体部分):
允许的输入是:
- 单个标签,例如
5或'a',(注意5被解释为索引的标签,而**never 被解释为整数 沿索引的位置**)。- 标签列表或数组,例如
['a', 'b', 'c']。- 带有标签的切片对象,例如
'a':'f'(请注意,与通常的 python 切片相反,开始和停止都是 包括在内!)。- 布尔数组。
callable函数有一个参数(调用 Series、DataFrame 或 Panel)并返回有效的索引输出(一个 以上)
.loc将在找不到项目时引发KeyError。
对此的任何解释;我在这里错过了什么?
编辑
在this question 中,类似的行为被认为是在 0.13 中修复的错误。我用的是 0.19.1。
编辑 2 以@EdChum 的帖子为基础,可以执行以下操作:
df.loc[2] = 20
df.loc[3] = 30
df.loc[4] = 40
产生
A B C D
b 0.083326 -1.047032 0.830499 -0.729662
c 0.942744 -0.535013 0.809251 1.132983
d -0.074918 1.123331 -2.205294 -0.497468
e 0.213349 0.694366 -0.816550 0.496324
f 0.021347 0.917340 -0.595254 -0.392177
g -1.149890 0.965645 0.172672 -0.043652
2 20.000000 20.000000 20.000000 20.000000
3 30.000000 30.000000 30.000000 30.000000
4 40.000000 40.000000 40.000000 40.000000
然而,这仍然让我感到困惑,因为虽然
print df.loc['d':'f', ['C', 'D']]
工作正常,命令
print df.loc[2:4, ['C', 'D']]
给出上面提到的索引错误。
此外,当人们现在分配这样的值时
df.loc[2:4, ['C', 'D']] = 100
数据框如下所示:
A B C D
b 0.083326 -1.047032 0.830499 -0.729662
c 0.942744 -0.535013 0.809251 1.132983
d -0.074918 1.123331 100.000000 100.000000
e 0.213349 0.694366 100.000000 100.000000
f 0.021347 0.917340 -0.595254 -0.392177
g -1.149890 0.965645 0.172672 -0.043652
2 20.000000 20.000000 20.000000 20.000000
3 30.000000 30.000000 30.000000 30.000000
4 40.000000 40.000000 40.000000 40.000000
因此,值不会被添加到一个人 - 或者至少我 - 期望它们被添加的地方(使用位置而不是标签)。
【问题讨论】:
-
根据pandas-docs.github.io/pandas-docs-travis/…,第一个案例调用“getitem”,而赋值案例调用“setitem”方法。我假设第二种方法旨在处理整数切片
-
这里的关键是“.loc 主要是基于标签的,但也可以与布尔数组一起使用。.loc 将在找不到项目时引发 KeyError”所以当你尝试使用索引时键 'e' 而不是 3,它对数据进行切片。 df.loc['e':, ['C', 'D']]
-
@Prateek:我认为这是完全相同的方法。但一次是
print df.loc[3:, ['C', 'D']],另一次是df.loc[3:, ['C', 'D']] = 10。所以在这两种情况下,都使用了.loc,没有链式索引(我认为)。 -
@VaishaliGarg:是的,但我不传递布尔数组,而是传递表示索引的整数。据我了解文档字符串,这应该总是失败。但是,分配有效,而打印失败。
-
@Cleb 在同一个链接中提到
dfmi.loc[:,('one','second')]将 (slice(None),('one','second')) 的嵌套元组传递给对__getitem__的单个调用,而dfmi.loc[:,('one','second')] = value变为dfmi.loc.__setitem__((slice(None), ('one', 'second')), value)。您的示例中的第一个示例 print 是通过 getitem 方法执行的。这似乎也是一个合理的解释,因为查看 pandas 代码库中的 indexing.py 类表明__setitem__比__getitem__具有更多检测/扩展索引的条件和方法。