2015-12-21 7 views
5

Ich habe mehrere Reihen von Listen variabler Länge mit einigen Nullen. Ein Beispiel dafür ist:pandas IndexError/TypeError Inkonsistenz mit NaN-Werten

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

aber eine andere enthält alle NaNs:

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

Ich muss das letzte Element in jeder Liste, die einfach ist:

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

Aber während dieser ich immer entdeckt, dass, ohne die isinstance, wenn die Indizierung Drosseln auf der NaNses so anders auf s0 und 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. 

Kann mir jemand erklären, warum? Ist das ein Fehler? Ich benutze Pandas 0.16.2 und Python 3.4.3.

+0

Interessante Frage. Es hat mit der Funktionsweise von 'pd.Series' zu tun, da der Versuch, dies mit' list' und 'np.array' zu replizieren, nur mit' TypeError' erfolgt. – DeepSpace

+0

Haben Sie Tupel anstatt Listen versucht? Meiner Erfahrung nach arbeiten Tupel in Datenrahmen viel besser. Nicht sicher, dass dies Ihr Problem anspricht, da ich nicht versucht habe, –

Antwort

1

Im Kern ist dies eher ein NumPy-Problem als ein Pandas-Problem.

map iteriert über die Werte in der Spalte, um sie einzeln an die lambda-Funktion zu übergeben. Darunter sind Spalten/Reihen in Pandas nur (Scheiben von) NumPy-Arrays, also definiert Pandas die folgenden helper function, um den Wert aus dem zugrunde liegenden Array für die Funktion zu erhalten. Dies wird durch map bei jeder Iteration genannt:

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); 
} 

der Schlüsselbart ist PyArray_Scalar, die eine NumPy API-Funktion, die kopiert einen Abschnitt eines Arrays aus NumPy einen skalaren Wert zurück.

Der Code, der die Funktion ausmacht, ist zu lang, um hier zu posten, aber here's wo es in der Codebasis zu finden ist. Alles, was wir wissen müssen, ist, dass der zurückgegebene Skalar dem dtype des Arrays entspricht, auf dem er verwendet wird.

Zurück zu Ihrer Serie: s0 hat object dtype während s1 hat float64 dtype. Dies bedeutet, dass PyArray_Scalar eine andere Art von Skalar für jede Serie zurückgibt; ein tatsächlicher Pythonfloat Objekt und ein Skalar float Objekt NumPy jeweils:

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

Die NaN Werte als zwei verschiedene Typen zurückgegeben werden, damit die verschiedenen Fehler, wenn Sie indizieren versuchen, in ihnen die lambda Funktion.

+0

wiederherzustellen Vielen Dank, sehr klar! – majr

Verwandte Themen