Pandas: Werte einer Zelle verschieben wenn Bedingung erfüllt. Lambda Funktion

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
andreas96
User
Beiträge: 11
Registriert: Montag 7. September 2020, 08:27

Ich benutze pandas in python3. In einem Dataframe mit drei Spalten (col_X, col_Y and col_Z) sind die ersten beiden Spalten (col_X, col_Y) komplett gefüllt, die dritte nur teilweise. Ich möchte die Werte aus der mittelern Spalte (col_Y) in die Nachbarspalte (col_Z) verschieben unter der Bedingung, dass sie leer ist, bzw. in ihr ist "-". Dann den Ursprung löschen. Hilfsweise habe ich eine Spalte col_K eingeführt die als Zwischenlager dient.

Sind also drei Werte vorhanden mache nichts, gehe zur nächsten Zeile, sind zwei Zellen gefüllt, kopiere den mittleren Wert nach rechts, lösche alten Wert, also lasse die mittlere frei und gehe zur nächsten Zeile. Die Liste ist sehr lang, daher soll der Zellenwechsel durch die Spaltenbereiche durchlaufen. Versucht habe ich bisher map, applymap, apply, lambda, conditional. Es wird immer nur die mittlere Spalte kopiert, nicht aber die else Bedingung ausgeführt. Auch die loc Funktion hat in der unten dargestellten Form nicht funktioniert.

Bilder der Tabellen:
Ausgangstabelle: Bild
Gewünschte Tabelle: Bild

Code: Alles auswählen

import pandas as pd

df = pd.read_csv("C:/DATA/daten/shift_value_if.csv",
                 sep=";",
                 decimal=",",
                 usecols=["col_X", "col_Y", "col_Z"])

df['col_K'] = df['col_Y'].apply(lambda x: 'col_Z' if x == '-' else x)

print(df)
Die loc Funktion hat auch nicht geholfen:

Code: Alles auswählen

df.loc[df['col_Z'] == '-', 'col_Z'] = df['col_Y']
Benutzeravatar
__blackjack__
User
Beiträge: 13926
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@andreas96: Ich würde eine Maske erzeugen mit den Bedingungen das in "col_Z" ein "-" steht und in "col_Y" kein "-" steht. Und dann kann man mit zwei Zuweisungen erst "col_Z" die Werte aus "col_Y" zuweisen und dann eine leere Zeichenkette "col_Y" zuweisen.

Beispieldaten machen sich besser in einem Format das man auch benutzen kann, statt eines Bildes. Und bei Bildern muss man einen Link auf *das Bild* in den Beitrag einbinden, nicht auf eine Webseite die das Bild enthält.

Edit:

Code: Alles auswählen

In [223]: df                                                                    
Out[223]: 
      col_X     col_Y     col_Z
0         -         -         -
1         -         -         -
2  HX220LAD  HX340LAD         -
3  HX220LAD   HCT780X  HX340LAD
4  HX220LAD   HCT780X  HX340LAD
5  HX220LAD   HCT780X  HX340LAD
6  HX220LAD   HCT780X  HX340LAD
7  HX220LAD  HX340LAD         -
8  HX220LAD   HCT780X         -
9  HX220LAD   HCT780X         -

In [224]: df["col_Z"] == "-"                                                    
Out[224]: 
0     True
1     True
2     True
3    False
4    False
5    False
6    False
7     True
8     True
9     True
Name: col_Z, dtype: bool

In [225]: (df["col_Z"] == "-") & (df["col_Y"] != "-")                           
Out[225]: 
0    False
1    False
2     True
3    False
4    False
5    False
6    False
7     True
8     True
9     True
dtype: bool

In [226]: mask = (df["col_Z"] == "-") & (df["col_Y"] != "-")                    

In [227]: mask                                                                  
Out[227]: 
0    False
1    False
2     True
3    False
4    False
5    False
6    False
7     True
8     True
9     True
dtype: bool

In [228]: df["col_Z"][mask] = df["col_Y"][mask]                                 

In [229]: df                                                                    
Out[229]: 
      col_X     col_Y     col_Z
0         -         -         -
1         -         -         -
2  HX220LAD  HX340LAD  HX340LAD
3  HX220LAD   HCT780X  HX340LAD
4  HX220LAD   HCT780X  HX340LAD
5  HX220LAD   HCT780X  HX340LAD
6  HX220LAD   HCT780X  HX340LAD
7  HX220LAD  HX340LAD  HX340LAD
8  HX220LAD   HCT780X   HCT780X
9  HX220LAD   HCT780X   HCT780X

In [230]: df["col_Y"][mask] = ""                                                

In [231]: df                                                                    
Out[231]: 
      col_X    col_Y     col_Z
0         -        -         -
1         -        -         -
2  HX220LAD           HX340LAD
3  HX220LAD  HCT780X  HX340LAD
4  HX220LAD  HCT780X  HX340LAD
5  HX220LAD  HCT780X  HX340LAD
6  HX220LAD  HCT780X  HX340LAD
7  HX220LAD           HX340LAD
8  HX220LAD            HCT780X
9  HX220LAD            HCT780X
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
andreas96
User
Beiträge: 11
Registriert: Montag 7. September 2020, 08:27

Danke für deinen Lösungsansatz blackjack!. Ich habe versucht ihn nachzuvollziehen. Es scheitert schon nach der ersten codezeile:

Code: Alles auswählen

df["col_Z"] == "-" # 224
statt 0 True, 1 True, 2 True, 3 False, 4 False, 5 False, 6 False ,7 True, 8 True, 9 True
wird 0 True, 1 True, 2 False, 3 False, 4 False, 5 False, 6 False, 7 False, 8 False, 9 False

bei der nächsten Eingabe nur noch False.
Mache ich etwas beim Import des Dataframes falsch? (Bestimmt, aber was)

PS das mit den Bildern tut mir leid. Ich versuche es nächstes Mal besser zu machen, auch kann ich anscheinend keine Datei an meinen Post anhängen.
Benutzeravatar
__blackjack__
User
Beiträge: 13926
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@andreas96: An den Stellen wo `False` steht und `True` stehen sollte steht dann halt kein "-" in der jeweiliegen ”Zelle”. Vielleicht können die noch führende oder folgende Leerzeichen enthalten? Oder es ist ein sehr ähnliches Zeichen (”echtes” Minus, ein echter Bindestrich, …).

Die Testdaten hatte ich als CSV-Datei aus den Bildern rekonstruiert:

Code: Alles auswählen

col_X;col_Y;col_Z
-;-;-
-;-;-
HX220LAD;HX340LAD;-
HX220LAD;HCT780X;HX340LAD
HX220LAD;HCT780X;HX340LAD
HX220LAD;HCT780X;HX340LAD
HX220LAD;HCT780X;HX340LAD
HX220LAD;HX340LAD;-
HX220LAD;HCT780X;-
HX220LAD;HCT780X;-
In die Zwischenablage kopiert und dann so in einen DataFrame gesteckt:

Code: Alles auswählen

In [237]: df = pd.read_clipboard(delimiter=";")                                 

In [238]: df                                                                    
Out[238]: 
      col_X     col_Y     col_Z
0         -         -         -
1         -         -         -
2  HX220LAD  HX340LAD         -
3  HX220LAD   HCT780X  HX340LAD
4  HX220LAD   HCT780X  HX340LAD
5  HX220LAD   HCT780X  HX340LAD
6  HX220LAD   HCT780X  HX340LAD
7  HX220LAD  HX340LAD         -
8  HX220LAD   HCT780X         -
9  HX220LAD   HCT780X         -
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
andreas96
User
Beiträge: 11
Registriert: Montag 7. September 2020, 08:27

Vielen Dank! Ich habe die falschen Einträge gefunden. Anfängerfehler. Es klappt prima!
Gruß Andreas
Antworten