Wie kann eine Pandas-Datenrahmen-Zeichenfolgenspalte in Kleinbuchstaben geschrieben werden, wenn Werte fehlen?

86

Der folgende Code funktioniert nicht.

import pandas as pd
import numpy as np
df=pd.DataFrame(['ONE','Two', np.nan],columns=['x']) 
xLower = df["x"].map(lambda x: x.lower())

Wie soll ich es optimieren, um xLower = ['eins', 'zwei', np.nan] zu erhalten? Effizienz ist wichtig, da der reale Datenrahmen riesig ist.

P. Scondido
quelle
Ab Version 0.25 empfehle ich str.casefoldfür aggressivere Vergleiche von Faltstrings . Weitere Informationen in dieser Antwort .
CS95

Antworten:

184

Verwenden Sie pandas- vektorisierte String-Methoden . wie in der Dokumentation:

Diese Methoden schließen fehlende / NA-Werte automatisch aus

.str.lower() ist das allererste Beispiel dort;

>>> df['x'].str.lower()
0    one
1    two
2    NaN
Name: x, dtype: object
behzad.nouri
quelle
Interessanterweise ist dies langsamer als die 10000 loops, best of 3: 96.4 µs per loop10000 loops, best of 3: 125 µs per loop
Kartenmethode
1
@EdChum das ist nicht überraschend mit nur 3 Elementen; aber es wäre nicht der Fall mit nur 100 Elementen;
behzad.nouri
@ behzad.nouri Ich habe versucht, df1 ['comment'] = df1 ['comment']. str.lower (), habe aber jedes Mal den Fehler KeyError: 'comment' erhalten. Ich habe geprüft - ich habe die gleiche Spalte mit dem gleichen Namen. Was kann einen Fehler verursachen?
Katya
16

Eine andere mögliche Lösung für den Fall, dass die Spalte nicht nur Zeichenfolgen, sondern auch Zahlen enthält, ist die Verwendung astype(str).str.lower()oder to_string(na_rep='')weil eine Zahl, wenn sie keine Zeichenfolge ist, wenn sie abgesenkt wird NaN, wird sie zurückgegeben :

import pandas as pd
import numpy as np
df=pd.DataFrame(['ONE','Two', np.nan,2],columns=['x']) 
xSecureLower = df['x'].to_string(na_rep='').lower()
xLower = df['x'].str.lower()

dann haben wir:

>>> xSecureLower
0    one
1    two
2   
3      2
Name: x, dtype: object

und nicht

>>> xLower
0    one
1    two
2    NaN
3    NaN
Name: x, dtype: object

bearbeiten:

Wenn Sie die NaNs nicht verlieren möchten, ist die Verwendung der Karte besser (aus @ wojciech-walczak und @ cs95 Kommentar). Sie sieht ungefähr so ​​aus

xSecureLower = df['x'].map(lambda x: x.lower() if isinstance(x,str) else x)
Mike W.
quelle
1
Danke, Mann! Ich habe NaNs vergessen, ich habe gerade die Antwort korrigiert
Mike W
7

Sie können dieses auch versuchen,

df= df.applymap(lambda s:s.lower() if type(s) == str else s)
Farid
quelle
1
type(s) == strsollte stattdessen seinisinstance(s, str)
cs95
7

Eine mögliche Lösung:

import pandas as pd
import numpy as np

df=pd.DataFrame(['ONE','Two', np.nan],columns=['x']) 
xLower = df["x"].map(lambda x: x if type(x)!=str else x.lower())
print (xLower)

Und ein Ergebnis:

0    one
1    two
2    NaN
Name: x, dtype: object

Ich bin mir jedoch nicht sicher über die Effizienz.

Wojciech Walczak
quelle
Verwenden Sie diese Option wie bei der anderen Antwort, isinstancewenn Sie den Typ eines Objekts überprüfen.
CS95
6

Pandas> = 0,25: Fallunterscheidungen entfernen mit str.casefold

Ab Version 0.25 empfehle ich die Verwendung der "vektorisierten" String-Methode, str.casefoldwenn Sie mit Unicode-Daten arbeiten (sie funktioniert unabhängig von String oder Unicodes):

s = pd.Series(['lower', 'CAPITALS', np.nan, 'SwApCaSe'])
s.str.casefold()

0       lower
1    capitals
2         NaN
3    swapcase
dtype: object

Siehe auch das zugehörige GitHub-Problem GH25405 .

casefoldeignet sich für einen aggressiveren Vergleich von Fällen. Es behandelt auch NaNs elegant (genau wie str.lower).

Aber warum ist das besser?

Der Unterschied wird bei Unicodes gesehen. Nehmen Sie das Beispiel in den Python- str.casefoldDokumenten ,

Das Fallfalten ähnelt dem Kleinbuchstaben, ist jedoch aggressiver, da alle Fallunterschiede in einer Zeichenfolge entfernt werden sollen. Zum Beispiel ist der deutsche Kleinbuchstabe 'ß'gleichbedeutend mit "ss". Da es bereits Kleinbuchstaben ist, lower()würde nichts dagegen tun 'ß'; casefold() konvertiert es in "ss".

Vergleichen Sie die Ausgabe von lowerfür,

s = pd.Series(["der Fluß"])
s.str.lower()

0    der fluß
dtype: object

Versus casefold,

s.str.casefold()

0    der fluss
dtype: object

Siehe auch Python: lower () vs. casefold () bei der Zeichenfolgenübereinstimmung und Konvertierung in Kleinbuchstaben .

cs95
quelle
2

Möglicherweise wird das Listenverständnis verwendet

import pandas as pd
import numpy as np
df=pd.DataFrame(['ONE','Two', np.nan],columns=['Name']})
df['Name'] = [str(i).lower() for i in df['Name']] 

print(df)
deepesh
quelle
2

Wenden Sie die Lambda-Funktion an

df['original_category'] = df['original_category'].apply(lambda x:x.lower())
Aravinda_gn
quelle
1

Verwenden Sie die Apply-Funktion.

Xlower = df['x'].apply(lambda x: x.upper()).head(10) 
Ashutosh Shankar
quelle
1
Da die Effizienz für den Benutzer wichtig ist (Efficiency is important since the real data frame is huge.)und es noch einige Antworten gibt, versuchen Sie bitte herauszufinden, welche der gute Punkt Ihrer Antwort ist.
David García Bodego
0

Kopieren Sie Ihre Dataframe-Spalte und bewerben Sie sich einfach

df=data['x']
newdf=df.str.lower()
Ch HaXam
quelle