Holen Sie sich die letzte "Spalte" nach der Operation .str.split () für die Spalte in pandas DataFrame

75

Ich habe eine Spalte in einem Pandas-DataFrame, die ich auf ein einzelnes Leerzeichen aufteilen möchte. Die Aufteilung ist einfach genug DataFrame.str.split(' '), aber ich kann aus dem letzten Eintrag keine neue Spalte erstellen. Wenn ich .str.split()die Spalte erhalte, erhalte ich eine Liste von Arrays und weiß nicht, wie ich diese bearbeiten soll, um eine neue Spalte für meinen DataFrame zu erhalten.

Hier ist ein Beispiel. Jeder Eintrag in der Spalte enthält 'Symboldatenpreis' und ich möchte den Preis aufteilen (und schließlich das "p" ... oder "c" in der Hälfte der Fälle entfernen).

import pandas as pd
temp = pd.DataFrame({'ticker' : ['spx 5/25/2001 p500', 'spx 5/25/2001 p600', 'spx 5/25/2001 p700']})
temp2 = temp.ticker.str.split(' ')

was ergibt

0    ['spx', '5/25/2001', 'p500']
1    ['spx', '5/25/2001', 'p600']
2    ['spx', '5/25/2001', 'p700']

Gibt aber temp2[0]nur das Array eines Listeneintrags an und temp2[:][-1]schlägt fehl. Wie kann ich den letzten Eintrag in jedem Array in eine neue Spalte konvertieren? Vielen Dank!

Richard Herron
quelle

Antworten:

145

Mach das:

In [43]: temp2.str[-1]
Out[43]: 
0    p500
1    p600
2    p700
Name: ticker

Alles in allem wäre es also:

>>> temp = pd.DataFrame({'ticker' : ['spx 5/25/2001 p500', 'spx 5/25/2001 p600', 'spx 5/25/2001 p700']})
>>> temp['ticker'].str.split(' ').str[-1]
0    p500
1    p600
2    p700
Name: ticker, dtype: object
Wes McKinney
quelle
6
Ich liebe die saubere Lösung!
Ericmjl
12
vom Autor von "Pandas" :)
kmonsoor
4
Ich liebe diese Lösung, aber wie funktioniert sie? Was passiert also "hinter den Kulissen", bei dem strgefolgt von Klammern ein bestimmtes Element aus der Liste ausgewählt werden kann?
Kevin Markham
2
Ich war etwas verwirrt, der Einzeiler ist d1.ticker.str.split (). Str [-1]. Nicht das, was Sie erwarten würden ...
Citynorman
5
@ KevinMarkham: So funktioniert es: strfunktioniert nicht nur für Strings, sondern in gewissem Umfang auch für Listen. Also , wenn Sie eine Zeichenfolge haben Series foodann foo.str[0]würde das erste Zeichen jeder Saite, und foo.str[-1]würde die letzte nehmen. Da dies aber strauch (teilweise) auch auf Listen funktioniert, temp2.str[-1]wird das letzte Element jeder Liste in der Serie verwendet. Eine Zeichenfolge ist schließlich eine Folge von Zeichen, ähnlich einer Liste.
John Zwinck
46

Sie können die tolistMethode als Vermittler verwenden:

In [99]: import pandas as pd

In [100]: d1 = pd.DataFrame({'ticker' : ['spx 5/25/2001 p500', 'spx 5/25/2001 p600', 'spx 5/25/2001 p700']})

In [101]: d1.ticker.str.split().tolist()
Out[101]: 
[['spx', '5/25/2001', 'p500'],
 ['spx', '5/25/2001', 'p600'],
 ['spx', '5/25/2001', 'p700']]

Daraus können Sie einen neuen DataFrame erstellen:

In [102]: d2 = pd.DataFrame(d1.ticker.str.split().tolist(), 
   .....:                   columns="symbol date price".split())

In [103]: d2
Out[103]: 
  symbol       date price
0    spx  5/25/2001  p500
1    spx  5/25/2001  p600
2    spx  5/25/2001  p700

Für ein gutes Maß könnten Sie den Preis festlegen:

In [104]: d2["price"] = d2["price"].str.replace("p","").astype(float)

In [105]: d2
Out[105]: 
  symbol       date  price
0    spx  5/25/2001    500
1    spx  5/25/2001    600
2    spx  5/25/2001    700

PS: aber wenn Sie wirklich nur die letzte Spalte wollen, applywürde ausreichen:

In [113]: temp2.apply(lambda x: x[2])
Out[113]: 
0    p500
1    p600
2    p700
Name: ticker
DSM
quelle
Dies hat mir nur geholfen, eine Protokolldatei in Pandas hinzuzufügen, die zu beängstigend und chaotisch war, um sie vorher zu berühren (einzelne Datenspalte mit vielen Informationen pro Zeile).
Graben
Alle diese Ansätze haben im Vergleich zu Wes McKinneys Antwort eine katastrophale Leistung.
John Zwinck
3
@ JohnZwinck: Wow, eine leistungsbezogene Abwertung einer fünf Jahre alten Antwort auf Funktionen, die erst vor zwei Monaten eingeführt wurde ? Das ist ... streng, das gebe ich dir!
DSM
1
Aber das ist der Punkt von SE: Veraltete Antworten sollten weniger prominent angezeigt werden. Da dies hier nicht möglich ist, wenn OP die akzeptierte Lösung nicht ändert, kann nur eine Warnung an zukünftige Benutzer zu
Stimmenunterschieden führen
26

https://pandas.pydata.org/pandas-docs/stable/text.html

s2 = pd.Series(['a_b_c', 'c_d_e', np.nan, 'f_g_h'])
s2.str.split('_').str.get(1)

oder

s2.str.split('_').str[1]
James Holland
quelle
1
Sie können -1 verwenden, um das letzte Element wie den Zugriff auf das letzte Element aus der Liste s2.str.split('_').str.get(-1)
abzurufen
4

Verwenden von Pandas 0.20.3:

In [10]: import pandas as pd
    ...: temp = pd.DataFrame({'ticker' : ['spx 5/25/2001 p500', 'spx 5/25/2001 p600', 'spx 5/25/2001 p700']})
    ...:

In [11]: temp2 = temp.ticker.str.split(' ', expand=True)  # the expand=True return a DataFrame

In [12]: temp2
Out[12]:
     0          1     2
0  spx  5/25/2001  p500
1  spx  5/25/2001  p600
2  spx  5/25/2001  p700

In [13]: temp3 = temp.join(temp2[2])

In [14]: temp3
Out[14]:
               ticker     2
0  spx 5/25/2001 p500  p500
1  spx 5/25/2001 p600  p600
2  spx 5/25/2001 p700  p700
AllanLRH
quelle
1

Wenn Sie nach einem Einzeiler suchen (wie ich hierher gekommen bin), sollte dies gut funktionieren:

temp2 = temp.ticker.str.split(' ', expand = True)[-1]

Sie können diese Antwort auch trivial ändern, um diese Spalte wie folgt dem ursprünglichen DataFrame zuzuweisen:

temp['last_split'] = temp.ticker.str.split(' ', expand = True)[-1]

Was ich mir vorstelle, ist hier ein beliebter Anwendungsfall.

Sfortney
quelle