Renomear colunas específicas em pandas

182

Eu tenho um quadro de dados chamado data. Como renomearia o único cabeçalho de coluna? Por exemplo gdppara 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
fonte
7
Definitivamente, há sobreposição, mas não estava claro para mim em "Renomeando colunas nos pandas" que você poderia destacar um elemento de coluna solitário para renomear. É claro que, em retrospecto, é óbvio, e se eu tivesse aprofundado mais, provavelmente teria descoberto isso, mas acho que essa pergunta / resposta é melhor para apontar isso.
precisa

Respostas:

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

O renameprograma que aceita um ditado como um parâmetro para columnsvocê passar um ditado com uma única entrada.

Veja também relacionados

EdChum
fonte
3
Isso leva muito tempo em um grande quadro de dados, então eu acredito que isso faz algum tipo de cópia de todo o quadro na memória?
elgehelge
1
@elgehelge não deve fazer, operação maioria dos pandas irá retornar uma cópia e alguns aceitam um inplaceparâmetro, se é ignorar este param então este é um bug, você pode fazer horários com e sem o param, também tentar algo parecido new_df = df.rename(columns={'new_name':'old_name'})e ver se isso é mais rápido ou não
EdChum
1
@ EdChum Obrigado. A remoção do inplaceparâmetro quase dobrou o tempo de 14 segundos para 26 segundos. Mas 14 segundos ainda
demoram
2
apenas uma nota, cuidado! se a coluna de destino não existir, (digitando incorretamente o nome), isso não fará nada sem erro ou aviso.
Amir
1
@ Quastiat, é meio deprimente por que algumas dessas operações simples são mais rápidas, fazendo uma lista de compreensão. Fundamentalmente, embora menos que você tenha um grande df, então não deve realmente importa menos que você está renomeando um monte de colunas em uma grande df
EdChum
27

Uma implementação muito mais rápida seria usar list-comprehensionse você precisar renomear uma única coluna.

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

Se surgir a necessidade de renomear várias colunas, use expressões condicionais como:

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

Ou, construa um mapeamento usando ae dictionaryexecute a operação list-comprehensionit getits definindo o valor padrão como o nome antigo:

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]

Horários:

%%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
Nickil Maveli
fonte
Eu adoraria usar esse método, mas infelizmente ele não funciona pd.merge_asof()porque é uma expressão :(.
thdoan
14

Como renomear uma coluna específica nos pandas?

Da v0.24 +, para renomear uma (ou mais) colunas por vez,

Se você precisar renomear TODAS as colunas de uma só vez,

  • DataFrame.set_axis()método com axis=1. Passe uma sequência tipo lista. As opções também estão disponíveis para modificação no local.

rename com 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

Com 0,21+, agora você pode especificar um axisparâmetro com 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

(Observe que renamenão está no local por padrão, você precisará atribuir o resultado novamente .)

Essa adição foi feita para melhorar a consistência com o restante da API. O novo axisargumento é análogo ao columnsparâmetro - eles fazem a mesma coisa.

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 também aceita um retorno de chamada chamado uma vez para cada coluna.

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

Para esse cenário específico, você deseja usar

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

Index.str.replace

Semelhante ao replacemétodo de seqüências de caracteres em python, o pandas Index and Series (apenas no tipo de objeto) define um str.replacemétodo ("vetorizado") para a substituição baseada em expressões e regex.

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

A vantagem disso sobre os outros métodos é que str.replacesuporta regex (ativado por padrão). Veja os documentos para mais informações.


Passando uma lista para set_axiscomaxis=1

Ligue set_axiscom uma lista de cabeçalho (s). A lista deve ter comprimento igual ao tamanho das colunas / índice. set_axismodifica o DataFrame original por padrão, mas você pode especificar inplace=Falsepara retornar uma cópia modificada.

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

Nota: Em versões futuras, inplaceo padrão será True.

Encadeamento de métodos
Por que escolher set_axisquando já temos uma maneira eficiente de atribuir colunas df.columns = ...? Conforme mostrado por Ted Petrou em [esta resposta], ( https://stackoverflow.com/a/46912050/4909087 ) set_axisé útil ao tentar encadear métodos.

Comparar

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

Versus

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

O primeiro é uma sintaxe mais natural e de fluxo livre.

cs95
fonte
3

Existem pelo menos cinco maneiras diferentes de renomear colunas específicas nos pandas, e eu as listei abaixo, juntamente com links para as respostas originais. Também cronometrei esses métodos e achei que eles tinham o mesmo desempenho (apesar do YMMV, dependendo do seu conjunto de dados e cenário). O caso de teste abaixo é renomear colunas A M N Zpara A2 M2 N2 Z2em um dataframe com colunas Apara Zconter um milhão de linhas.

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

Resultado:

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

Use o método mais intuitivo para você e mais fácil de implementar em seu aplicativo.

thdoan
fonte