Как сделать строковый столбец pandas dataframe в нижнем регистре, если в нем отсутствуют значения?


87

Следующий код не работает.

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]? Эффективность важна, поскольку реальный фрейм данных огромен.


Начиная с v0.25, я рекомендую str.casefoldдля более агрессивных сравнений строк сворачивания регистра. Больше информации в этом ответе .
— cs95

Ответы:


188

использовать векторизованные строковые методы pandas ; как в документации:

эти методы автоматически исключают отсутствующие значения / значения 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 07

@ 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

вы также можете попробовать это,

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

1
type(s) == strвместо этого должно бытьisinstance(s, str)
— cs95

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

Pandas> = 0,25: удалить различия в регистре с помощью str.casefold

Начиная с v0.25, я рекомендую использовать "векторизованный" строковый метод, str.casefoldесли вы имеете дело с данными в Юникоде (он работает независимо от строки или юникода):

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