TL; DR-Version:
Für den einfachen Fall von:
- Ich habe eine Textspalte mit einem Trennzeichen und möchte zwei Spalten
Die einfachste Lösung ist:
df['A'], df['B'] = df['AB'].str.split(' ', 1).str
Oder Sie können einen DataFrame mit einer Spalte für jeden Eintrag des Split automatisch erstellen mit:
df['AB'].str.split(' ', 1, expand=True)
Sie müssen verwenden, expand=True
wenn Ihre Zeichenfolgen eine ungleichmäßige Anzahl von Teilungen aufweisen und Sie None
die fehlenden Werte ersetzen möchten .
Beachten Sie, dass die .tolist()
Methode in beiden Fällen nicht erforderlich ist. Weder ist zip()
.
Im Detail:
Die Lösung von Andy Hayden ist hervorragend geeignet, um die Leistungsfähigkeit der str.extract()
Methode zu demonstrieren .
Für eine einfache Aufteilung über ein bekanntes Trennzeichen (z. B. Aufteilen durch Bindestriche oder Aufteilen durch Leerzeichen) reicht die .str.split()
Methode jedoch aus 1 . Es verarbeitet eine Spalte (Serie) von Zeichenfolgen und gibt eine Spalte (Serie) von Listen zurück:
>>> import pandas as pd
>>> df = pd.DataFrame({'AB': ['A1-B1', 'A2-B2']})
>>> df
AB
0 A1-B1
1 A2-B2
>>> df['AB_split'] = df['AB'].str.split('-')
>>> df
AB AB_split
0 A1-B1 [A1, B1]
1 A2-B2 [A2, B2]
1: Wenn Sie sich nicht sicher sind, was die ersten beiden Parameter .str.split()
tun, empfehle ich die Dokumente für die einfache Python-Version der Methode .
Aber wie geht es dir:
- eine Spalte mit Listen mit zwei Elementen
zu:
- zwei Spalten, die jeweils das jeweilige Element der Listen enthalten?
Nun, wir müssen uns das .str
Attribut einer Spalte genauer ansehen .
Es ist ein magisches Objekt, mit dem Methoden gesammelt werden, die jedes Element in einer Spalte als Zeichenfolge behandeln und dann die entsprechende Methode in jedem Element so effizient wie möglich anwenden:
>>> upper_lower_df = pd.DataFrame({"U": ["A", "B", "C"]})
>>> upper_lower_df
U
0 A
1 B
2 C
>>> upper_lower_df["L"] = upper_lower_df["U"].str.lower()
>>> upper_lower_df
U L
0 A a
1 B b
2 C c
Es hat aber auch eine "Indizierungs" -Schnittstelle, um jedes Element eines Strings anhand seines Index abzurufen:
>>> df['AB'].str[0]
0 A
1 A
Name: AB, dtype: object
>>> df['AB'].str[1]
0 1
1 2
Name: AB, dtype: object
Natürlich ist es dieser Indizierungsschnittstelle von .str
egal, ob jedes zu indizierende Element tatsächlich eine Zeichenfolge ist, solange es indiziert werden kann.
>>> df['AB'].str.split('-', 1).str[0]
0 A1
1 A2
Name: AB, dtype: object
>>> df['AB'].str.split('-', 1).str[1]
0 B1
1 B2
Name: AB, dtype: object
Dann ist es eine einfache Sache, das Python-Tupel zu nutzen, um iterables zu entpacken
>>> df['A'], df['B'] = df['AB'].str.split('-', 1).str
>>> df
AB AB_split A B
0 A1-B1 [A1, B1] A1 B1
1 A2-B2 [A2, B2] A2 B2
Natürlich ist es so nützlich, einen DataFrame aus dem Teilen einer Zeichenfolgenspalte herauszuholen, dass die .str.split()
Methode dies mit dem folgenden expand=True
Parameter für Sie tun kann:
>>> df['AB'].str.split('-', 1, expand=True)
0 1
0 A1 B1
1 A2 B2
Ein anderer Weg, um das zu erreichen, was wir wollten, ist:
>>> df = df[['AB']]
>>> df
AB
0 A1-B1
1 A2-B2
>>> df.join(df['AB'].str.split('-', 1, expand=True).rename(columns={0:'A', 1:'B'}))
AB A B
0 A1-B1 A1 B1
1 A2-B2 A2 B2
Die expand=True
Version ist zwar länger, hat aber einen deutlichen Vorteil gegenüber der Tupel-Entpackmethode. Das Auspacken von Tupeln eignet sich nicht für Splits unterschiedlicher Länge:
>>> df = pd.DataFrame({'AB': ['A1-B1', 'A2-B2', 'A3-B3-C3']})
>>> df
AB
0 A1-B1
1 A2-B2
2 A3-B3-C3
>>> df['A'], df['B'], df['C'] = df['AB'].str.split('-')
Traceback (most recent call last):
[...]
ValueError: Length of values does not match length of index
>>>
Aber expand=True
es geht gut, indem man None
in die Spalten setzt, für die es nicht genug "Splits" gibt:
>>> df.join(
... df['AB'].str.split('-', expand=True).rename(
... columns={0:'A', 1:'B', 2:'C'}
... )
... )
AB A B C
0 A1-B1 A1 B1 None
1 A2-B2 A2 B2 None
2 A3-B3-C3 A3 B3 C3
read_table()
oderread_fwf()