Seite 1 von 1

Python Pandas Umlaute in CSV schreiben

Verfasst: Montag 31. Januar 2022, 10:10
von Stempelente
Moin Leute,

ich bin ein totaler Änfänger was Programmieren angeht.

Leider habe ich im Forum keine Lösung zu meiner Frage gefunden.

EInfach erklärt, ich bekomm eine CSV Datei die UTF-8 codiert ist möchte da ein paar Spalten löschen, eine Spalte und header hinzufügen, und sortieren. Das klappt auch alles wie gewünscht. Danach sollen Werte durch Eingabe vom User ersetzt werden (zB Wert in Ursprungs-CSV: "blau" -> User gibt ein "Pflege" -> aus allen Werten "blau" wird -> "Pflege"

Leider gibt es Berufsbezeichnungen wie "Ärzte" und wenn diese in die CSV geschrieben werden kommt nur "Ärzte" raus.

Code: Alles auswählen

import pandas as pd

df = pd.read_csv("table1.csv",
                  sep=",",
                  names=["1", "MAC", "3", "4", "5","6","7","Berufsgruppe","9","10","11","12","Stationsname"])


for i in range(1,14):
    if (i == 2) or (i == 8) or (i == 13):
        pass
    else:
        i = str(i)
        df.drop(i, axis=1)
        del df[i]

df.insert(loc=1, column="QRCode", value = "")
#df.sort()
BG = input("Anzahl Berufsgruppen: ")
int(BG)
Farbe = [BG]
Job = [BG]
i = 0

for u in range (1,int(BG)+1):

    Farbe[i] = input("Farbe für " + str(u) + ". Berufsgruppe: ")
    Job[i] = input("Name für " + str(u) + ". Berufsgruppe: ")
    df = df.replace([Farbe[i]],[Job[i]])
    i+1

df.to_csv("fertig.csv", index=False)
#print(df)
Gibt es eine Möglichkeit Umlaute hier richtig darzustellen?

Re: Python Pandas Umlaute in CSV schreiben

Verfasst: Montag 31. Januar 2022, 11:57
von sparrow
read_csv kennt - wie das open in python - einen Parameter "encoding"

Zum Code: Namen schreibt man in Python klein_mit_unterstrich.
Zeichenketten baut man nicht mit + zusammen sondern verwendet f-strings

Code: Alles auswählen

farbe[i] = input(f"Farbe für {u}. Berufsgruppe: ")

Re: Python Pandas Umlaute in CSV schreiben

Verfasst: Montag 31. Januar 2022, 13:11
von Sirius3
Statt nachträglich Spalten rauszulöschen, lädt man sie erst gar nicht erst.
Variablennamen schreibt man komplett klein und benutzt keine kryptischen Abkürzungen: anzahl_berufsgruppen.
Der einsame int-Aufruf sollte einer Variable zugewiesen werden, und nicht später nochmal die selbe Umwandlung gemacht werden.
Die Variable `i` hat immer den Wert 0, so dass die Daten immer wieder überschrieben werden, was ein Glück ist, weil alle Indizes außer 0 nicht existieren. Die Listen werden auch gar nicht richtig verwendet, und dazu auch noch falsch.

Code: Alles auswählen

import pandas as pd

df = pd.read_csv("table1.csv", sep=",", usecols=[1,7,12], names=["MAC", "Berufsgruppe", "Stationsname"], encoding="UTF8")
df.insert(loc=1, column="QRCode", value="")
anzahl_berufsgruppen = int(input("Anzahl Berufsgruppen: "))

for u in range(1, anzahl_berufsgruppen + 1):
    farbe = input(f"Farbe für {u}. Berufsgruppe: ")
    job = input(f"Name für {u}. Berufsgruppe: ")
    df = df.replace(farbe, job)

df.to_csv("fertig.csv", index=False)
Was hat die Farbe mit der u. Berufsgruppe zu tun? Sind die Farben jeweils nur einmal in der Tabelle enthalten? Dann sollte man die Farben ausgeben und nicht abfragen. Wenn sie mehrmals vorkommen, dann ist die Nummer irgendwie verwirrend.

Re: Python Pandas Umlaute in CSV schreiben

Verfasst: Montag 31. Januar 2022, 13:38
von __blackjack__
@Stempelente: Ergibt sich die Anzahl der Berufsgruppen, also zumindest der Eingaben die der Benutzer maximal machen muss, nicht durch die Anzahl der eindeutig verschiedenen Werte in der Spalte "Berufsgruppe"? Und dann muss man den Benutzer doch auch die Farbe gar nicht eingeben lassen, wenn man die aus dem DataFrame auslesen kann.

Und soll die Farbe dann tatsächlich im gesamten Dataframe, also über alle Spalten ersetzt werden, oder nur in der Spalte "Berufsgruppe"? Es wäre dann auch deutlich effizienter die Ersetzung der Werte in *einem* Durchgang zu machen und nicht für jede Farbe einen neuen Dataframe mit *einer* Farbe/Name-Ersetzung anzulegen. Schau Dir mal an was `replace()` so an Argumenten bekommen kann. Sowohl auf `DataFrame`- als auch auf `Series`-Objekten.

Re: Python Pandas Umlaute in CSV schreiben

Verfasst: Dienstag 1. Februar 2022, 17:29
von Stempelente
Hey Leute,

danke für eure Kritik. Ist mein erstes kleines Python-Programm und ja es ist keine Ausrede für die schlampige Programmierung. Aber, ich will dazulernen deshalb ein dickes Danke für eure Ratschläge.

Die Verschlankung werde ich auch direkt umsetzen sobald das Programm läuft wie es soll. :)

Leider gibt er mir immer noch ,Ärzte in der csv aus auch wenn ich encoding = 'UTF8' im csv_reader nutze.

Ich denke, dass das encoding doch eher in den df.to_csv müsste, oder? Aber da sagt er mir, dass er es nicht kennt...TypeError: NDFrame.to_csv() got an unexpected keyword argument 'endcoding'.
Kann mir da jedem erklären wie ich es hinbekomme, dass z.B. "Ärzte" auch in die CSV geschrieben wird und nicht ",Ärzte"

@__blackjack__ Nein, leider ergibt sich das nicht aus der Spalte. Alle Farben im DataFrame sollen ersetzt werden.

Code: Alles auswählen

import pandas as pd

df = pd.read_csv("table1.csv",
                 sep=",",
                 usecols=[1,7,12],
                 names=["MAC","Berufsgruppe","Stationsname"], 
                 encoding="UTF8")

df.insert(loc=1, column="QRCode", value="")

BG = input("Anzahl Berufsgruppen: ")
int(BG)

for u in range (1,int(BG)+1):

    Farbe = input(f"Farbe für {u}. Berufsgruppe: ")
    Job = input(f"Name für {u}. Berufsgruppe: ")

df.to_csv("fertig.csv", index=False)

#print(df)
EDIT: Code eingefügt

Re: Python Pandas Umlaute in CSV schreiben

Verfasst: Dienstag 1. Februar 2022, 18:12
von __blackjack__
@Stempelente: Das heisst ja auch nicht `endcoding`. Da ist ja nix zu ende. 😉

Was heisst denn „Leider gibt er mir immer noch Ärzte in der csv aus“? Wo genau siehst Du das denn? Was erwartet das dort für eine Kodierung, was immer das auch ist? Auch beim laden irgendwo musst Du auch wieder UTF-8 als Kodierung angeben.

Und wenn das beim Laden in den DataFrame mit UTF-8 funktioniert und da „Ärzte” als Text drin vor kommt, dann ist das auch ziemlich sicher UTF-8 kodiert. Was natürlich auch noch sein kann, das die Eingangsdatei UTF-8 kodiert ist, und dort *tatsächlich* „Ärzte“ drin steht, weil irgend wo vorher schon eine kaputte Mehrfachkodierung passiert ist.

Re: Python Pandas Umlaute in CSV schreiben

Verfasst: Samstag 5. Februar 2022, 09:10
von Stempelente
So es funktioniert jetzt, und falls über google jmd auf diesen Theard stßen sollte hier der Code:

Code: Alles auswählen

import numpy as np
import pandas as pd

Pfad=input("Bitte den Pfad, mit Dateinamen angeben: ")
df = pd.read_csv(Pfad,
                 sep=",",
                 usecols=[1,7,12],
                 names=["MAC","Berufsgruppe","Stationsname"],
                 encoding="utf-8-sig")

df.insert(loc=1, column="QRCode", value="")

Jobgruppen = df["Berufsgruppe"].unique()


print(f"Es wurden {df['Berufsgruppe'].nunique()} Farben erkannt, ({df['Berufsgruppe'].unique()}) \nKorrekt?\n j=Jo, n=Nö\n")
Auswahl = input()

if (Auswahl == "j"):
    BG = df['Berufsgruppe'].nunique()
    type(df["Berufsgruppe"].unique())

    for u in range(1, int(BG) + 1):

        Farbe = Jobgruppen[u-1]
        Job = input(f"Zur Farbe: {Jobgruppen[u-1]}, soll welche Berufsgruppe zugewiesen werden: ")
        df = df.replace([Farbe], [Job])

elif (Auswahl == "n"):
    BG = input("Anzahl Berufsgruppen: ")
    int(BG)

    for u in range(1, int(BG) + 1):

        Farbe = input(f"Farbe für {u}. Berufsgruppe: ")
        if Farbe == "grün":
            Farbe = "grün"
        Job = input(f"Name für {u}. Berufsgruppe: ")
        df = df.replace([Farbe], [Job])

else:
    print("Keine richtige Auswahl getroffen")
    input("Beliebige Tase zum Schließen des Programms drücken")
    quit()

NeuerPfad = Pfad [:-4]
# print(NeuerPfad+"fertig.csv")

df.to_csv(NeuerPfad+"fertig.csv", index=False, encoding="utf-8-sig")

# print(df)

Re: Python Pandas Umlaute in CSV schreiben

Verfasst: Samstag 5. Februar 2022, 14:08
von __blackjack__
@Stempelente: Numpy wird importiert aber gar nicht verwendet.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

Für Operationen auf Pfadnamen gibt es das `pathlib`-Modul, da sollte man keine Zeichenkettenoperationen verwenden.

Auf ``df["Berufsgruppen"]`` wird zu oft zugegriffen statt schon ermittelte und an Namen gebundene Werte einfach zu verwenden.

Sowohl ``type(df["Berufsgruppe"].unique())`` als auch ``int(BG)`` machen so ohne alles als Anweisungen keinen Sinn, weil die keinerlei Wirkung haben, ausser ein bisschen Rechenzeit zu verbrauchen.

`u` ist ein ungewöhnlicher Name für einen Laufindex. Was soll der denn bedeuten? Zudem ist es unypthonisch damit dann auf die Elemente einer Sequenz zuzugreifen. Man kann direkt über die Elemente iterieren, ohne den Umweg über einen Index. Fall man *zusätzlich* eine laufende ganze Zahl benötigt, gibt es die `enumerate()`-Funktion. Da kann man dann auch bei anderen Werten als 0 anfangen, und muss für Indexzugriffe nicht auch nicht Anpassungen vornehmen.

Dem Code nach ist die Kodierung der Datei also tatsächlich kaputt. Wo auch immer die Datei her kommt, das sollte man dort vielleicht mal lösen statt hier absichtlich "grün" durch "grün" zu ersetzen. Das ist pervers!

Und wenn man das hier absichtlich falsch macht, dann sollte man das auch *richtig* falsch machen, und nicht nur einen Wert ersetzen, sondern konsequent alles gleichartig falsch kodieren.

`quit()` gibt es eigentlich gar nicht. Das ist für die interaktive Python-Shell.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
from pathlib import Path

import pandas as pd


def pervers_falsch_kodieren(text):
    return text.encode("utf-8").decode("iso-8859-1")


def main():
    pfad = Path(input("Bitte den Pfad, mit Dateinamen angeben: "))
    df = pd.read_csv(
        pfad,
        sep=",",
        usecols=[1, 7, 12],
        names=["MAC", "Berufsgruppe", "Stationsname"],
        encoding="utf-8-sig",
    )

    df.insert(loc=1, column="QRCode", value="")

    jobgruppen = df["Berufsgruppe"].unique()

    auswahl = input(
        f"Es wurden {len(jobgruppen)} Farben erkannt, ({jobgruppen})\n"
        f"Korrekt?\n"
        f" j=Jo, n=Nö\n"
    )
    if auswahl == "j":
        for farbe in jobgruppen:
            job = input(
                f"Zur Farbe: {farbe}, soll welche Berufsgruppe zugewiesen werden: "
            )
            df = df.replace([farbe], [pervers_falsch_kodieren(job)])

    elif auswahl == "n":
        for i in range(1, len(jobgruppen) + 1):
            farbe = input(f"Farbe für {i}. Berufsgruppe: ")
            job = input(f"Name für {i}. Berufsgruppe: ")
            df = df.replace(
                [pervers_falsch_kodieren(farbe)],
                [pervers_falsch_kodieren(job)],
            )

    else:
        print("Keine richtige Auswahl getroffen")
        return

    df.to_csv(
        pfad.with_name(pfad.stem + "fertig.csv"),
        index=False,
        encoding="utf-8-sig",
    )


if __name__ == "__main__":
    main()