我有几个可变长度列表和一些空值。一个例子是:
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
上的索引窒息时,s0
和s1
上的索引会有所不同:
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。
答案 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相匹配。
返回您的系列:s0
有object
dtype而s1
有float64
dtype。这意味着PyArray_Scalar
将为每个系列返回不同类型的标量;一个实际的 Python float
对象和一个NumPy标量浮点对象:
>>> type(s0[2])
float
>>> type(s1[0])
numpy.float64
NaN
值以两种不同的类型返回,因此当您尝试使用lambda
函数对其进行索引时会出现不同的错误。