Як писати в нижньому регістрі рядок стовпця кадру даних pandas, якщо в ньому відсутні значення?


86

Наступний код не працює.

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())

Як мені його налаштувати, щоб отримати xLower = ['one', 'two', np.nan]? Ефективність важлива, оскільки реальний фрейм даних величезний.


Починаючи з версії 0.25, я рекомендую str.casefoldдля більш агресивного порівняння рядків, що складаються. Більше інформації у цій відповіді .
cs95

Відповіді:


183

використовувати векторизовані рядкові методи панд ; як в документації:

ці методи автоматично виключають відсутні значення / значення NA

.str.lower() це найперший приклад там;

>>> df['x'].str.lower()
0    one
1    two
2    NaN
Name: x, dtype: object

цікаво, що це повільніше, ніж метод карти, в іншій відповіді 10000 loops, best of 3: 96.4 µs per loopпроти10000 loops, best of 3: 125 µs per loop
EdChum

1
@EdChum, що не дивно лише з 3 елементами; але це не було б у випадку з, скажімо, лише 100 елементами;
behzad.nouri

@ behzad.nouri Я спробував df1 ['comment'] = df1 ['comment']. str.lower (), але щоразу мав помилку KeyError: 'comment'. Я перевірив - у мене стовпець з назвою точно такий же. Що може спричинити помилку?
Катя

16

Іншим можливим рішенням, якщо стовпець має не лише рядки, а й числа, є використання astype(str).str.lower()або to_string(na_rep='')тому, що інакше, враховуючи, що число не є рядком, при опусканні воно повернеться NaN, отже:

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()

тоді маємо:

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

і ні

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

редагувати:

якщо ви не хочете втратити NaN, то використання карти буде краще, (з @ wojciech-walczak та @ cs95 коментар) це буде виглядати приблизно так

xSecureLower = df['x'].map(lambda x: x.lower() if isinstance(x,str) else x)

1
Дякую, чоловіче! Я забув про NaN, я просто виправив відповідь
Mike W,

7

Можливе рішення:

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)

І результат:

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

Не впевнений у ефективності, хоча.


Так само, як і інша відповідь, використовуйте isinstanceпри перевірці типу об’єкта.
cs95,

6

Ви можете спробувати і цей,

df= df.applymap(lambda s:s.lower() if type(s) == str else s)

1
type(s) == strмає бути замість цьогоisinstance(s, str)
cs95,

6

Pandas> = 0,25: Видалити відмінності між регістром за допомогою str.casefold

Починаючи з v0.25, я рекомендую використовувати "векторизований" метод рядків, str.casefoldякщо ви маєте справу з даними Unicode (він працює незалежно від рядка або unicodes):

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

0       lower
1    capitals
2         NaN
3    swapcase
dtype: object

Також див. Відповідну проблему GitHub GH25405 .

casefoldпіддається більш агресивному порівнянню складання справ. Він також граційно обробляє NaN (так само, як str.lowerце робить).

Але чому це краще?

Різниця помітна в унікодах. Беручи приклад у документах pythonstr.casefold ,

Складання регістрів подібне до нижнього, але більш агресивне, оскільки воно призначене для видалення всіх відмінностей між регістрами в рядку. Наприклад, німецька мала літера 'ß'є еквівалентом "ss". Оскільки це вже мала літера, lower()нічого не зробиш 'ß'; casefold() перетворює його в "ss".

Порівняйте вихідні дані lowerдля,

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

0    der fluß
dtype: object

Versus casefold,

s.str.casefold()

0    der fluss
dtype: object

Також див. Python: lower () проти casefold () у збігу рядків та перетворенні в нижній регістр .


2

Можливо, використовується розуміння списку

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)

2

Застосувати лямбда-функцію

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

1

Використовуйте функцію застосування,

Xlower = df['x'].apply(lambda x: x.upper()).head(10) 

1
Оскільки ефективність є важливою для користувача, (Efficiency is important since the real data frame is huge.)і є ще кілька відповідей, спробуйте пояснити, яка з них є вашою точкою вашої відповіді.
Девід Гарсія Бодего,

0

скопіюйте стовпець Dataframe і просто застосуйте

df=data['x']
newdf=df.str.lower()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.