2015-05-27 10 views
7

Ich dachte, ich verstehe map vs applymap ziemlich gut, aber habe ein Problem (siehe here für zusätzlichen Hintergrund, wenn Sie interessiert sind).Karte vs applymap beim Übergeben eines Wörterbuchs

Ein einfaches Beispiel:

df = pd.DataFrame([[1,2],[1,1]]) 
dct = { 1:'python', 2:'gator' } 

df[0].map(lambda x: x+90) 
df.applymap(lambda x: x+90) 

Das funktioniert wie erwartet - sowohl auf Basis arbeitet element, Karte auf einer Reihe, applymap auf einem Datenrahmen (sehr gut erklärt here btw).

Wenn ich einen Wörterbuch eher als ein Lambda verwenden, funktioniert Karte noch in Ordnung:

df[0].map(dct) 

0 python 
1 python 

aber nicht applymap:

df.applymap(dct) 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-100-7872ff604851> in <module>() 
----> 1 df.applymap(dct) 

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\frame.pyc in applymap(self, func) 
    3856     x = lib.map_infer(_values_from_object(x), f) 
    3857    return lib.map_infer(_values_from_object(x), func) 
-> 3858   return self.apply(infer) 
    3859 
    3860  #---------------------------------------------------------------------- 

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\frame.pyc in apply(self, func, axis, broadcast, raw, reduce, args, **kwds) 
    3687      if reduce is None: 
    3688       reduce = True 
-> 3689      return self._apply_standard(f, axis, reduce=reduce) 
    3690    else: 
    3691     return self._apply_broadcast(f, axis) 

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\frame.pyc in _apply_standard(self, func, axis, ignore_failures, reduce) 
    3777    try: 
    3778     for i, v in enumerate(series_gen): 
-> 3779      results[i] = func(v) 
    3780      keys.append(v.name) 
    3781    except Exception as e: 

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\frame.pyc in infer(x) 
    3855     f = com.i8_boxer(x) 
    3856     x = lib.map_infer(_values_from_object(x), f) 
-> 3857    return lib.map_infer(_values_from_object(x), func) 
    3858   return self.apply(infer) 
    3859 

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\lib.pyd in pandas.lib.map_infer (pandas\lib.c:56990)() 

TypeError: ("'dict' object is not callable", u'occurred at index 0') 

So ist meine Frage, warum Karte nicht und applymap Arbeit in analoger Weise hier? Ist es ein Fehler mit appmap, oder mache ich etwas falsch?

bearbeiten hinzufügen: Ich habe entdeckt, dass ich um diese ziemlich leicht mit diesem arbeiten kann:

df.applymap(lambda x: dct[x]) 

     0  1 
0 python gator 
1 python python 

Oder noch besser über diesen answer die kein Lambda erfordert.

df.applymap(dct.get) 

Also das ist ziemlich genau gleichwertig, oder? Muss etwas damit sein, wie applymap die Syntax analysiert und ich denke, die explizite Form einer Funktion/Methode funktioniert besser als ein Wörterbuch. Wie auch immer, ich denke, jetzt gibt es kein praktisches Problem mehr, aber ich bin immer noch daran interessiert, was hier vor sich geht, wenn jemand antworten möchte.

+1

df.applymap() nicht anwenden .map() auf jeder Reihe des DataFrame, setzen Sie map .apply() auf jeder Serie. Siehe Serie .apply() hier: [link] (http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.apply.html) And .apply() benötigt eine Funktion als Argument und kann kein Dictionary nehmen, wie .map() tun kann. –

+1

Entschuldigung, ich verstehe wirklich nicht, was Sie hier sagen. Ich denke, dass appmap und map nicht gleichwertig sind, was ich nicht bestreite, aber ich habe kein besseres Verständnis dafür, warum oder wie. Um aus dem obigen Link zu zitieren (zu einer sehr populären SO-Antwort): "appmap funktioniert elementweise auf einem DataFrame, und Map funktioniert elementweise auf einer Serie." Ich hoffe auf einige Ausführungen zu diesem Punkt. – JohnE

Antwort

5

.applymap() und .map() ist wahr, um elementweise zu arbeiten. Aber .applymap() nimmt nicht alle Spalten und macht .map() auf diesen, aber tut .apply() auf jedem von diesen.

Also, wenn Sie anrufen df.applymap (dct): was passiert ist df [0] .apply (dct), df nicht [0] .map (dct)

Und hier, was die Unterschied zwischen diesen beiden Series-Methoden:

.map() akzeptieren Serie, dict und Funktion (alle aufrufbar, damit Methoden wie dict.get funktionieren auch) als erstes Argument; als .apply() akzeptieren nur Funktion (oder alle aufrufbar) als erstes Argument.

.map() enthält if-Anweisung, um herauszufinden, ob das erste übergebene Argument ein dict, eine Serie oder eine Funktion ist und entsprechend der Eingabe funktioniert. Wenn Sie eine Funktion an .map() übergeben, führt die .map() -Methode die gleichen Funktionen wie .apply() aus.

Aber .apply() haben nicht diese if-Anweisungen, die es ermöglichen, mit Dictionary und Serie zu behandeln. Es kann nur mit Callable arbeiten.

Wenn Sie .apply() oder .map() mit einer Funktion aufrufen, enden beide mit dem Aufruf von lib.map_infer(), die sich wie die map() - Funktion von python verhalten (aber ich kann meine Hand anlegen) der Quellcode ist also nicht ganz sicher).

Doing map (dct, df [0]) wird Ihnen den gleichen Fehler wie df.applymap (dct) und df [0] .apply (dct) wird auch den gleichen Fehler geben.

Jetzt können Sie fragen, warum mit .apply() anstelle von .map(), wenn .map() dasselbe tun, wenn mit einer Funktion aufgerufen wird und dict und Series nehmen kann?

Weil .apply() Ihnen einen Dataframe zurückgeben kann, wenn das Ergebnis der Funktion, die Sie übergeben, eine Serie ist.

ser = pandas.Series([1,2,3,4,5], index=range(5)) 

ser_map = ser.map(lambda x : pandas.Series([x]*5, index=range(5))) 
type(ser_map) 
pandas.core.series.Series 

ser_app = ser.apply(lambda x : pandas.Series([x]*5, index=range(5))) 
type(ser_app) 
pandas.core.frame.DataFrame 
+0

Danke! Das Beispiel, das zeigt, wie eine Karte eine Serie erzeugt und einen Datenrahmen erzeugt, erklärt auch einige Ergebnisse, die ich in der Vergangenheit erhalten und nicht verstanden habe. Mein Verständnis von all dem ist immer noch ein bisschen weniger als 100%, aber das hilft. – JohnE

Verwandte Themen