Dataframe, Zeilen prüfen und zuordnen

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
lambkin
User
Beiträge: 17
Registriert: Dienstag 22. Mai 2018, 08:29

HI,

ich habe eine Dataframe, in dem ich eine Spalte zeilenweise durchgehen möchte. Dabei soll aber jeweils nur die 5+6 Stelle des Eintrags betrachtet werden, wenn die Länge 10 ist.
Anschließend soll der Eintrag der 5+6 Stelle einer Kategorie zugeordnet werden, also zb '10' ist Kategorie 1, '11' ist Kategorie 2 usw...
Leider klappt das bei mir noch nicht wirklich und ich weiß nicht weiter und hoffe auf eure Denkanstöße :-)
Was ich mir soweit überlegt habe:

1. Teil: Ich habe geschaut, um welchen Datentyp es sich in der Spalte handelt, es ist ein Series Object. Daher wollte ich dies erstmal in einen String casten. Und anschließen zeilenweise durchgehen,
auf die Länge des Eintrags prüfen und wenn diese 10 ist, die 5+6 Stelle betrachten.

Code: Alles auswählen

df_View['Tabelle'] = df_View['Tabelle'].astype(str)
for s in df_View['Tabelle']:
    if df_View['Tabelle'].len() == 10:
        print (s[4:6])
Bei dem Code bin ich mir nicht wirklich sicher, ob das so klappt. Besonders mit dem print, wird so der Wert von den beiden Positionen in die Zeile geschrieben? Leider klappt auch das mit dem casten nicht. Ich bekomme nämlich folgende Fehlermeldung:
AttributeError: 'Series' object has no attribute 'len'

2. Teil: Nun soll die entsprechende Kategorie zugeordnet werden. Meine Überlegung war, eine Methode zu definieren.

Code: Alles auswählen

def Kat_zuordnen(kat):
    if kat == '10':
        return 1
    elif kat == '11':
        return 2
    .....
    else:
        return 0
df_View['Tabelle_zugeordnet'] = df_View['Tabelle'].apply(Kat_zuordnen)
del df_View['Tabelle']
Das Problem ist hierbei natürlich, dass es ein großer Aufwand wäre, 99 Kategorien so festzulegen. Hier gibt es doch sicher eine schönere Lösung?
Ich habe die Kategorien auch als .csv hinterlegt. Habt ihr hier eine Idee, wie ich das ganze schöner machen kann?

Danke und liebe Grüße
lambkin
lambkin
User
Beiträge: 17
Registriert: Dienstag 22. Mai 2018, 08:29

Hat niemand ein Tipp für mich? :/
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

kannst du vielleicht mal ein vereinfachtes Beispiel einer Ausgangstabelle und des gewünschten Ergebnisses posten. Zumindest mir ist nicht ganz klar, was du vor hast.

Bzgl. der Kategorien: statt einer if-elif Kasakade solltest du die Zuordnung als Dict speichern und darauf zugreifen:

Code: Alles auswählen

kategorien = {10: 1, 11: 2, 12: 3}
def kategorie_zuordnen(kat):
    return kategorien.get(kat, 0)
Gruß, noisefloor
lambkin
User
Beiträge: 17
Registriert: Dienstag 22. Mai 2018, 08:29

Hallo,

ja, ich versuche es an einem Beispiel aufzuzeigen:

Ich habe ein Dataframe, der sieht so aus

Index | ID | Erstellt | Kennzahl
0 | 1490 | 01.01.2012 | K294837531
1 | 9284 | 01.04.2012 | K920583921
2 | 2910 | 15.04.2012 | K821839202
...........

Nun möchte ich die Spalte "Kennzahl" meines Dataframes zeilenweise durchgehen und prüfen, ob die enthaltene Kennzahl 10 Stellen hat und wenn ja, dann soll nur die 4+5 Stelle gespeichert werden.
Also quasi:
Index | ID | Erstellt | Kennzahl
0 | 1490 | 01.01.2012 | 48
1 | 9284 | 01.04.2012 | 05
2 | 2910 | 15.04.2012 | 18
...........

Ich habe mir für den Dataframe den Datentyp ausgeben lassen:
ID object
Erstellt datetime64[ns]
Kennzahl object
dtype: object

Ich habe es eben folgendermaßen probiert, aber das klappt nicht:

Code: Alles auswählen

df_View['Kennzahl'] = df_View['Kennzahl'].astype(str)
for s in df_View['Kennzahl']:
    if df_View['Kennzahl'].len() == 10:
        print (s[4:6])
Da bekomme ich aber die Fehlermeldung: AttributeError: 'Series' object has no attribute 'len'

Danke, das mit dem Dict. ist eine gute Idee! Werde ich versuchen :-)
Liebe Grüße
Lambkin
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

das geht z.B. so:

Code: Alles auswählen

>>> import pandas as pd
>>> df = pd.DataFrame([[1234, 'KX12345678'],[5678, 'KY98765432'], [9012, 'KZ12345']], columns=['id', 'Kennzahl'])
>>> df
     id    Kennzahl
0  1234  KX12345678
1  5678  KY98765432
2  9012     KZ12345
>>> for row, kennzahl in enumerate(df['Kennzahl']):
...     if len(kennzahl)==10:
...         df.set_value(row, 'Kennzahl', kennzahl[4:6])
... 
     id    Kennzahl
0  1234          34
1  5678  KY98765432
2  9012     KZ12345
     id Kennzahl
0  1234       34
1  5678       76
2  9012  KZ12345
>>> df
     id Kennzahl
0  1234       34
1  5678       76
2  9012  KZ12345
>>>
Wichtig: du änderst den DataFrame direkt, es wird keine Kopie angelegt.

Gruß, noisefloor
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@noisefloor: pandas hat wie numpy den Vorteil, dass man keine Schleifen braucht, sondern Vektoroperationen anwenden kann:

Code: Alles auswählen

mask = df['Kennzahl'].str.len() == 10
df['Kennzahl'][mask] = df['Kennzahl'][mask].str[4:6]
lambkin
User
Beiträge: 17
Registriert: Dienstag 22. Mai 2018, 08:29

Hab es jetzt mit eurer Hilfe hinbekommen so wie ich es brauche:

Code: Alles auswählen

df = df.drop(df[df.Kennzahl.str.len() > 10].index) 
mask = df['Kennzahl'].str.len() == 10
df['Kennzahl'][mask] = df['Kennzahl'][mask].str[4:6]
df['Kennzahl']= df['Kennzahl'].astype(int)
Vielen Dank!
Antworten