Ich habe eine, pandas dataframe
in der eine Spalte von Textzeichenfolgen durch Kommas getrennte Werte enthält. Ich möchte jedes CSV-Feld aufteilen und eine neue Zeile pro Eintrag erstellen (vorausgesetzt, die CSV ist sauber und muss nur auf ',' aufgeteilt werden). Zum Beispiel a
sollte werden b
:
In [7]: a
Out[7]:
var1 var2
0 a,b,c 1
1 d,e,f 2
In [8]: b
Out[8]:
var1 var2
0 a 1
1 b 1
2 c 1
3 d 2
4 e 2
5 f 2
Bisher habe ich verschiedene einfache Funktionen ausprobiert, aber die .apply
Methode scheint nur eine Zeile als Rückgabewert zu akzeptieren, wenn sie auf einer Achse verwendet wird, und ich kann nicht .transform
arbeiten. Anregungen wäre sehr dankbar!
Beispieldaten:
from pandas import DataFrame
import numpy as np
a = DataFrame([{'var1': 'a,b,c', 'var2': 1},
{'var1': 'd,e,f', 'var2': 2}])
b = DataFrame([{'var1': 'a', 'var2': 1},
{'var1': 'b', 'var2': 1},
{'var1': 'c', 'var2': 1},
{'var1': 'd', 'var2': 2},
{'var1': 'e', 'var2': 2},
{'var1': 'f', 'var2': 2}])
Ich weiß, dass dies nicht funktioniert, weil wir DataFrame-Metadaten verlieren, indem wir numpy durchlaufen, aber es sollte Ihnen einen Eindruck davon geben, was ich versucht habe:
def fun(row):
letters = row['var1']
letters = letters.split(',')
out = np.array([row] * len(letters))
out['var1'] = letters
a['idx'] = range(a.shape[0])
z = a.groupby('idx')
z.transform(fun)
Antworten:
Wie wäre es mit so etwas:
Dann müssen Sie nur noch die Spalten umbenennen
quelle
UPDATE2: Allgemeinere vektorisierte Funktion, die für mehrere
normal
und mehrerelist
Spalten funktioniertDemo:
Mehrere
list
Spalten - Allelist
Spalten müssen dieselbe Anzahl von Elementen in jeder Zeile haben:Beibehaltung der ursprünglichen Indexwerte:
Konfiguration:
CSV-Spalte:
Mit diesem kleinen Trick können wir CSV-ähnliche Spalten in
list
Spalten konvertieren :UPDATE: generischer vektorisierter Ansatz (funktioniert auch für mehrere Spalten):
Original DF:
Lösung:
Lassen Sie uns zuerst CSV-Zeichenfolgen in Listen konvertieren:
Jetzt können wir das tun:
ALTE Antwort:
Inspiriert von der @ AFsteinstein-Lösung wollte ich sie etwas verallgemeinern, was auf DF mit mehr als zwei Spalten angewendet werden kann und so schnell, fast so schnell wie die AFinkelstein-Lösung):
quelle
.explode()
Methode in die API installiert (siehe auch diese Antwort ).Nach schmerzhaften Experimenten, um etwas schneller als die akzeptierte Antwort zu finden, brachte ich dies zum Laufen. Es lief ungefähr 100x schneller auf dem Datensatz, den ich anprobiert habe.
Wenn jemand einen Weg kennt, dies eleganter zu gestalten, ändern Sie auf jeden Fall meinen Code. Ich konnte keinen Weg finden, der funktioniert, ohne die anderen Spalten, die Sie als Index behalten möchten, festzulegen und dann den Index zurückzusetzen und die Spalten umzubenennen, aber ich würde mir vorstellen, dass noch etwas anderes funktioniert.
quelle
TypeError: object of type 'float' has no len()
DataFrame(df.var1.str.split(',').tolist())
NaN
in dieser Spalte, so ist der Ersatzb = DataFrame(a.var1.str.split(',').values.tolist(), index=a.var2).stack()
Hier ist eine Funktion, die ich für diese allgemeine Aufgabe geschrieben habe. Es ist effizienter als die
Series
/stack
Methoden. Spaltenreihenfolge und Namen bleiben erhalten.Mit dieser Funktion ist die ursprüngliche Frage so einfach wie:
quelle
Pandas> = 0,25
Serien- und DataFrame-Methoden definieren eine
.explode()
Methode, die Listen in separate Zeilen auflöst . Weitere Informationen finden Sie im Abschnitt "Dokumente" zum Auflösen einer listenähnlichen Spalte .Da Sie eine Liste von durch Kommas getrennten Zeichenfolgen haben, teilen Sie die Zeichenfolge durch Komma auf, um eine Liste der Elemente zu erhalten, und rufen Sie dann
explode
diese Spalte auf.Beachten Sie, dass dies
explode
(vorerst) nur für eine einzelne Spalte funktioniert .NaNs und leere Listen erhalten die Behandlung, die sie verdienen, ohne dass Sie durch Reifen springen müssen, um es richtig zu machen.
Dies ist ein schwerwiegender Vorteil gegenüber
ravel
+repeat
-basierten Lösungen (die leere Listen vollständig ignorieren und NaNs ersticken).quelle
Ähnliche Frage wie: pandas: Wie teile ich Text in einer Spalte in mehrere Zeilen auf?
Du könntest es tun:
quelle
s.name = 'var1'
TL; DR
Demonstration
Erstellen wir einen neuen Datenrahmen
d
mit ListenAllgemeine Kommentare
Ich werde
np.arange
mit verwendenrepeat
, um Dataframe-Indexpositionen zu erstellen, mit denen ich arbeiten kanniloc
.FAQ
Warum benutze ich nicht
loc
?Weil der Index möglicherweise nicht eindeutig ist und verwendet wird
loc
wird jede Zeile zurückgegeben, die einem abgefragten Index entspricht.Warum benutzt du nicht das
values
Attribut und schneidest das?Wenn sich
values
der gesamte Datenrahmen beim Aufruf in einem zusammenhängenden "Block" befindet, gibt Pandas eine Ansicht des Arrays zurück, das der "Block" ist. Andernfalls müssen Pandas ein neues Array zusammenschustern. Beim Kopfsteinpflaster muss dieses Array einen einheitlichen Typ haben. Oft bedeutet dies, ein Array mit dem Typ dtype zurückzugebenobject
. Indem ichiloc
dasvalues
Attribut verwende, anstatt es zu zerschneiden , lasse ich mich davon abhalten, damit umgehen zu müssen.Warum benutzt du
assign
?Wenn ich benutze
assign
denselben Spaltennamen verwende, den ich explodiere, überschreibe ich die vorhandene Spalte und behalte ihre Position im Datenrahmen bei.Warum wiederholen sich die Indexwerte?
Aufgrund der Verwendung
iloc
an wiederholten Positionen zeigt der resultierende Index das gleiche wiederholte Muster. Eine Wiederholung für jedes Element der Liste oder Zeichenfolge.Dies kann mit zurückgesetzt werden
reset_index(drop=True)
Für Streicher
Ich möchte die Saiten nicht vorzeitig teilen müssen. Stattdessen zähle ich die Vorkommen des
sep
Arguments unter der Annahme, dass bei einer Aufteilung die Länge der resultierenden Liste um eins größer wäre als die Anzahl der Trennzeichen.Ich benutze das dann
sep
fürjoin
die Saitensplit
.Für Listen
Ähnlich wie bei Zeichenfolgen, außer dass ich keine Vorkommen von zählen muss
sep
da diese bereits aufgeteilt sind.Ich benutze Numpy's,
concatenate
um die Listen zusammen zu jammen.quelle
Es besteht die Möglichkeit, den Datenrahmen zu teilen und zu explodieren, ohne die Struktur des Datenrahmens zu ändern
Eingang:
Aus:
Edit-1
Indizierung basierend auf der Referenzspalte und Ausrichten der Spaltenwertinformationen mit dem Stapel
Aus:
quelle
Ich habe eine Lösung für Datenrahmen mit einer beliebigen Anzahl von Spalten gefunden (wobei immer nur die Einträge einer Spalte gleichzeitig getrennt werden).
quelle
Hier ist eine ziemlich einfache Nachricht, die die
split
Methode von Pandas verwendetstr
accessor verwendet und dann NumPy verwendet, um jede Zeile in ein einzelnes Array zu reduzieren.Die entsprechenden Werte werden abgerufen, indem die nicht geteilte Spalte die richtige Anzahl mit wiederholt wird
np.repeat
.quelle
Ich hatte Probleme mit Speicherproblemen, bei denen meine Listen auf verschiedene Weise aufgelöst wurden. Daher habe ich einige Benchmarks vorbereitet, um zu entscheiden, welche Antworten positiv bewertet werden sollen. Ich habe fünf Szenarien mit unterschiedlichen Anteilen der Listenlänge an der Anzahl der Listen getestet. Teilen Sie die Ergebnisse unten:
Zeit: (weniger ist besser, klicken, um eine große Version anzuzeigen)
Maximale Speichernutzung: (weniger ist besser)
Schlussfolgerungen :
Ausführliche Informationen (Funktionen und Benchmarking-Code) finden Sie in dieser GitHub-Übersicht . Bitte beachten Sie, dass das Benchmark-Problem vereinfacht wurde und keine Aufteilung von Zeichenfolgen in die Liste beinhaltete - die meisten Lösungen wurden auf ähnliche Weise durchgeführt.
quelle
Basierend auf der exzellenten @ DMulligan- Lösung gibt es hier eine generische vektorisierte Funktion (keine Schleifen), die eine Spalte eines Datenrahmens in mehrere Zeilen aufteilt und sie wieder mit dem ursprünglichen Datenrahmen zusammenführt. Es verwendet auch eine großartige generische
change_column_order
Funktion aus dieser Antwort .Beispiel:
Beachten Sie, dass der ursprüngliche Index und die Reihenfolge der Spalten beibehalten werden. Es funktioniert auch mit Datenrahmen, die keinen nicht sequentiellen Index haben.
quelle
Die Aufteilung der Zeichenfolgenfunktion kann ein boolesches Optionsargument 'expand' annehmen.
Hier ist eine Lösung mit diesem Argument:
quelle
Ich habe gerade Jilns ausgezeichnete Antwort von oben verwendet, musste aber erweitert werden, um mehrere Spalten zu teilen. Ich dachte, ich würde teilen.
quelle
Die Antwort von MaxU wurde mit MultiIndex-Unterstützung aktualisiert
quelle
Einzeiler mit
split(___, expand=True)
undlevel
undname
Argumentereset_index()
:Wenn Sie
b
genau wie in der Frage aussehen müssen , können Sie zusätzlich Folgendes tun:quelle
Ich habe die folgende Lösung für dieses Problem gefunden:
quelle
Eine andere Lösung, die Python-Kopierpaket verwendet
quelle
Hier gibt es viele Antworten, aber ich bin überrascht, dass niemand die eingebaute Pandas-Explosionsfunktion erwähnt hat. Überprüfen Sie den Link unten: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.explode.html#pandas.DataFrame.explode
Aus irgendeinem Grund konnte ich nicht auf diese Funktion zugreifen, daher habe ich den folgenden Code verwendet:
Oben ist ein Beispiel meiner Daten. Wie Sie sehen können, hatte die Personenspalte eine Reihe von Personen, und ich habe versucht, sie zu explodieren. Der von mir angegebene Code funktioniert für Listentypdaten. Versuchen Sie also, Ihre durch Kommas getrennten Textdaten in das Listenformat zu bringen. Da mein Code integrierte Funktionen verwendet, ist er viel schneller als benutzerdefinierte / angewendete Funktionen.
Hinweis: Möglicherweise müssen Sie pandas_explode mit pip installieren.
quelle
Ich hatte ein ähnliches Problem. Meine Lösung bestand darin, den Datenrahmen zuerst in eine Liste von Wörterbüchern zu konvertieren und dann den Übergang durchzuführen. Hier ist die Funktion:
Beispiel:
Sie können die Funktion auch ein wenig ändern, um das Trennen von Zeilen vom Listentyp zu unterstützen.
quelle