analogie zu sverweis?

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
peterwoodbridge
User
Beiträge: 50
Registriert: Freitag 30. November 2012, 10:26

Ich habe 2 Dataframes:

Code: Alles auswählen

df1 = pd.DataFrame({"G1": ["alfa", "beta", "delta"], "G2": ['Hanjo', 'Adil', 'Bouncer']})

Code: Alles auswählen

df2 = pd.DataFrame({"D1": ["Adil", "Podo", "Hanjo", "Holger"], "E2": ['XY', 'Bouncer', 'Bouncer', 'Stan'], "G3": ['Zehn', 'Zwanzig', 'Null', 'Eins']})
Nun möchte ich im zweiten Dataframe 2 weitere Kolonnen hinzufügen: Die erste soll jeweils die Werte von D1 kontrollieren, ob sie in der Spalte G2 vorkommen; falls ja sollte der Wert von G1 erscheinen in der neuen Spalte

In der zweiten neuen Spalte soll E2 kontrolliert werden mit G2; falls dieser Name auftaucht, soll wieder der entsprechende Wert von G1 erscheinen.

Mein Problem ist der "sverweis": ich kann für einen string das "isin" nicht verwenden.

Den "Wert" von G1, wenn G2 gefunden wird, würde ich hinbekommen mit: df1.G1[df1.G2.index[0]] (falls der Wert "Hanjo" ist)

Ich wäre dankbar, wenn mir jemand weiter helfen kann.

Die Lösung würde so aussehen:

Code: Alles auswählen

df2 = pd.DataFrame({"D1": ["Adil", "Podo", "Hanjo", "Holger"], "E2": ['XY', 'Bouncer', 'Bouncer', 'Stan'], "G3": ['Zehn', 'Zwanzig', 'Null', 'Eins'], "Spalte X": ["beta", NaN, "alfa", NaN], "Spalte Z": [NaN, "delta", "delta", NaN]})
BlackJack

@peterwoodbridge: Dazu kann man den Index von Pandas-Objekten verwenden. Der ist ja so etwas wie ein Schlüssel in relationalen Datenbanken. Und `DataFrame`-Objekte haben eine `join()`-Methode die diesen Datenbanken nicht unähnlich ist.

Code: Alles auswählen

In [71]: df1
Out[71]: 
      G1       G2
0   alfa    Hanjo
1   beta     Adil
2  delta  Bouncer

In [72]: df2
Out[72]: 
       D1       E2       G3
0    Adil       XY     Zehn
1    Podo  Bouncer  Zwanzig
2   Hanjo  Bouncer     Null
3  Holger     Stan     Eins

In [73]: s = pd.Series(df1.G1, df1.G2, name='Spalte X')

In [74]: s
Out[74]: 
Hanjo       alfa
Adil        beta
Bouncer    delta
Name: Spalte X

In [75]: df3 = df2.join(s, 'D1')

In [76]: df3
Out[76]: 
       D1       E2       G3 Spalte X
0    Adil       XY     Zehn     beta
1    Podo  Bouncer  Zwanzig      NaN
2   Hanjo  Bouncer     Null     alfa
3  Holger     Stan     Eins      NaN

In [77]: s.name = 'Spalte Z'

In [78]: df4 = df3.join(s, 'E2')

In [79]: df4
Out[79]: 
       D1       E2       G3 Spalte X Spalte Z
0    Adil       XY     Zehn     beta      NaN
1    Podo  Bouncer  Zwanzig      NaN    delta
2   Hanjo  Bouncer     Null     alfa    delta
3  Holger     Stan     Eins      NaN      NaN
peterwoodbridge
User
Beiträge: 50
Registriert: Freitag 30. November 2012, 10:26

Eine Idee habe ich, jedoch frage ich mich, wie gut sie ist (da sie sehr umständlich erscheint):

Code: Alles auswählen

df2["Spalte X"] = "x"
df2["Spalte Z"] = "x"

for i, v in df2.iterrows():
    if df2.ix[i, "D1"] in list(df1.G2):
        df2.ix[i, "Spalte X"] = df1.G1[list(df1.G2).index(df2.ix[i, "D1"])]
    if df2.ix[i, "E2"] in list(df1.G2):
        df2.ix[i, "Spalte Z"] = df1.G1[list(df1.G2).index(df2.ix[i, "E2"])]
und am Ende würde ich noch x mit np.nan ersetzen



Edith: hey Blackjack: erst jetzt deine Lösung gesehen; und sorry, dass ich immer mit iterrows komme :D (aber mir fehlen nach wie vor die Kenntnisse)
peterwoodbridge
User
Beiträge: 50
Registriert: Freitag 30. November 2012, 10:26

@Blackjack:

wenn ich s = pd.Series(df1.G1, df1.G2, name='Spalte X') schreibe, erhalte ich:

Hanjo NaN
Adil NaN
Bouncer NaN
Name: Spalte X

habe deine Zeile nur copy paste gemacht, nichts variiert. An was liegt das?
peterwoodbridge
User
Beiträge: 50
Registriert: Freitag 30. November 2012, 10:26

anscheinend muss ich es ändern in:

s = pd.Series(list(df1.G1), df1.G2, name='Spalte X') ?
BlackJack

@peterwoodbridge: Ich nehme mal an, dass wir da verschiedene Versionen von `pandas` verwenden und sich die API geändert hat. Ich würde es dann so ändern:

Code: Alles auswählen

In [95]: s = pd.Series(df1.G1, index=df1.G2, name='Spalte X')

In [96]: s
Out[96]: 
Hanjo       alfa
Adil        beta
Bouncer    delta
Name: Spalte X
peterwoodbridge
User
Beiträge: 50
Registriert: Freitag 30. November 2012, 10:26

Hi Blackjack: leider ging dies auch nicht mit deiner Lösung; nun hab ich meine verwendet mit Liste.

Nun noch eine Frage:

wenn ich in meinem DataFrame einen np.nan Wert habe; wie kann ich das DataFrame filtern, so dass er mir alle Zeilen gibt, wo in einer bestimmten Spalte der Wert nan auftaucht und wie kann ich mir alle Zeilen geben lassen, wo der Wert nicht nan ist?
zB in folgendem DataFrame:

Code: Alles auswählen

import numpy as np
df2 = pd.DataFrame({"D1": ["Adil", "Podo", "Hanjo", "Holger"], "E2": ['XY', 'Bouncer', 'Bouncer', 'Stan'], "G3": ['Zehn', 'Zwanzig', 'Null', 'Eins']})
df2[df2 == "Bouncer"] = np.nan
leider geht folgendes nicht:

Code: Alles auswählen

df3 = df2[df2["E2] == np.nan]
(auch nicht, wenn ich nur nan schreibe)
Zuletzt geändert von peterwoodbridge am Mittwoch 20. März 2013, 10:40, insgesamt 1-mal geändert.
BlackJack

@peterwoodbridge: Das liegt daran, dass NaN ungleich *allem* ist, sogar ungleich NaN selbst:

Code: Alles auswählen

In [18]: np.nan == np.nan
Out[18]: False

In [19]: np.nan != np.nan
Out[19]: True
Das Verhalten ist im IEEE 754 Gleitkommastandard definiert: https://en.wikipedia.org/wiki/NaN#Floating_point

Du kannst also entweder auf ungleich vergleichen und gegebenenfalls das Ergebnis negieren, oder die `isnull()`-Methode auf dem `Series`-Exemplar verwenden:

Code: Alles auswählen

In [22]: df2[df2.E2.isnull()]
Out[22]: 
      D1   E2       G3
1   Podo  NaN  Zwanzig
2  Hanjo  NaN     Null

In [23]: df2[~df2.E2.isnull()]
Out[23]: 
       D1    E2    G3
0    Adil    XY  Zehn
3  Holger  Stan  Eins

In [24]: df2[~(df2.E2 != np.nan)]
Out[24]: 
      D1   E2       G3
1   Podo  NaN  Zwanzig
2  Hanjo  NaN     Null

In [25]: df2[df2.E2 != np.nan]
Out[25]: 
       D1    E2    G3
0    Adil    XY  Zehn
3  Holger  Stan  Eins
peterwoodbridge
User
Beiträge: 50
Registriert: Freitag 30. November 2012, 10:26

Hi
Besten Dank!!

Bei mir geht allerdings folgendes nicht:
df2[~(df2.E2 != np.nan)]
(empty dataframe)

df2[df2.E2 != np.nan]
(zeigt mir 4 Reihen)

nur die isnull() funktionen gehen bei mir :)
Antworten