【问题标题】:pandas IndexError/TypeError inconsistency with NaN valuespandas IndexError/TypeError 与 NaN 值不一致
【发布时间】:2016-03-27 15:57:08
【问题描述】:

我有几个带有一些空值的可变长度列表。一个例子是:

In [108]: s0 = pd.Series([['a', 'b'],['c'],np.nan])
In [109]: s0
Out[109]: 
0    [a, b]
1       [c]
2       NaN
dtype: object

但另一个包含所有NaNs

In [110]: s1 = pd.Series([np.nan,np.nan])
In [111]: s1
Out[111]: 
0    NaN
1    NaN
dtype: float64

我需要每个列表中的最后一项,这很简单:

In [112]: s0.map(lambda x: x[-1] if isinstance(x,list) else x)
Out[112]: 
0      b
1      c
2    NaN
dtype: object

但在进行此操作时,我发现,如果没有 isinstance,当 NaNs 上的索引阻塞时,s0s1 上的表现会有所不同:

In [113]: s0.map(lambda x: x[-1])
...
TypeError: 'float' object is not subscriptable

In [114]: s1.map(lamda x: x[-1])
...
IndexError: invalid index to scalar variable.

谁能解释为什么?这是一个错误吗?我正在使用 Pandas 0.16.2 和 Python 3.4.3。

【问题讨论】:

  • 有趣的问题。它与pd.Series 的工作方式有关,因为尝试使用listnp.array 复制它只会导致TypeError
  • 您尝试过使用元组而不是列表吗?根据我的经验,数据框中的元组工作得更好。不确定这是否解决了您的问题,因为我没有尝试重新创建

标签: python exception pandas indexing nan


【解决方案1】:

从本质上讲,这实际上是一个 NumPy 问题,而不是 pandas 问题。

map 遍历列中的值,一次一个地将它们传递给lambda 函数。在下面,pandas 中的列/系列只是 NumPy 数组的(切片),因此 pandas 定义了以下 helper function 以从函数的底层数组中获取值。 map 在每次迭代时都会调用它:

PANDAS_INLINE PyObject*
get_value_1d(PyArrayObject* ap, Py_ssize_t i) {
  char *item = (char *) PyArray_DATA(ap) + i * PyArray_STRIDE(ap, 0);
  return PyArray_Scalar(item, PyArray_DESCR(ap), (PyObject*) ap);
}

关键位是PyArray_Scalar,这是一个 NumPy API 函数,它复制 NumPy 数组的一部分以返回一个标量值。

构成该函数的代码太长,无法在此处发布,但是here's 在代码库中的哪里可以找到它。我们只需要知道它返回的标量将匹配它所使用的数组的 dtype。

回到您的系列:s0 具有 object dtype,而 s1 具有 float64 dtype。这意味着PyArray_Scalar 将为每个系列返回不同类型的标量;一个实际的 Python float 对象和一个 NumPy 标量浮点对象:

>>> type(s0[2])
float
>>> type(s1[0])
numpy.float64

NaN 值作为两种不同类型返回,因此当您尝试使用 lambda 函数对它们进行索引时会出现不同的错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多