Spalte aus Pandas DataFrame in mehrere Spalten aufteilen anhand von Positionen aus Array

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
H3llo
User
Beiträge: 20
Registriert: Montag 9. Mai 2022, 10:17

Hallo,

ich habe ein DataFrame, in dem alle Daten in der ersten Spalte stehen. Diese Daten sollen in mehrere Spalten aufgeteilt werden. Dafür gibt es einen (Numpy) Array, in dem die "Positionen", an denen die Spalte aufgeteilt werden soll, stehen.

Beispiel:

Das DataFrame sieht so aus:
K1ABC123HH8
K1ERT777HH9
K1QWE666ZZ2

Der Array sieht so aus:
[1, 3, 6, 9, 11]

Das Ergebnis soll so aussehen:
Spalte 1 Spalte 2 Spalte 3 Spalte 4 Spalte 5
K1 ABC 123 HH 8
K1 ERT 777 HH 9
K1 QWE 666 ZZ 2

Gibt es dafür speziell eine Funktion oder wie sollte man das am effizientesten machen?
Benutzeravatar
__blackjack__
User
Beiträge: 14030
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@H3llo: Wie ist das denn passiert? Die Daten hätten gar nicht erst so im `DataFrame` landen sollen. Für „fixed width field“ Dateien hat Pandas eine eigene Funktion zum einlesen.

Ansonsten schau Dir das `str`-Attribut von `Series`-Objekten an, da gibt es eine `slice()`-Methode. Dazu dann noch die `pairwise()`-Funktion aus dem `more_itertools`-Modul, beziehungsweise das Rezept dafür aus der Dokumentation vom `itertools`-Modul.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
H3llo
User
Beiträge: 20
Registriert: Montag 9. Mai 2022, 10:17

Hallo blackjack,

Ich habe eigentlich ein größeres DataFrame, dessen Daten ich aus einer txt-Datei ausgelesen habe. In der txt-Datei sind verschiedene Typen von Zeilen, die sich durch Länge und Anzahl ihrer Spalten unterscheiden. Als vereinfachtes Beispiel mal Folgendes: Es gibt "P1"-Zeilen, die 3 Spalten haben, Spalte 1 10 Zeichen lang, Spalte 2 15 Zeichen lang und Spalte 3 ebenfalls 15 Zeichen lang, "K1"-Zeilen, die 6 Spalten haben, Spalte 1 2 Zeichen lang, Spalte 2 3 Zeichen lang, Spalte 3 3 Zeichen lang, Spalte 4 2 Zeichen lang, Spalte 5 1 Zeichen lang und Spalte 6 29 Zeichen lang und weitere Zeilentypen. Ich weiß nicht, wie man die Daten in so einem Fall direkt beim Import trennt. Daher habe ich sie erstmal in eine Spalte geschrieben. Die Angaben der Spaltenlängen sind in einer CSV-Datei gespeichert. Diese habe ich eingelesen und für jeden Zeilentyp einen Array mit den Spaltenlängen gemacht (wie dem Array aus meiner Fragestellung). Das ursprüngliche DataFrame habe ich aufgespalten in mehrere DataFrames, die alle nur jeweils einen Zeilentyp beinhalten (- ich habe also einen DataFrame für "P1"-Zeilen, eins für "K1"-Zeilen usw.). Ich bin aber auch offen für andere "Programmierstrategien". Ich muss nun alle DataFrames aufspalten. Meine Frage habe ich beispielhaft für das "K1"-DataFrame gestellt.

Dadurch dass jeder Zeilentyp eine unterschiedliche Anzahl von Zeichen für jede Spalte hat, ist hier, wenn ich die Definition richtig verstanden habe, kein fixed width field gegeben.

Sollte es erforderlich sein, kann ich auch ein Beispiel hochladen.
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

Ist das immer noch die Datei, die Du in viewtopic.php?p=409723#p409723 gepostet hast?
Und die Antwort ist immer noch die selbe. Diese Datei läßt sich nicht mit Pandas lesen, aber anscheinend versuchst Du das immer noch.
Aber statt hier einen Thread nach dem anderen mit komischen Pandas-Fragen zu stellen, könntest Du auch einfach mal versuchen, die Datei mit den üblichen Python-Mitteln zu parsen.
H3llo
User
Beiträge: 20
Registriert: Montag 9. Mai 2022, 10:17

Nein, das ist nicht mehr die gleiche Datei.

Aber zugegeben eine ähnliche.

Zu dieser Datei gibt es eine CSV Datei, die genau die Struktur der txt-Datei spezifiziert!

Ich sag auch nicht, dass man alles mit Pandas machen muss.

@blackjack: Ich verstehe nicht, wie man die slice Funktion und die pairwise Funktion kombinieren kann, um das Problem zu lösen. Kannst du ein Beispiel machen?
Benutzeravatar
__blackjack__
User
Beiträge: 14030
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@H3llo: Du musst ja aus der Liste mit den Indexwerten eine machen mit Start- und Endindex. Das liefert `pairwise()`. Und mit diesen Werten musst Du dann ”slicen”. Du musst halt Code schreiben der die beiden Funktionen verwendet. Da fehlt natürlich noch was was Du programmieren musst.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
H3llo
User
Beiträge: 20
Registriert: Montag 9. Mai 2022, 10:17

Ich habe es nun erstmal wie folgt gemacht:

Ich habe mir eine Liste erstellt

Code: Alles auswählen

glassdata_group_edited = []
Die Positionen, an denen geschnitten werden muss, habe ich in

Code: Alles auswählen

specificationdata_group
Ich gehe nun alle Einträge in specificationdata_group durch und füge den geschnittenen String an letzter Stelle der Liste hinzu:

Code: Alles auswählen

    for i in range(0, len(specificationdata_group.index) - 1):
        glassdata_group_edited.append(glassdata_group.str.slice(int(specificationdata_group[i]) - 1, int(specificationdata_group[i + 1]) - 1))
So habe ich alle Daten voneinander getrennt.

Ich habe es auch mit deinem Vorschlag, neben der Slice-Funktion auch die pairwise-Funktion zu nehmen, probiert. Ich habe auch eine Liste mit den Tupels mit Start- und Endposition erzeugen können, wusste dann aber nicht, wie ich damit die Slice-Funktion "füttern" soll. Falls das nochmal eine Vereinfachung zum obigen Code sein sollte, gerne ein kurzes Beispiel dazu geben. Ansonsten bin ich auch für weitere Verbesserungsvorschläge an dem obigen Code offen. Ansonsten werde ich es erstmal so lassen und bedanke mich herzlich für die tolle Hilfe, blackjack.
Benutzeravatar
__blackjack__
User
Beiträge: 14030
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Code: Alles auswählen

    glassdata_group_edited = []
    for start, end in pairwise(specificationdata_group):
        glassdata_group_edited.append(glassdata_group.str.slice(start - 1, end - 1))
Oder als „list comprehension“:

Code: Alles auswählen

    glassdata_group_edited = [
        glassdata_group.str.slice(start - 1, end - 1)
        for start, end in pairwise(specificationdata_group)
    ]
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Antworten