pandas IndexError / TypeError与NaN值不一致

时间:2015-12-21 14:29:10

标签: python exception pandas indexing nan

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

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。

1 个答案:

答案 0 :(得分:1)

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

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相匹配。

返回您的系列:s0object dtype而s1float64 dtype。这意味着PyArray_Scalar将为每个系列返回不同类型的标量;一个实际的 Python float对象和一个NumPy标量浮点对象:

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

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