Fügen Sie jedem Wert in einer Zeichenfolgenspalte mit Pandas ein Zeichenfolgenpräfix hinzu


118

Ich möchte eine Zeichenfolge an den Anfang jedes Werts in einer der Spalten eines Pandas-Datenrahmens anhängen (elegant). Ich habe bereits herausgefunden, wie das geht und verwende derzeit:

df.ix[(df['col'] != False), 'col'] = 'str'+df[(df['col'] != False), 'col']

Dies scheint eine verdammt unelegante Sache zu sein - kennen Sie einen anderen Weg (der den Charakter vielleicht auch zu Zeilen hinzufügt, in denen diese Spalte 0 oder NaN ist)?

Falls dies noch unklar ist, möchte ich mich wenden:

    col 
1     a
2     0

in:

       col 
1     stra
2     str0

Was genau fragst du? Bitte schreiben Sie eine Erklärung darüber, was Ihr Code tut / wünscht
Ryan Saxe

1
Ich dachte, was der Beispielcode macht, war für den durchschnittlichen Pandas-Benutzer sehr klar. Ich habe Anwendungsbeispiele für Ihre Bequemlichkeit hinzugefügt.
TheChymera

3
Ihre Beschreibung steht in gewissem Widerspruch zu Ihrem Code. Was ist != Falselos mit dem Geschäft? Möchten Sie strjeden Wert oder nur einige hinzufügen ?
BrenBarn

auf jeden Wert, wie in meinen Beispieldatenrahmen gezeigt.
TheChymera

1
Ihr Beispiel ist noch etwas unklar. Wollen Sie so etwas df['col'] = 'str' + df['col'].astype(str)?
Roman Pekar

Antworten:


222
df['col'] = 'str' + df['col'].astype(str)

Beispiel:

>>> df = pd.DataFrame({'col':['a',0]})
>>> df
  col
0   a
1   0
>>> df['col'] = 'str' + df['col'].astype(str)
>>> df
    col
0  stra
1  str0

1
Danke. Bei Interesse unterstützen Datenrahmenindizes auch solche Zeichenfolgenmanipulationen.
Tagoma

2
Wie mache ich das, wenn vor der Verkettung Bedingungen erfüllt sein müssen?
Acecabana

1
@tagoma, nach 4 Jahren Ja: Es werden auch die Datenrahmenindizes unterstützt. Sie können eine neue Spalte erstellen und an den Indexwert anhängen als: df ['col'] = 'str' + df.index.astype (str)
MEdwin

"astype (str)" kann die Codierung ruinieren, wenn Sie am Ende versuchen, in einer Datei zu speichern.
Raein Hashemi

1
Wenn ich dies und einen anderen Ansatz versuche, erhalte ich eine SettingWithCopyWarning. Gibt es eine Möglichkeit, dies zu vermeiden?
Madan Ivan

13

Alternativ können Sie auch eine applyKombination mit format(oder besser mit F-Strings) verwenden, die ich etwas besser lesbar finde, wenn man zB auch ein Suffix hinzufügen oder das Element selbst manipulieren möchte:

df = pd.DataFrame({'col':['a', 0]})

df['col'] = df['col'].apply(lambda x: "{}{}".format('str', x))

was auch die gewünschte Ausgabe ergibt:

    col
0  stra
1  str0

Wenn Sie Python 3.6+ verwenden, können Sie auch F-Strings verwenden:

df['col'] = df['col'].apply(lambda x: f"str{x}")

die gleiche Ausgabe ergeben.

Die F-String-Version ist fast so schnell wie die Lösung von @ RomanPekar (Python 3.6.4):

df = pd.DataFrame({'col':['a', 0]*200000})

%timeit df['col'].apply(lambda x: f"str{x}")
117 ms ± 451 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit 'str' + df['col'].astype(str)
112 ms ± 1.04 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

Die Verwendung formatist jedoch in der Tat viel langsamer:

%timeit df['col'].apply(lambda x: "{}{}".format('str', x))
185 ms ± 1.07 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

gleiches Ergebnis, aber viel langsamer ;-)
Philipp_Kats

1
@Philipp_Kats: Ich habe einige Timings hinzugefügt, danke für den Vorschlag! Es scheint, dass F-Saiten fast genauso schnell sind; formatin der Tat schlechter abschneidet. Wie hast du verglichen?
Cleb

Oh schön! nach meinem Verständnis .applyist es immer entweder so schnell oder langsamer als "direkte" vektorisierte Operationen; Auch wenn sie nicht langsamer sind, ziehe ich es vor, sie nach Möglichkeit zu meiden.
Philipp_Kats

@Philipp_Kats: Ich stimme jedoch zu, in diesem speziellen Fall finde ich es besser lesbar, wenn ich auch ein Suffix hinzufüge, etwas mit sich xselbst mache usw., aber das ist nur eine Frage des Geschmacks ... :)
Cleb

4

Sie können pandas.Series.map verwenden:

df['col'].map('str{}'.format)

Es wird das Wort "str" ​​vor allen Ihren Werten anwenden.


3

Wenn Sie Ihre Tabellendatei mit einem dtype=str
Spaltentyp laden oder in einen String konvertieren, können Sie folgende df['a'] = df['a'].astype(str)
Vorgehensweise verwenden:

df['a']= 'col' + df['a'].str[:]

Dieser Ansatz ermöglicht das Voranstellen, Anhängen und Teilmengenzeichenfolgen von df.
Funktioniert mit Pandas v0.23.4, v0.24.1. Ich weiß nichts über frühere Versionen.


0

Eine andere Lösung mit .loc:

df = pd.DataFrame({'col': ['a', 0]})
df.loc[df.index, 'col'] = 'string' + df['col'].astype(str)

Dies ist nicht so schnell wie die oben genannten Lösungen (> 1 ms pro Schleife langsamer), kann jedoch nützlich sein, wenn Sie eine bedingte Änderung benötigen, wie z.

mask = (df['col'] == 0)
df.loc[mask, 'col'] = 'string' + df['col'].astype(str)

Warum das .indexin df[mask].index?
AMC

@AMC, weil Sie für .loc Indizes des Datenrahmens benötigen. Dies bedeutet, dass - df [Maske] einen Datenrahmen zurückgibt, der der Bedingung entspricht, und der Index df [Maske]. Indizes des Datenrahmens zurückgibt. Aber es ist wahr, dass Sie dasselbe auch mit df.loc [(df ['col'] == 'a'), 'col'] oder df.loc [mask, 'col'] tun können.
Lukas

1
denn für .loc benötigen Sie Indizes des Datenrahmens. Wenn es df.loc[mask]funktioniert und es funktioniert, dann .indexist das überflüssig, oder?
AMC

@ AMC genau :). Ich habe die Lösung bearbeitet. Danke dir.
Lukas
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.