Преобразование всего фрейма данных из нижнего регистра в верхний регистр с помощью Pandas

у меня есть фрейм данных, как показано ниже:

# Create an example dataframe about a fictional army
raw_data = {'regiment': ['Nighthawks', 'Nighthawks', 'Nighthawks', 'Nighthawks'],
            'company': ['1st', '1st', '2nd', '2nd'],
            'deaths': ['kkk', 52, '25', 616],
            'battles': [5, '42', 2, 2],
            'size': ['l', 'll', 'l', 'm']}
df = pd.DataFrame(raw_data, columns = ['regiment', 'company', 'deaths', 'battles', 'size'])

enter image description here

моя цель-преобразовать каждую строку внутри фрейма данных в верхний регистр, чтобы она выглядела так:

enter image description here

Примечание: все типы данных являются объектами и не должны быть изменены; выходные данные должны содержать все объекты. Я хочу избежать преобразования каждого столбца по одному... Я хотел бы сделать это в целом более возможно, весь фрейм данных.

то, что я пробовал до сих пор, это сделать, но безуспешно

df.str.upper()

4 ответов


astype () будет бросать каждую серию в dtype объект (строка), а затем вызовите str () метод на преобразованной серии, чтобы получить строку буквально и вызвать функцию верхний() на нем. Обратите внимание, что после этого dtype всех столбцов изменяется на object.

In [17]: df
Out[17]: 
     regiment company deaths battles size
0  Nighthawks     1st    kkk       5    l
1  Nighthawks     1st     52      42   ll
2  Nighthawks     2nd     25       2    l
3  Nighthawks     2nd    616       2    m

In [18]: df.apply(lambda x: x.astype(str).str.upper())
Out[18]: 
     regiment company deaths battles size
0  NIGHTHAWKS     1ST    KKK       5    L
1  NIGHTHAWKS     1ST     52      42   LL
2  NIGHTHAWKS     2ND     25       2    L
3  NIGHTHAWKS     2ND    616       2    M

вы можете позже преобразовать столбец "битвы" в числовой снова, используя to_numeric():

In [42]: df2 = df.apply(lambda x: x.astype(str).str.upper())

In [43]: df2['battles'] = pd.to_numeric(df2['battles'])

In [44]: df2
Out[44]: 
     regiment company deaths  battles size
0  NIGHTHAWKS     1ST    KKK        5    L
1  NIGHTHAWKS     1ST     52       42   LL
2  NIGHTHAWKS     2ND     25        2    L
3  NIGHTHAWKS     2ND    616        2    M

In [45]: df2.dtypes
Out[45]: 
regiment    object
company     object
deaths      object
battles      int64
size        object
dtype: object

Это можно решить с помощью следующей операции applymap:

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

С str работает только для серии, вы можете применить его к каждому столбцу индивидуально, а затем объединить:

In [6]: pd.concat([df[col].astype(str).str.upper() for col in df.columns], axis=1)
Out[6]: 
     regiment company deaths battles size
0  NIGHTHAWKS     1ST    KKK       5    L
1  NIGHTHAWKS     1ST     52      42   LL
2  NIGHTHAWKS     2ND     25       2    L
3  NIGHTHAWKS     2ND    616       2    M

Edit:сравнение производительности

In [10]: %timeit df.apply(lambda x: x.astype(str).str.upper())
100 loops, best of 3: 3.32 ms per loop

In [11]: %timeit pd.concat([df[col].astype(str).str.upper() for col in df.columns], axis=1)
100 loops, best of 3: 3.32 ms per loop

оба ответа выполняются одинаково на небольшом фрейме данных.

In [15]: df = pd.concat(10000 * [df])

In [16]: %timeit pd.concat([df[col].astype(str).str.upper() for col in df.columns], axis=1)
10 loops, best of 3: 104 ms per loop

In [17]: %timeit df.apply(lambda x: x.astype(str).str.upper())
10 loops, best of 3: 130 ms per loop

на большом фрейме данных мой ответ немного быстрее.


Если вы хотите сохранить использование dtype, это isinstance(obj,type)

df.apply(lambda x: x.str.upper().str.strip() if isinstance(x, object) else x)