Mudar o nome das colunas em pandas

eu tenho um DataFrame usando pandas e legendas de colunas que eu preciso Editar para substituir as legendas originais da coluna.

gostaria de alterar os nomes das colunas num DataFrame A onde os nomes das colunas originais são:

['$a', '$b', '$c', '$d', '$e'] 

a

['a', 'b', 'c', 'd', 'e'].

tenho os nomes das colunas editadas guardadas numa lista, mas não sei como substituir os nomes das colunas.

Author: jmuhlenkamp, 2012-07-05

28 answers

Atribui-o apenas ao atributo .columns:

>>> df = pd.DataFrame({'$a':[1,2], '$b': [10,20]})
>>> df.columns = ['a', 'b']
>>> df
   a   b
0  1  10
1  2  20
 1186
Author: eumiro, 2012-07-05 14:23:27

df.rename() function and reference the columns to be renamed. Nem todas as colunas têm de ser renomeadas:

df = df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'})
# Or rename the existing DataFrame (rather than creating a copy) 
df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'}, inplace=True)
 1947
Author: lexual, 2017-11-17 17:39:42

A rename o método pode ter uma função, por exemplo:

In [11]: df.columns
Out[11]: Index([u'$a', u'$b', u'$c', u'$d', u'$e'], dtype=object)

In [12]: df.rename(columns=lambda x: x[1:], inplace=True)

In [13]: df.columns
Out[13]: Index([u'a', u'b', u'c', u'd', u'e'], dtype=object)
 305
Author: Andy Hayden, 2013-05-21 09:58:59

Conforme documentado em http://pandas.pydata.org/pandas-docs/stable/text.html:

df.columns = df.columns.str.replace('$','')
 129
Author: kadee, 2015-05-30 13:24:05

Uma vez que só quer remover o sinal de $ em todos os nomes das colunas, pode simplesmente fazer:

df = df.rename(columns=lambda x: x.replace('$', ''))

Ou

df.rename(columns=lambda x: x.replace('$', ''), inplace=True)
 116
Author: paulo.filip3, 2014-03-26 10:20:45

Pandas 0.21+ Resposta

Houve algumas actualizações significativas para a mudança de nome da coluna na versão 0.21.

  • a rename o método adicionou o parâmetro axis que pode ser definido como columns ou 1. Esta atualização faz com que este método corresponda ao resto da API pandas. Ele ainda tem os parâmetros index e columns mas você não é mais forçado a usá-los.
  • a set_axis o método com o inplace definido em False permite-lhe mudar o nome de todos os Legendas de índices ou colunas com uma lista.

Exemplos de Pandas 0, 21+

Construir um DataFrame de amostra:

df = pd.DataFrame({'$a':[1,2], '$b': [3,4], 
                   '$c':[5,6], '$d':[7,8], 
                   '$e':[9,10]})

   $a  $b  $c  $d  $e
0   1   3   5   7   9
1   2   4   6   8  10

Usando rename com axis='columns' ou axis=1

df.rename({'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'}, axis='columns')

Ou

df.rename({'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'}, axis=1)

Ambos resultam no seguinte:

   a  b  c  d   e
0  1  3  5  7   9
1  2  4  6  8  10

Ainda é possível utilizar a assinatura do método antigo:

df.rename(columns={'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'})

A função rename também aceita funções que serão aplicadas a cada nome de coluna.

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

Ou

df.rename(lambda x: x[1:], axis=1)

Utilizar set_axis com uma lista e inplace=False

Você pode fornecer uma lista para o método set_axis que é igual em comprimento ao número de colunas (ou índice). Actualmente, inplace o valor por omissão é True, Mas inplace será ultrapassado em False em versões futuras.

df.set_axis(['a', 'b', 'c', 'd', 'e'], axis='columns', inplace=False)

Ou

df.set_axis(['a', 'b', 'c', 'd', 'e'], axis=1, inplace=False)

Porque não utilizar df.columns = ['a', 'b', 'c', 'd', 'e']?

Não há nada de errado em Atribuir colunas directamente como esta. É uma solução perfeitamente boa.

A vantagem de usar {[16] } é que pode ser usado como parte de uma cadeia de métodos e que devolve uma nova cópia do DataFrame. Sem ele, você teria que armazenar seus passos intermediários da cadeia para outra variável antes de reassegurar as colunas.

# 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()
 102
Author: Ted Petrou, 2017-11-17 19:31:57
df.columns = ['a', 'b', 'c', 'd', 'e']

Substituirá os nomes existentes pelos nomes que indicar, pela ordem que indicar.

 68
Author: M PAUL, 2018-10-12 05:45:57
old_names = ['$a', '$b', '$c', '$d', '$e'] 
new_names = ['a', 'b', 'c', 'd', 'e']
df.rename(columns=dict(zip(old_names, new_names)), inplace=True)

Desta forma, poderá editar manualmente o new_names como desejar. Funciona muito bem quando precisa de mudar o nome de apenas algumas colunas para corrigir erros ortográficos, sotaques, remover caracteres especiais, etc.

 54
Author: migloo, 2015-05-21 17:54:25

Acho que este método é útil:

df.rename(columns={"old_column_name1":"new_column_name1", "old_column_name2":"new_column_name2"})

Este método permite-lhe alterar os nomes das colunas individualmente.

 37
Author: wolfog, 2018-04-19 08:08:00

Nomes de colunas vs nomes de Séries

Gostaria de explicar um pouco o que acontece nos bastidores.

Os nomes de dados são um conjunto de Séries.

Por sua vez, as séries são uma extensão de numpy.array

numpy.arrays têm uma propriedade .name

Este é o nome da série. É raro que pandas respeite este atributo, mas ele permanece em lugares e pode ser usado para hackear alguns comportamentos pandas.

Nomear a lista das colunas

Muito as respostas aqui falam sobre o atributo df.columns ser um list quando na verdade é um Series. Isto significa que tem um atributo .name.

Isto é o que acontece se você decidir preencher o nome das colunas Series:

df.columns = ['column_one', 'column_two']
df.columns.names = ['name of the list of columns']
df.index.names = ['name of the index']

name of the list of columns     column_one  column_two
name of the index       
0                                    4           1
1                                    5           2
2                                    6           3

Note que o nome do índice vem sempre uma coluna mais abaixo.

Artefactos que permanecem

O atributo .name permanece às vezes. Se você definir {[13] } Então o {[14] } será 'one'.

Se você definir df.one.name = 'three' Então df.columns ainda lhe dará ['one', 'two'], e df.one.name dar-te-á 'three'

Mas

pd.DataFrame(df.one) vai voltar

    three
0       1
1       2
2       3

Porque os pandas reutilizam o .name do já definido Series.

Nomes de colunas multi-níveis

Os Pandas têm formas de fazer vários nomes de colunas. Não há muita magia envolvida, mas eu queria cobrir isso na minha resposta também, uma vez que não vejo ninguém percebendo isso aqui.
    |one            |
    |one      |two  |
0   |  4      |  1  |
1   |  5      |  2  |
2   |  6      |  3  |

Isto é facilmente realizável ao definir colunas para listas, como isto:

df.columns = [['one', 'one'], ['one', 'two']]
 31
Author: firelynx, 2016-09-29 12:30:40

Uma linha ou soluções de oleoduto

Vou concentrar-me em duas coisas:
  1. A OP indica claramente

    Tenho os nomes das colunas editadas guardadas numa lista, mas não sei como substituir os nomes das colunas.

    Não quero resolver o problema de como substituir '$' ou remover o primeiro carácter de cada cabeçalho da coluna. O OP já deu este passo. Em vez disso, quero concentrar-me em substituir o objecto existente columns por um novo um deles deu uma lista de nomes de colunas de substituição.

  2. df.columns = new onde new está a lista de nomes de colunas novas é tão simples quanto possível. A desvantagem desta abordagem é que ela requer a edição do atributo dataframe existente columns e não é feito inline. Vou mostrar algumas maneiras de executar isso através de pipelining sem editar o dataframe existente.


Configuração 1
Para se concentrar na necessidade de mudar o nome das colunas por um lista pré-existente, vou criar uma nova amostra de dataframe df com nomes de colunas iniciais e nomes de colunas novos não relacionados.

df = pd.DataFrame({'Jack': [1, 2], 'Mahesh': [3, 4], 'Xin': [5, 6]})
new = ['x098', 'y765', 'z432']

df

   Jack  Mahesh  Xin
0     1       3    5
1     2       4    6

Solução 1
pd.DataFrame.rename

Já foi dito que se tivesses um dicionário a mapear os nomes das colunas antigas para os nomes das colunas novas, podias usar pd.DataFrame.rename.

d = {'Jack': 'x098', 'Mahesh': 'y765', 'Xin': 'z432'}
df.rename(columns=d)

   x098  y765  z432
0     1     3     5
1     2     4     6

No entanto, você pode facilmente criar esse dicionário e incluí-lo na chamada para rename. O seguinte aproveita o facto de que, quando se iterando sobre df, nós iteramos sobre cada nome de coluna.

# given just a list of new column names
df.rename(columns=dict(zip(df, new)))

   x098  y765  z432
0     1     3     5
1     2     4     6
Isto funciona muito bem se os nomes originais das colunas forem únicos. Mas se não estiverem, então isto vai-se abaixo.

Configuração 2
colunas não únicas

df = pd.DataFrame(
    [[1, 3, 5], [2, 4, 6]],
    columns=['Mahesh', 'Mahesh', 'Xin']
)
new = ['x098', 'y765', 'z432']

df

   Mahesh  Mahesh  Xin
0       1       3    5
1       2       4    6

Solução 2
pd.concat usando o keys argumento

Primeiro, observe o que acontece quando tentamos usar a solução 1:
df.rename(columns=dict(zip(df, new)))

   y765  y765  z432
0     1     3     5
1     2     4     6
Não mapeámos o mapa. new lista com os nomes das colunas. Acabámos por repetir. Em vez disso, podemos usar o argumento keys da função pd.concat enquanto iteramos através das colunas de df.
pd.concat([c for _, c in df.items()], axis=1, keys=new) 

   x098  y765  z432
0     1     3     5
1     2     4     6

Solução 3
Reconstruir. Isto só deve ser usado se tiver um dtype único para todas as colunas. Caso contrário, vais acabar com dtype object para todas as colunas e convertê-las de volta requer mais trabalho de dicionário.

simples dtype

pd.DataFrame(df.values, df.index, new)

   x098  y765  z432
0     1     3     5
1     2     4     6

Misto dtype

pd.DataFrame(df.values, df.index, new).astype(dict(zip(new, df.dtypes)))

   x098  y765  z432
0     1     3     5
1     2     4     6

Solução 4
Este é um truque de truques com transpose e set_index. pd.DataFrame.set_index permite-nos definir um índice em linha, mas não existe um set_columns correspondente. Então podemos transpor, então set_index, e transpor para trás. No entanto, aplica-se aqui o mesmo único dtype versus misto dtype da solução 3.

simples dtype

df.T.set_index(np.asarray(new)).T

   x098  y765  z432
0     1     3     5
1     2     4     6

Misto dtype

df.T.set_index(np.asarray(new)).T.astype(dict(zip(new, df.dtypes)))

   x098  y765  z432
0     1     3     5
1     2     4     6

Solução 5
Utilizar um lambda em pd.DataFrame.rename que atravessa cada elemento de new
Nesta solução, passamos por uma lambda que toma x mas depois ignora-a. Também é preciso um y mas não o espera. Em vez disso, um iterador é dado como um valor padrão e eu posso então usar isso para ciclo através de um de cada vez sem considerar o que o valor de x é.

df.rename(columns=lambda x, y=iter(new): next(y))

   x098  y765  z432
0     1     3     5
1     2     4     6

E tal como me foi apontado pelo pessoal emsopython chat, Se eu adicione um * entre x e y, Eu posso proteger a minha variável y. Mas, neste contexto, não creio que precise de protecção. Ainda vale a pena mencioná-lo.

df.rename(columns=lambda x, *, y=iter(new): next(y))

   x098  y765  z432
0     1     3     5
1     2     4     6
 28
Author: piRSquared, 2017-09-13 09:10:15

DataFrame -- df.mudar o nome () irá funcionar.

df.rename(columns = {'Old Name':'New Name'})

Df é o nome de dados que tens, e o Nome antigo é o nome de coluna que tens se quiser mudar, então o Novo Nome é o novo nome para o qual você muda. Este método built-in do DataFrame torna as coisas muito mais fáceis.

 19
Author: flowera, 2017-10-15 16:25:03
df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1], '$d': [1], '$e': [1]})

Se a sua nova lista de colunas estiver na mesma ordem que as colunas existentes, a atribuição é simples:

new_cols = ['a', 'b', 'c', 'd', 'e']
df.columns = new_cols
>>> df
   a  b  c  d  e
0  1  1  1  1  1

Se tivesse um dicionário marcado nos nomes das colunas antigas para os nomes das colunas novas, poderia fazer o seguinte:

d = {'$a': 'a', '$b': 'b', '$c': 'c', '$d': 'd', '$e': 'e'}
df.columns = df.columns.map(lambda col: d[col])  # Or `.map(d.get)` as pointed out by @PiRSquared.
>>> df
   a  b  c  d  e
0  1  1  1  1  1

Se não tiver uma lista ou um mapeamento de dicionário, poderá remover o símbolo principal $ através de uma compreensão de Lista:

df.columns = [col[1:] if col[0] == '$' else col for col in df]
 16
Author: Alexander, 2017-09-13 12:24:31

Se tiveres o nome do dataframe, df.as colunas largam tudo numa lista que pode manipular e depois transferem para o seu nome de dados como os nomes das colunas...

columns = df.columns
columns = [row.replace("$","") for row in columns]
df.rename(columns=dict(zip(columns, things)), inplace=True)
df.head() #to validate the output
A melhor maneira? IDK. Uma maneira ... sim.

Uma melhor maneira de avaliar todas as principais técnicas apresentadas nas respostas à pergunta é usando o perfil de cProfile para a memória gage e tempo de execução. @kadee, @kaitlyn, & @eumiro teve as funções com os tempos de execução mais rápidos-embora estas funções são tão rápido que estamos comparando o arredondamento de .Mil e ...001 segundos para todas as respostas. Moral: minha resposta acima provavelmente não é a melhor maneira.

import pandas as pd
import cProfile, pstats, re

old_names = ['$a', '$b', '$c', '$d', '$e']
new_names = ['a', 'b', 'c', 'd', 'e']
col_dict = {'$a': 'a', '$b': 'b','$c':'c','$d':'d','$e':'e'}

df = pd.DataFrame({'$a':[1,2], '$b': [10,20],'$c':['bleep','blorp'],'$d':[1,2],'$e':['texa$','']})

df.head()

def eumiro(df,nn):
    df.columns = nn
    #This direct renaming approach is duplicated in methodology in several other answers: 
    return df

def lexual1(df):
    return df.rename(columns=col_dict)

def lexual2(df,col_dict):
    return df.rename(columns=col_dict, inplace=True)

def Panda_Master_Hayden(df):
    return df.rename(columns=lambda x: x[1:], inplace=True)

def paulo1(df):
    return df.rename(columns=lambda x: x.replace('$', ''))

def paulo2(df):
    return df.rename(columns=lambda x: x.replace('$', ''), inplace=True)

def migloo(df,on,nn):
    return df.rename(columns=dict(zip(on, nn)), inplace=True)

def kadee(df):
    return df.columns.str.replace('$','')

def awo(df):
    columns = df.columns
    columns = [row.replace("$","") for row in columns]
    return df.rename(columns=dict(zip(columns, '')), inplace=True)

def kaitlyn(df):
    df.columns = [col.strip('$') for col in df.columns]
    return df

print 'eumiro'
cProfile.run('eumiro(df,new_names)')
print 'lexual1'
cProfile.run('lexual1(df)')
print 'lexual2'
cProfile.run('lexual2(df,col_dict)')
print 'andy hayden'
cProfile.run('Panda_Master_Hayden(df)')
print 'paulo1'
cProfile.run('paulo1(df)')
print 'paulo2'
cProfile.run('paulo2(df)')
print 'migloo'
cProfile.run('migloo(df,old_names,new_names)')
print 'kadee'
cProfile.run('kadee(df)')
print 'awo'
cProfile.run('awo(df)')
print 'kaitlyn'
cProfile.run('kaitlyn(df)')
 15
Author: andrewwowens, 2016-09-07 02:24:19
df = df.rename(columns=lambda n: n.replace('$', ''))

É uma maneira funcional de resolver isto

 12
Author: lf2225, 2018-04-19 08:07:43

Outra forma de substituirmos as legendas originais das colunas é retirando os caracteres indesejados (aqui'$') das legendas originais das colunas.

Isto poderia ter sido feito executando um laço for sobre o df.colunas e adicionando as colunas despojadas ao df.coluna.

Em vez disso, podemos fazer isto bem numa única declaração usando a compreensão da lista como abaixo:

df.columns = [col.strip('$') for col in df.columns]

(strip o método em Python remove o carácter dado do início e do fim do texto.)

 11
Author: kait, 2017-07-05 13:19:35
Sei que esta pergunta e a resposta foram mastigadas até à morte. Mas eu me referi a ele para inspiração para um dos problemas que eu estava tendo . Eu fui capaz de resolvê-lo usando bits e peças de diferentes respostas, portanto, fornecendo a minha resposta no caso de alguém precisar dele.

O meu método é genérico, onde se pode adicionar delimitadores adicionais por vírgula a separar delimiters= variável e à prova do futuro.

Código De Trabalho:

import pandas as pd
import re


df = pd.DataFrame({'$a':[1,2], '$b': [3,4],'$c':[5,6], '$d': [7,8], '$e': [9,10]})

delimiters = '$'
matchPattern = '|'.join(map(re.escape, delimiters))
df.columns = [re.split(matchPattern, i)[1] for i in df.columns ]

Resultado:

>>> df
   $a  $b  $c  $d  $e
0   1   3   5   7   9
1   2   4   6   8  10

>>> df
   a  b  c  d   e
0  1  3  5  7   9
1  2  4  6  8  10
 10
Author: Anil_M, 2016-08-04 20:26:50

Muito simples apenas use

df.columns = ['Name1', 'Name2', 'Name3'...]

E irá atribuir os nomes das colunas pela ordem que os colocares

 9
Author: Thodoris P, 2015-11-29 19:22:47

Podias usar str.slice para isso:

df.columns = df.columns.str.slice(1)
 9
Author: Anton Protopopov, 2016-01-28 17:31:39
 8
Author: Yog, 2018-08-29 13:35:39

Note que esta abordagem não funciona para um MultiIndex. Para um MultiIndex, você precisa fazer algo como o seguinte:

>>> df = pd.DataFrame({('$a','$x'):[1,2], ('$b','$y'): [3,4], ('e','f'):[5,6]})
>>> df
   $a $b  e
   $x $y  f
0  1  3  5
1  2  4  6
>>> rename = {('$a','$x'):('a','x'), ('$b','$y'):('b','y')}
>>> df.columns = pandas.MultiIndex.from_tuples([
        rename.get(item, item) for item in df.columns.tolist()])
>>> df
   a  b  e
   x  y  f
0  1  3  5
1  2  4  6
 7
Author: oxer, 2016-08-29 21:27:20

Mudar o nome das colunas de dados e substituir o formato

import pandas as pd

data = {'year':[2015,2011,2007,2003,1999,1996,1992,1987,1983,1979,1975],
        'team':['Australia','India','Australia','Australia','Australia','Sri Lanka','Pakistan','Australia','India','West Indies','West Indies'],
        }
df = pd.DataFrame(data)

#Rename Columns
df.rename(columns={'year':'Years of Win','team':'Winning Team'}, inplace=True)

#Replace format
df = df.columns.str.replace(' ', '_')
 7
Author: Sankar guru, 2018-05-18 09:02:02
Se você tem que lidar com cargas de colunas nomeadas pelo sistema de fornecimento fora de seu controle, eu cheguei com a seguinte abordagem que é uma combinação de uma abordagem geral e substituições específicas de uma só vez.

Primeiro, crio um dicionário a partir dos nomes das colunas dataframe usando expressões regex para deitar fora certos apêndices de nomes de colunas e então eu adiciono substituições específicas ao dicionário para nomear colunas centrais como esperado mais tarde na recepção banco.

Isto é então aplicado ao dataframe de uma vez.

dict=dict(zip(df.columns,df.columns.str.replace('(:S$|:C1$|:L$|:D$|\.Serial:L$)','')))
dict['brand_timeseries:C1']='BTS'
dict['respid:L']='RespID'
dict['country:C1']='CountryID
dict['pim1:D']='pim_actual'
df.rename(columns=dict, inplace=True)
 4
Author: matthhias, 2017-06-16 08:27:37

Outra opção é mudar o nome usando uma expressão regular:

import pandas as pd
import re

df = pd.DataFrame({'$a':[1,2], '$b':[3,4], '$c':[5,6]})

df = df.rename(columns=lambda x: re.sub('\$','',x))
>>> df
   a  b  c
0  1  3  5
1  2  4  6
 4
Author: sbha, 2018-07-07 02:07:23
Experimenta isto. Funciona para mim.
df.rename(index=str, columns={"$a": "a", "$b": "b", "$c" : "c", "$d" : "d", "$e" : "e"})
 3
Author: Nodar Okroshiashvili, 2018-04-19 08:07:06
Caso não queiras os nomes das linhasdf.columns = ['a', 'b',index=False]
 2
Author: Domnick, 2017-11-02 05:17:38
Aqui está uma pequena função que gosto de usar para cortar ao escrever:
def rename(data, oldnames, newname): 
    if type(oldnames) == str: #input can be a string or list of strings 
        oldnames = [oldnames] #when renaming multiple columns 
        newname = [newname] #make sure you pass the corresponding list of new names
    i = 0 
    for name in oldnames:
        oldvar = [c for c in data.columns if name in c]
        if len(oldvar) == 0: 
            raise ValueError("Sorry, couldn't find that column in the dataset")
        if len(oldvar) > 1: #doesn't have to be an exact match 
            print("Found multiple columns that matched " + str(name) + " :")
            for c in oldvar:
                print(str(oldvar.index(c)) + ": " + str(c))
            ind = input('please enter the index of the column you would like to rename: ')
            oldvar = oldvar[int(ind)]
        if len(oldvar) == 1:
            oldvar = oldvar[0]
        data = data.rename(columns = {oldvar : newname[i]})
        i += 1 
    return data   
Aqui está um exemplo de como funciona:
In [2]: df = pd.DataFrame(np.random.randint(0,10,size=(10, 4)), columns=['col1','col2','omg','idk'])
#first list = existing variables
#second list = new names for those variables
In [3]: df = rename(df, ['col','omg'],['first','ohmy']) 
Found multiple columns that matched col :
0: col1
1: col2

please enter the index of the column you would like to rename: 0

In [4]: df.columns
Out[5]: Index(['first', 'col2', 'ohmy', 'idk'], dtype='object')
 2
Author: seeiespi, 2018-05-18 23:36:09
Renaming columns while reading the Dataframe: 

>>> df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1]}).rename(columns = 
         {'$a' : 'a','$b':'b','$c':'c'})

Out[1]: 
   a  b  c
0  1  1  1
 1
Author: M.r_L, 2018-09-29 08:38:08