lambda durch List comprehension ersetzen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
C#17
User
Beiträge: 19
Registriert: Montag 22. Mai 2017, 12:19

Hallo liebes Forum,

ich habe ein pandas DataFrame welcher wie folgt ausschaut.:

Code: Alles auswählen

   key  data1  data2   
0   A      0      5         
1   B      1      0    
2   C      2      3     
3   A      3      3
4   B      4      7
5   C      5      9
Mittels der Funktion

Code: Alles auswählen

 df.groupby('key').transform(lambda x: x - x.mean())
zentriere ich die Werte der "data1" und "data2". Nun habe ich in einigen Lehrbüchern gelesen, dass man anstatt der lambda Funktion eher die List comprehension verwenden soll.
Meine Frage wäre nun wie diesen Ausruck durch eine LC ersetzen kann....
Es ist ja so, dass, "groupby" ein groupby Objekt zurück gibt auf welches zugegriffen und welches weiter verwendet werden kann.
Meine Idee wäre nun etwas wie:

Code: Alles auswählen

df.groupby("key").transform([x-x.mean() for x in df.groupby("key")])
Das Problem scheint hierbei zu sein, dass die LC nicht "weiss" welches Element des von df.groupby("key") zurückgegebenen Objektes sie als x nehmen soll da ich immer die Fehlermeldung bekomme:

AttributeError: 'tuple' object has no attribute 'mean'

Ich hoffe mir kann jemand weiterhelfen.

Lg
nezzcarth
User
Beiträge: 1632
Registriert: Samstag 16. April 2011, 12:47

So allgemein kann trifft diese Aussage meiner Meinung nach nicht zu, weil List-Comprehensions und Lambda-Ausdrücke für ganz verschiedene Dinge verwendet werden; LCs sind äquivalent zu Schleifen, die eine Liste befüllen, Lambda-Ausdrücke (anonyme Funktionen) sind äquivalent zu voll ausgeschrieben Funktionen.

Was ich mir vorstellen kann, ist, dass in den Lehrbüchern 'map' und/oder 'filter' gemeint waren. Dort verwendet man öfter mal Lambdas als Prädikat und diese würden sich in eine "Langform" aus List-Comprehension und Funktion umschreiben lassen.

Kurzum:Ich würde sagen, du kannst es so lassen, wie es ist.
Zuletzt geändert von nezzcarth am Montag 5. Juni 2017, 09:57, insgesamt 1-mal geändert.
C#17
User
Beiträge: 19
Registriert: Montag 22. Mai 2017, 12:19

Hm okay nun ja also in dem Buch wird es tatsächlich so beschrieben dass man mit den List-Comprehensions alles erreichen kann was man auch mit lambda erreichen kann...

Wie könnte ich das Problem aber dennoch mit einer LC lösen?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

C#17 hat geschrieben:Hm okay nun ja also in dem Buch wird es tatsächlich so beschrieben dass man mit den List-Comprehensions alles erreichen kann was man auch mit lambda erreichen kann...
Dann ist das aber kein so dolles Buch...
Wie könnte ich das Problem aber dennoch mit einer LC lösen?
Wieso willst Du das denn unbedingt? Das sieht doch ganz gut und lesbar aus!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
C#17
User
Beiträge: 19
Registriert: Montag 22. Mai 2017, 12:19

Weil ich lernen will und verstehen möchte :)
nezzcarth
User
Beiträge: 1632
Registriert: Samstag 16. April 2011, 12:47

C#17 hat geschrieben:Hm okay nun ja also in dem Buch wird es tatsächlich so beschrieben dass man mit den List-Comprehensions alles erreichen kann was man auch mit lambda erreichen kann...
Ich würde Hyperion zustimmen.

Ich weiß ja nicht, ob ich was übersehe, aber:
Wenn du wirklich daran festhalten möchtest, musst du denke ich 'transform' loswerden und das durch etwas Eigenes ersetzen. 'Transform' ist eine Funktion(/Methode) höherer Ordnung (wie auch map oder filter) und braucht als solche eine Funktion (bzw. ein callable) als erstes Argument. Dass du überhaupt eine Liste übergeben kannst, liegt daran, dass 'transform' auch Listen und Dictionaries von Funktionen oder Strings mit Funktionennamen nimmt. Diese werden auf die Elemente des Dataframes angewendet und es wird ein neues Dataframe mit den Resultaten, die der Funktionsaufruf für jedes Element ergeben hat, erzeugt und zurückgegeben. Diesen Ablauf müsstest du dann halt selbst in eine LC gießen.
C#17
User
Beiträge: 19
Registriert: Montag 22. Mai 2017, 12:19

okay vielen Dank. Das mit der Funktion welche an transform() übergeben werden muss hat mir i wie gefehlt... d.h.

Code: Alles auswählen

df.groupby('key').transform(lambda x: x - x.mean())
ist so zu sagen die Kurzfassung von:

Code: Alles auswählen

def normalize(x):
    x= x-x.mean()
    return(x)

print(df.groupby("key").transform(normalize))
und damit macht es eigentlich keinen Sinn es mit einer LC zu machen, da dies nur "umständlich" (vor allem für einen Neuling) zu bewerkstelligen ist....
Vielen Dank!
nezzcarth
User
Beiträge: 1632
Registriert: Samstag 16. April 2011, 12:47

Ja, im Prinzip schon, die Funktion ist nur ein Ersatz für den Lambda-Ausdruck, nicht den gesamten Aufruf von 'transform'. Üblicherweise würde man die Funktion noch etwas vereinfachen, in dem man die Klammern bei 'return' weglässt und das Ergebnis gleich zurück gibt, statt es erst an einen Namen zu binden:

Code: Alles auswählen

def normalize(x):
    return x - x.mean()
Allerdings ist es wie gesagt empfehlenswert, es so zu lassen, wie du es hattest.
Antworten