2017-01-11 3 views
2

Ich versuche apply eine Funktion entlang DataFrames 's Zeilen (mit apply mit axis=1). Die Funktion gibt ein NDArray mit 2 Dimensionen zurück. Ich würde die Rückkehr des apply wie ein einzelnes Objekt Spalte zu sein, die 2D-NDArrays enthalten geschieht, sondern erhalte ich:Rückgabe von 2D NDArray in Pandas DataFrame.apply

<venv>/lib/python2.7/site-packages/pandas/core/frame.pyc in _homogenize(data, index, dtype) 
    5544     v = lib.fast_multiget(v, oindex.values, default=NA) 
    5545    v = _sanitize_array(v, index, dtype=dtype, copy=False, 
-> 5546         raise_cast_failure=False) 
    5547 
    5548   homogenized.append(v) 

<venv>/lib/python2.7/site-packages/pandas/core/series.pyc in _sanitize_array(data, index, dtype, copy, raise_cast_failure) 
    2918  elif subarr.ndim > 1: 
    2919   if isinstance(data, np.ndarray): 
-> 2920    raise Exception('Data must be 1-dimensional') 
    2921   else: 
    2922    subarr = _asarray_tuplesafe(data, dtype=dtype) 

Exception: Data must be 1-dimensional 

Gibt es eine Möglichkeit Pandas zu sagen, nicht zu versuchen, das Array auszupacken?

UPDATE Beispiel:

arr = np.ones((3,3)) 
pd.DataFrame({'d': [arr, arr]}).apply(lambda x: x.ix['d'], axis=1) 
+0

können Sie hinzufügen ein Beispieldatensatz, definiti von Ihrer Funktion und dem gewünschten Datensatz auf Ihren Beitrag? – MaxU

+0

'df.ix ['d']' erzeugt einen Fehler - es ist nicht klar, was Sie erreichen möchten (was ist der gewünschte DF/Datensatz)? – MaxU

+0

Richtig dies gilt zeilenweise zu übergeben an das Lambda ist eine Serie entsprechend der Zeile, wo der Index der Serie ist die Spalte Namen, –

Antwort

0

apply auf einer Reihe laufen und es mit mehrdimensionalen Objekten Füllung funktioniert

pd.Series([1, 2]).apply(lambda x: np.array([[x, x], [x, x]])) 

0 [[1, 1], [1, 1]] 
1 [[2, 2], [2, 2]] 
dtype: object 

jedoch auf einem Datenrahmen Pandas ist die Rückkehr erwartet Wert, um skalar oder eindimensional zu sein

Betrachten Sie die d ataframe df

df = pd.DataFrame([[1, 2]]) 

Diese

df.apply(lambda x: 1) 

0 1 
1 1 
dtype: int64 

arbeitet Und diese

df.apply(lambda x: [1]) 

    0 1 
0 1 1 

Und dieses

df.apply(lambda x: [1] * 2) 

0 [1, 1] 
1 [1, 1] 
dtype: object 

Beachten Sie, dass, wenn wireine Liste der zurückgegebenen Längegab es einen Datenrahmen zurück, aber als wir eine Liste mit einer Länge größer als 1 zurückgaben, kehrte sie zu einer Reihe von Listen zurück.

HOLDON!
ist die Länge der df

df = pd.DataFrame([[1, 2]] * 2) 

und führen das gleiche

df.apply(lambda x: [1] * 2) 

    0 1 
0 0 0 
1 0 0 

Whoa Lassen verdoppeln! Ok, ich habe genau dasselbe auf zwei verschiedenen Datenfeldern ausgeführt. Es scheint, dass, wenn die Länge des Rückgabewerts mit der Aus-Dimension des Datenrahmens übereinstimmt, pandas annimmt, den Rückgabewert mit dem Aus-Dimensionsindex in Übereinstimmung zu bringen.

Wir können dies mit pd.Series übergehen, wo Pandas auf seine Interpretation verzichten und den Reihenindex verwenden, den es gegeben wurde.

df.apply(lambda x: pd.Series([1] * 5)) 

    0 1 
0 1 1 
1 1 1 
2 1 1 
3 1 1 
4 1 1 

Und was ndarray

Dies bricht

df.apply(lambda x: np.ones((3, 2))) 
Exception: Data must be 1-dimensional 

Das funktioniert aber nicht, was Sie wollen


Lösung

Stattdessen würde ich ein Verständnis mit einem pd.Series Rap mit dem übergebenen Index

f = lambda x: np.ones((3, 2)) 

pd.Series([f(c) for _, c in df.iteritems()], df.columns) 

0 [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0]] 
1 [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0]] 
dtype: object 

Hinweis:

type(pd.Series([f(c) for _, c in df.iteritems()], df.columns).iloc[0]) 

numpy.ndarray 
Verwandte Themen