Переименовать определенные столбцы в пандах

182

У меня есть датафрейм data. Как бы я переименовал только один заголовок столбца? Например, gdpчтобы log(gdp)?

data =
    y  gdp  cap
0   1    2    5
1   2    3    9
2   8    7    2
3   3    4    7
4   6    7    7
5   4    8    3
6   8    2    8
7   9    9   10
8   6    6    4
9  10   10    7
natsuki_2002
источник
7
Определенно есть совпадение, но из «Переименования столбцов в пандах» мне не сразу стало понятно, что можно выделить отдельный элемент столбца для переименования. Конечно, в ретроспективе это очевидно, и если бы я копал глубже, я бы, наверное, понял это, но я думаю, что этот вопрос / ответ лучше указать на это.
Иеремия Будда

Ответы:

360
data.rename(columns={'gdp':'log(gdp)'}, inplace=True)

renameПоказывает , что он принимает Dict как пары для columnsтак что вы просто пройти Dict с одной записью.

Также смотрите связанные

EdChum
источник
3
Это занимает очень много времени на большом фрейме данных, поэтому я считаю, что это копирует весь фрейм данных в памяти?
elgehelge
1
@elgehelge это не должно делать, большинство операций pandas будут возвращать копию, а некоторые принимают inplaceпараметр, если он игнорирует этот параметр, то это ошибка, можете ли вы выполнить тайминг с параметром и без параметра, также попробуйте что-то подобное new_df = df.rename(columns={'new_name':'old_name'})и посмотрите, быстрее или нет
EdChum
1
@ EdChum Спасибо. Удаление inplaceпараметра почти удвоило время с 14 до 26 секунд. Но 14 секунд все еще довольно долго, чтобы просто поменять заголовок ..
elgehelge
2
только одна заметка, будьте осторожны! если целевой столбец не существует (неправильное написание имени или около того), это ничего не изменит без ошибок или предупреждений.
Амир
1
@Quastiat - это удручающе, почему некоторые из этих простых операций выполняются быстрее, если понимать список. Принципиально, хотя, если у вас нет очень большого df, то это не должно иметь большого значения, если вы не переименовываете много столбцов на большом df
EdChum
27

Гораздо более быструю реализацию можно использовать, list-comprehensionесли вам нужно переименовать один столбец.

df.columns = ['log(gdp)' if x=='gdp' else x for x in df.columns]

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

df.columns = ['log(gdp)' if x=='gdp' else 'cap_mod' if x=='cap' else x for x in df.columns]

Или создайте отображение с помощью a dictionaryи выполните операцию list-comprehensionwith it, getустановив значение по умолчанию в качестве старого имени:

col_dict = {'gdp': 'log(gdp)', 'cap': 'cap_mod'}   ## key→old name, value→new name

df.columns = [col_dict.get(x, x) for x in df.columns]

Тайминги:

%%timeit
df.rename(columns={'gdp':'log(gdp)'}, inplace=True)
10000 loops, best of 3: 168 µs per loop

%%timeit
df.columns = ['log(gdp)' if x=='gdp' else x for x in df.columns]
10000 loops, best of 3: 58.5 µs per loop
Никил мавели
источник
Я хотел бы использовать этот метод, но, к сожалению, он не работает, pd.merge_asof()потому что это выражение :(.
thdoan
14

Как переименовать определенный столбец в пандах?

От v0.24 +, чтобы переименовать один (или более) столбцов за один раз,

  • DataFrame.rename()с axis=1или axis='columns'( axisаргумент был введен в v0.21.

  • Index.str.replace() для замены на основе строк / регулярных выражений.

Если вам нужно переименовать ВСЕ столбцы одновременно,

  • DataFrame.set_axis()метод с axis=1. Передайте последовательность, подобную списку. Опции доступны и для модификации на месте.

rename с участием axis=1

df = pd.DataFrame('x', columns=['y', 'gdp', 'cap'], index=range(5))
df

   y gdp cap
0  x   x   x
1  x   x   x
2  x   x   x
3  x   x   x
4  x   x   x

С 0.21+ вы можете теперь указать axisпараметр с rename:

df.rename({'gdp':'log(gdp)'}, axis=1)
# df.rename({'gdp':'log(gdp)'}, axis='columns')
    
   y log(gdp) cap
0  x        x   x
1  x        x   x
2  x        x   x
3  x        x   x
4  x        x   x

(Обратите внимание, что renameпо умолчанию это не на месте, поэтому вам нужно будет вернуть результат обратно .)

Это дополнение было сделано для улучшения согласованности с остальной частью API. Новый axisаргумент аналогичен columnsпараметру - они делают то же самое.

df.rename(columns={'gdp': 'log(gdp)'})

   y log(gdp) cap
0  x        x   x
1  x        x   x
2  x        x   x
3  x        x   x
4  x        x   x

rename также принимает обратный вызов, который вызывается один раз для каждого столбца.

df.rename(lambda x: x[0], axis=1)
# df.rename(lambda x: x[0], axis='columns')

   y  g  c
0  x  x  x
1  x  x  x
2  x  x  x
3  x  x  x
4  x  x  x

Для этого конкретного сценария вы хотели бы использовать

df.rename(lambda x: 'log(gdp)' if x == 'gdp' else x, axis=1)

Index.str.replace

Подобно replaceметоду строк в python, pandas Index и Series (только объект dtype) определяют (векторизованный) str.replaceметод для замены на основе строк и регулярных выражений.

df.columns = df.columns.str.replace('gdp', 'log(gdp)')
df
 
   y log(gdp) cap
0  x        x   x
1  x        x   x
2  x        x   x
3  x        x   x
4  x        x   x

Преимущество этого перед другими методами в том, что str.replaceподдерживает регулярные выражения (по умолчанию включено). Смотрите документы для получения дополнительной информации.


Передача списка set_axisсaxis=1

Вызов set_axisсо списком заголовков. Длина списка должна быть равна размеру столбцов / индексов. set_axisпо умолчанию изменяет исходный DataFrame, но вы можете указать, inplace=Falseвозвращать ли измененную копию.

df.set_axis(['cap', 'log(gdp)', 'y'], axis=1, inplace=False)
# df.set_axis(['cap', 'log(gdp)', 'y'], axis='columns', inplace=False)

  cap log(gdp)  y
0   x        x  x
1   x        x  x
2   x        x  x
3   x        x  x
4   x        x  x

Примечание: в будущих выпусках по inplaceумолчанию будет True.

Цепочка методов
Зачем выбирать, set_axisкогда у нас уже есть эффективный способ назначения столбцов df.columns = ...? Как показал Тед Петру в [этом ответе], ( https://stackoverflow.com/a/46912050/4909087 ) set_axisполезно при попытке цепочки методов.

сравнить

# new for pandas 0.21+
df.some_method1()
  .some_method2()
  .set_axis()
  .some_method3()

Против

# old way
df1 = df.some_method1()
        .some_method2()
df1.columns = columns
df1.some_method3()

Первый более естественный и свободно распространяемый синтаксис.

cs95
источник
3

Существует как минимум пять различных способов переименования определенных столбцов в пандах, и я перечислил их ниже вместе со ссылками на оригинальные ответы. Я также рассчитал время этих методов и обнаружил, что они работают примерно одинаково (хотя YMMV зависит от вашего набора данных и сценария). Тест ниже , чтобы переименовать столбцы , A M N Zчтобы A2 M2 N2 Z2в dataframe с колоннами , Aчтобы Zсодержащий миллион строк.

# Import required modules
import numpy as np
import pandas as pd
import timeit

# Create sample data
df = pd.DataFrame(np.random.randint(0,9999,size=(1000000, 26)), columns=list('ABCDEFGHIJKLMNOPQRSTUVWXYZ'))

# Standard way - https://stackoverflow.com/a/19758398/452587
def method_1():
    df_renamed = df.rename(columns={'A': 'A2', 'M': 'M2', 'N': 'N2', 'Z': 'Z2'})

# Lambda function - https://stackoverflow.com/a/16770353/452587
def method_2():
    df_renamed = df.rename(columns=lambda x: x + '2' if x in ['A', 'M', 'N', 'Z'] else x)

# Mapping function - https://stackoverflow.com/a/19758398/452587
def rename_some(x):
    if x=='A' or x=='M' or x=='N' or x=='Z':
        return x + '2'
    return x
def method_3():
    df_renamed = df.rename(columns=rename_some)

# Dictionary comprehension - https://stackoverflow.com/a/58143182/452587
def method_4():
    df_renamed = df.rename(columns={col: col + '2' for col in df.columns[
        np.asarray([i for i, col in enumerate(df.columns) if 'A' in col or 'M' in col or 'N' in col or 'Z' in col])
    ]})

# Dictionary comprehension - https://stackoverflow.com/a/38101084/452587
def method_5():
    df_renamed = df.rename(columns=dict(zip(df[['A', 'M', 'N', 'Z']], ['A2', 'M2', 'N2', 'Z2'])))

print('Method 1:', timeit.timeit(method_1, number=10))
print('Method 2:', timeit.timeit(method_2, number=10))
print('Method 3:', timeit.timeit(method_3, number=10))
print('Method 4:', timeit.timeit(method_4, number=10))
print('Method 5:', timeit.timeit(method_5, number=10))

Вывод:

Method 1: 3.650640267
Method 2: 3.163998427
Method 3: 2.998530871
Method 4: 2.9918436889999995
Method 5: 3.2436501520000007

Используйте наиболее интуитивный для вас метод, который проще всего реализовать в вашем приложении.

thdoan
источник