Seite 1 von 1
Apply function to every different row of a column
Verfasst: Donnerstag 22. August 2019, 22:28
von BroNKo
Guten Abend, eine Anfängerfrage. Folgender Code
Im Moment wird die Funktion auf alle rows des DF angewendet. Was wäre die einfachste Methode um zu gewährleisten das die Funktion nur auf rows angewendet wird die einen verschiedenen Wert haben der im column noch nicht vorkam?
Hätte noch eine andere Frage zur Ausgabe, wenn ich z.B. folgenden Code ausführe
dann wird mir ja eine Tabelle ausgegeben mit einem column in dem die Werte aus IsX stehen und einem column mit der Anzahl. Wenn ich aber das erste Codebeispiel ausführe wird in der Ausgabe nicht die Ursprüngliche Code ausgegeben sondern nur ein column mit den Rückgabewerten der Funktion. Wie kann ich aber die Ursprünglichen werte in einem column und die Rückgabewerte in einem zweiten ausgeben lassen? Hoffe man versteht was ich meine.
--> Ausgabe im Moment
Column1
Rückgabewert1
Rückgabewert2
Rückgabewert3
--> Gewünschte Ausgabe
Column1 Column2
Wert1 Rückgabewert1
Wert2 Rückgabewert2
Wert3 Rückgabewert3
Danke schonmal für Hilfe! lg
Re: Apply function to every different row of a column
Verfasst: Freitag 23. August 2019, 00:33
von __blackjack__
Man kann mit `duplicated()` auf dem `Series`-Objekt ein `Series`-Objekt bekommen das `False` bei jedem zum ersten mal gesehenen Wert liefert und `True` sonst. Du willst eigentlich das Gegenteil — die Werte die das erste mal gesehen wurden, also mit ``~`` negieren und als Index in das `Series`-Objekt verwenden. Und auf dem Ergebnis kannst Du dann Dein `apply()` aufrufen.
Beispiel mit einem Satz von 100 Zufallswerten zwischen 1 und 10:
Code: Alles auswählen
In [30]: df
Out[30]:
x
0 6
1 1
2 6
3 9
4 3
5 9
6 4
7 7
8 4
9 3
10 4
11 3
12 8
13 2
14 2
15 3
16 10
17 7
18 6
19 5
20 9
21 10
22 4
23 6
24 2
25 5
26 4
27 8
28 3
29 6
.. ..
70 10
71 6
72 6
73 4
74 5
75 3
76 10
77 8
78 1
79 2
80 1
81 7
82 1
83 1
84 9
85 1
86 10
87 9
88 2
89 8
90 1
91 10
92 7
93 2
94 4
95 4
96 2
97 6
98 1
99 5
[100 rows x 1 columns]
In [31]: df.x.duplicated()
Out[31]:
0 False
1 False
2 True
3 False
4 False
5 True
6 False
7 False
8 True
9 True
10 True
11 True
12 False
13 False
14 True
15 True
16 False
17 True
18 True
19 False
20 True
21 True
22 True
23 True
24 True
25 True
26 True
27 True
28 True
29 True
...
70 True
71 True
72 True
73 True
74 True
75 True
76 True
77 True
78 True
79 True
80 True
81 True
82 True
83 True
84 True
85 True
86 True
87 True
88 True
89 True
90 True
91 True
92 True
93 True
94 True
95 True
96 True
97 True
98 True
99 True
Name: x, Length: 100, dtype: bool
In [32]: ~df.x.duplicated()
Out[32]:
0 True
1 True
2 False
3 True
4 True
5 False
6 True
7 True
8 False
9 False
10 False
11 False
12 True
13 True
14 False
15 False
16 True
17 False
18 False
19 True
20 False
21 False
22 False
23 False
24 False
25 False
26 False
27 False
28 False
29 False
...
70 False
71 False
72 False
73 False
74 False
75 False
76 False
77 False
78 False
79 False
80 False
81 False
82 False
83 False
84 False
85 False
86 False
87 False
88 False
89 False
90 False
91 False
92 False
93 False
94 False
95 False
96 False
97 False
98 False
99 False
Name: x, Length: 100, dtype: bool
In [33]: df.x[~df.x.duplicated()]
Out[33]:
0 6
1 1
3 9
4 3
6 4
7 7
12 8
13 2
16 10
19 5
Name: x, dtype: int64
In [34]: df.x[~df.x.duplicated()].apply(lambda x: -x)
Out[34]:
0 -6
1 -1
3 -9
4 -3
6 -4
7 -7
12 -8
13 -2
16 -10
19 -5
Name: x, dtype: int64
Bei Deinem Code ist übrigens das ``lambda`` überflüssig wenn das nur dazu dient das Argument 1:1 an die tatsächliche Funktion durchzureichen.
Die zweite Frage verstehe ich nicht, denn Du bekommst doch ein `Series`-Objekt und das hat einen Index, und der Index sind genau die Werte die Du gerne hättest:
Code: Alles auswählen
In [35]: df.x.value_counts()
Out[35]:
8 14
1 12
4 11
10 10
7 10
3 10
2 10
9 9
6 8
5 6
Name: x, dtype: int64
Re: Apply function to every different row of a column
Verfasst: Freitag 23. August 2019, 11:46
von BroNKo
Danke für die ausführliche Anwort. Zu meiner zweiten Frage.
Code: Alles auswählen
df_temp = pd.DataFrame()
df_temp = (df_con.IsX[~df_con.IsX.duplicated()])
df_temp['VoX'] = df_temp.apply(lambda x: (function(x)))
df_temp
Verstehe nicht warum das nicht funktioniert. Es wird immer eine neue Zeile eingefügt?? Eigentlich müsste hier doch eine column eingefügt werden. Die Länge stimmt ja auch???
[Out]
0 wert1
1 wert2
2 wert3
3 wert4
4 und dann wird bei mir am Schluss in einer Zeile der komplette inhalt der neuen Column ['VoX'] geschrieben
Hoffe man versteht mein Problem. Wenn ich Beispielcode aus dem Internet verwende funktioniert es??
Re: Apply function to every different row of a column
Verfasst: Freitag 23. August 2019, 12:09
von __blackjack__
@BroNKo: Also die erste Zeile ist überflüssig weil der leere `DataFrame` ja nie für irgendetwas verwendet wird. Insgesamt sind in dem Code auch zwei Klammerpaare zu viel die keinen Effekt haben und auch die Lesbarkeit nicht erhöhen weil beide nichts gruppieren.
Ich weiss nicht was Du mit „die Länge stimmt ja auch“ meinst — das Ergebnis vom `apply()` beziehungsweise ja schon das `Series`-Objekt auf das `apply()` aufgerufen wird ist kürzer als der `DataFrame`. Das entscheidende ist hier nicht die Länge, sondern das die Indexwerte von `Series` und `DataFrame` passen, damit die Zuweisung an eine neue Spalte im `DataFrame` funktioniert. Mit den Beispieldaten aus meinem letzten Beitrag:
Code: Alles auswählen
In [54]: df.x[~df.x.duplicated()]
Out[54]:
0 6
1 1
3 9
4 3
6 4
7 7
12 8
13 2
16 10
19 5
Name: x, dtype: int64
In [55]: df['vx'] = df.x[~df.x.duplicated()].apply(lambda x: -x * 1000)
In [56]: df
Out[56]:
x vx
0 6 -6000.0
1 1 -1000.0
2 6 NaN
3 9 -9000.0
4 3 -3000.0
5 9 NaN
6 4 -4000.0
7 7 -7000.0
8 4 NaN
9 3 NaN
10 4 NaN
11 3 NaN
12 8 -8000.0
13 2 -2000.0
14 2 NaN
15 3 NaN
16 10 -10000.0
17 7 NaN
18 6 NaN
19 5 -5000.0
20 9 NaN
21 10 NaN
22 4 NaN
23 6 NaN
24 2 NaN
25 5 NaN
26 4 NaN
27 8 NaN
28 3 NaN
29 6 NaN
.. .. ...
70 10 NaN
71 6 NaN
72 6 NaN
73 4 NaN
74 5 NaN
75 3 NaN
76 10 NaN
77 8 NaN
78 1 NaN
79 2 NaN
80 1 NaN
81 7 NaN
82 1 NaN
83 1 NaN
84 9 NaN
85 1 NaN
86 10 NaN
87 9 NaN
88 2 NaN
89 8 NaN
90 1 NaN
91 10 NaN
92 7 NaN
93 2 NaN
94 4 NaN
95 4 NaN
96 2 NaN
97 6 NaN
98 1 NaN
99 5 NaN
[100 rows x 2 columns]
Wie man sieht eine Menge NaN-Werte wo das `apply()`-Ergebnis keinen Wert hat.
Re: Apply function to every different row of a column
Verfasst: Freitag 23. August 2019, 12:43
von __blackjack__
@BroNKo: Ah, Moment, ich habe mich vom Namen `df_temp` täuschen lassen: Das ist ja gar kein `DataFrame` sondern ein `Series`-Objekt — was soll denn das bedeuten was Du da machst? Was es tatsächlich bedeutet ist: füge an Index "VoX" eine neues Datum zu dem `Series`-Objekt hinzu, also wenn man das `Series`-Objekt als Spalte sieht, fügt das eine weitere Zeile hinzu. Und der Datentyp der Spalte ist dann natürlich `object` weil man als Wert zu einer vorher numerischen Spalte ein `Series`-Objekt hinzufügt, und das hat natürlich keinen kleineren gemeinsamen Nenner als `object`.
Code: Alles auswählen
In [58]: s = df.x[~df.x.duplicated()]
In [59]: s['vx'] = s.apply(lambda x: -x * 1000)
In [60]: s
Out[60]:
0 6
1 1
3 9
4 3
6 4
7 7
12 8
13 2
16 10
19 5
vx 0 -6000
1 -1000
3 -9000
4 -300...
Name: x, dtype: object
Beispiel dafür das gute und *passende* Namen wichtig sind. Nenne nix `df_irgendwas` was nicht tatsächlich ein `DataFrame` ist. Sonst ist Verwirrung beim Leser – und hier ja auch beim Autor selbst – vorprogrammiert.
Re: Apply function to every different row of a column
Verfasst: Samstag 24. August 2019, 11:43
von BroNKo
@__blackjack__ Danke für deine Mühe. Ja hab das so genannt weil es eigentlich ein Dataframe sein sollte. Aller Anfang ist schwer. Hab jetzt die Lösung für mein Problem nach 3 Stunden trail and error. Manchmal geht es einem so als Anfänger das man am Anfang der Lösung am nächsten ist und nur ein Syntaxfehler dazuführt das man sich im Ausprobieren immer weiter von der richtigen Lösung entfernt. Die überflüssigen Klammern kommen meist daher das ich versuche nur den für mein Problem relevanten Code hier einzustellen.
Code: Alles auswählen
def df_get_isX_vol(df):
df_temp = pd.DataFrame(df.IsX[~df.IsX.duplicated()])
df_temp['Vol'] = df_temp.IsX.apply(lambda x: IsX_delta_vol(x))
return df_temp
So einfach wäre es gewesen

Hoffe das ist jetzt so halbwegs sauber programmiert. Danke dir nochmal blackjack!
Re: Apply function to every different row of a column
Verfasst: Samstag 24. August 2019, 12:47
von __blackjack__
@BroNKo: Der ``lambda``-Ausdruck ist hier eine unnötige Indirektion. Einfach ``….apply(IsX_delta_vol)`` reicht. `df_temp` würde ich `result` oder so nennen, denn wenn etwas als Ergebnis zurückgegeben wird, dann ist es ja nicht wirklich „temporär“ – oder zumindest weiss man das an dieser Stelle nicht. Beziehungsweise könnte man an *alle* lokalen Namen ein „_temporary“ anhängen, was aber nicht wirklich einen Gewinn für den Leser bringt. Oh, und abgekürzt ist es ein bisschen problematisch, weil man sich in bestimmten Fällen fragen muss was es eigentlich bedeutet – „temporary“ oder „temperature“.