为什么Pandas在使用过多索引时会静默忽略.iloc [i,j]赋值?

5

为什么当在系列中设置或获取具有错误索引数量的项目时,pandas的行为会有所不同:

df = pd.DataFrame({'a': [10]})
# df['a'] is a series, can be indexed with 1 index only

# will raise IndexingError, as expected
df['a'].iloc[0, 0]
df['a'].loc[0, 0]

# will raise nothing, not as expected
df['a'].iloc[0, 0] = 1000 # equivalent to pass
df['a'].loc[0, 0] = 1000 # equivalent to df['a'].loc[0] = 1000

# pandas version 0.18.1, python 3.5

编辑:已报告


@JohnGordon,既然重写的行为在“设置值”的情况下不会产生任何效果,那么是否应该改为生成错误信息? - max
我误解了你的问题。我以为第一个例子是在尝试使用元组下标而不是整数访问普通列表时出现了标准Python错误。但那是TypeError,而不是IndexingError,所以我错了。我不知道Pandas为什么允许你做第二个。 - John Gordon
@ptrj 我认为这不是一个 bug,因为它太明显了,并且在 pandas 中 .loc 和 .iloc 索引相对成熟。但如果这是一个 bug,我会在 github 上报告它。 - max
@Merlin,[0,False]是什么意思? - max
这实际上涉及到 Series,因为 df['a'] 是一个 Series(你会得到相同的行为)。 - Alex
显示剩余6条评论
1个回答

1

获取值

如果键是元组(如您的示例中),则 lociloc 对象的超类的 __getitem__ 方法在某个时候调用 _has_valid_tuple(self, key)

该方法具有以下代码:

for i, k in enumerate(key):
    if i >= self.obj.ndim:
        raise IndexingError('Too many indexers')

这会引发一个预期中的IndexingError

设置值

超类的__setitem__调用_get_setitem_indexer,进而调用_convert_to_indexer

超类对_convert_to_indexer的实现有点混乱,但在这种情况下,它返回一个numpy数组[0, 0]

然而,iLoc索引器的类覆盖了_convert_to_indexer。该方法返回原始元组...

def _convert_to_indexer(self, obj, axis=0, is_setter=False):
    ...
    elif self._has_valid_type(obj, axis):
        return obj

现在,对于`.loc`情况下,`indexer`变量是一个numpy数组;对于`.iloc`情况下,`indexer`变量是一个元组。这导致在后续的父类调用中,设置行为存在差异,即调用`_setitem_with_indexer(indexer, value)`方法。

我猜应该将其修复为始终引发错误,无论是 loc 还是 iloc? - max
是的,设置值时进行的检查似乎是一个不错的选择...也许核心pandas开发人员对为什么会有所有这些不同的行为有一些见解。Pandas开发论坛是发布此内容的好地方。 - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接