Renomeando colunas em pandas


1826

Eu tenho um DataFrame usando pandas e rótulos de coluna que preciso editar para substituir os rótulos originais da coluna.

Gostaria de alterar os nomes das colunas em um DataFrame Aonde os nomes das colunas originais são:

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

para

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

Tenho os nomes das colunas editadas armazenados em uma lista, mas não sei como substituir os nomes das colunas.


1
Você pode querer consultar os documentos oficiais que cobrem a renomeação dos rótulos das colunas: pandas.pydata.org/pandas-docs/stable/user_guide/text.html
ccpizza

Respostas:


1828

Basta atribuí-lo ao .columnsatributo:

>>> df = pd.DataFrame({'$a':[1,2], '$b': [10,20]})
>>> df.columns = ['a', 'b']
>>> df
   a   b
0  1  10
1  2  20

303
É possível alterar um nome de cabeçalho de coluna única?
ericmjl

112
@ericmjl: suponha que você queira alterar o nome da primeira variável de df. Então você pode fazer algo parecido com:new_columns = df.columns.values; new_columns[0] = 'XX'; df.columns = new_columns
cd98

54
Parece que você poderia simplesmente ter feito df.columns.values ​​[0] = 'XX'
RAY

25
Brincadeirinha, @RAY - não faça isso. Parece que é uma lista gerada independentemente de qualquer indexação que armazene o nome da coluna. Faz um bom trabalho destruindo nomeação coluna para o seu df ...
Mitch Flax

433
@ericmjl yesdf.rename(columns = {'$b':'B'}, inplace = True)
nachocab

2847

RENOMEAR COLUNAS ESPECÍFICAS

Use a df.rename()função e consulte as colunas a serem renomeadas. Nem todas as colunas precisam 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)

Exemplo de código mínimo

df = pd.DataFrame('x', index=range(3), columns=list('abcde'))
df

   a  b  c  d  e
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x

Os seguintes métodos funcionam e produzem a mesma saída:

df2 = df.rename({'a': 'X', 'b': 'Y'}, axis=1)  # new method
df2 = df.rename({'a': 'X', 'b': 'Y'}, axis='columns')
df2 = df.rename(columns={'a': 'X', 'b': 'Y'})  # old method  

df2

   X  Y  c  d  e
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x

Lembre-se de atribuir o resultado de volta, pois a modificação não está no local. Como alternativa, especifique inplace=True:

df.rename({'a': 'X', 'b': 'Y'}, axis=1, inplace=True)
df

   X  Y  c  d  e
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x

Na v0.25, você também pode especificar errors='raise'para gerar erros se uma coluna para renomear inválida for especificada. Consulte os documentos v0.25rename() .


REASSIGN HEADERS DA COLUNA

Use df.set_axis()com axis=1e inplace=False(para retornar uma cópia).

df2 = df.set_axis(['V', 'W', 'X', 'Y', 'Z'], axis=1, inplace=False)
df2

   V  W  X  Y  Z
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x

Isso retorna uma cópia, mas você pode modificar o DataFrame no local, definindo inplace=True(esse é o comportamento padrão para as versões <= 0,24, mas provavelmente será alterado no futuro).

Você também pode atribuir cabeçalhos diretamente:

df.columns = ['V', 'W', 'X', 'Y', 'Z']
df

   V  W  X  Y  Z
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x

2
quando eu faço isso com um quadro de dados 6 coluna (trama de dados <enter>) a representação abreviada: code<class 'pandas.core.frame.DataFrame'> Int64Index: 1000 entradas, 0 a 999 colunas de dados: BodyMarkdown 1000 não nulos codeobras , mas quando eu faço o dataframe.head () os nomes antigos das colunas reaparecem.
DarKoram 10/09/12

12
Eu fico com medo SettingWithCopyWarning:quando uso o segundo trecho de código nesta resposta.
Monica Heddneck

existe uma versão disso com substituição de regex?
Denfromufa

@lexual E se duas colunas existentes tiverem o mesmo nome? Como me refiro ao nome da coluna antiga?
vagabundo

14
A primeira solução: df = df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'})altera o nome exibido, mas não os elementos na estrutura de dados subjacente. Portanto, se você tentar, df['newName1']receberá um erro. O inplace=Trueé necessário para evitar que gotchya.
irritable_phd_syndrom

402

O renamemétodo pode assumir 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)

56
Agradável. Este salvou meu dia:df.rename(columns=lambda x: x.lstrip(), inplace=True)
root-11

2
Semelhante ao @ root-11 - no meu caso, havia um caractere de marcador que não era impresso na saída do console IPython, então eu precisava remover mais do que apenas espaço em branco (faixa), então:t.columns = t.columns.str.replace(r'[^\x00-\x7F]+','')
The Red Pea

9
df.rename(columns=lambda x: x.replace(' ', '_'), inplace=True)é uma jóia para que possamos escrever em df.Column_1_Namevez de escrever df.loc[:, 'Column 1 Name'].
Little Bobby Tables


164

Pandas 0.21+ Answer

Houve algumas atualizações significativas na renomeação de colunas na versão 0.21.

  • O renamemétodo adicionou o axisparâmetro que pode ser definido como columnsou 1. Esta atualização faz esse método corresponder ao restante da API do pandas. Ele ainda possui os parâmetros indexe, columnsmas você não é mais obrigado a usá-los.
  • O set_axismétodo com o inplaceconjunto de Falsepermite renomear todos os rótulos de índice ou coluna com uma lista.

Exemplos para Pandas 0.21+

Exemplo de construção DataFrame:

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 renamecom axis='columns'ouaxis=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 usar a assinatura do método antigo:

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

A renamefunção 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)

Usando set_axiscom uma lista einplace=False

Você pode fornecer uma lista para o set_axismétodo de comprimento igual ao número de colunas (ou índice). Atualmente, o inplacepadrão é True, mas inplaceserá padronizado Falseem 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)

Por que não usar df.columns = ['a', 'b', 'c', 'd', 'e'] ?

Não há nada errado em atribuir colunas diretamente assim. É uma solução perfeitamente boa.

A vantagem do uso set_axisé que ele pode ser usado como parte de uma cadeia de métodos e retorna uma nova cópia do DataFrame. Sem ele, você teria que armazenar suas etapas intermediárias da cadeia em outra variável antes de reatribuir 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()

1
Obrigado pela Pandas 0.21+ answer- de alguma forma eu perdi essa parte no "o que é novo" parte ...
MaxU

1
A solução não parece funcionar para o Pandas 3.6: df.rename ({'$ a': 'a', '$ b': 'b', '$ c': 'c', '$ d': 'd ',' $ e ':' e '}, eixo =' colunas '). Obtém um argumento de palavra-chave "eixo" inesperado
Arthur D. Howland

3
df.columns = ['a', 'b', 'c', 'd', 'e'] parece não funcionar mais, trabalhando com a versão 0.22 Tenho um aviso dizendo que o Pandas não permite que colunas sejam criadas via um novo nome de atributo . como mudar o nome se todas minhas colunas são chamados a mesma: /
Nabla

Existe uma maneira de renomear uma, várias ou todas as colunas, se você não souber o nome da (s) coluna (s) antes, mas apenas o índice? Obrigado!
tommy.carstensen

este foi um comentário muito útil. por exemplo, a função lambda respondeu à minha pergunta de como fazer o seguinte:(df .groupby(['page',pd.Grouper(key='date',freq='MS')])['clicks'].sum() .unstack(1) .rename(lambda x: x.strftime("%Y-%m"), axis='columns') )
measureallthethings

131

Como você deseja remover apenas o sinal de $ em todos os nomes de coluna, basta:

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

OU

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

1
Este não apenas ajuda no caso do OP, mas também em requisitos genéricos. Por exemplo: para dividir o nome de uma coluna por um separador e usar uma parte dela.
Deepak


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

Dessa forma, você pode editar manualmente o new_namesque desejar. Funciona muito bem quando você precisa renomear apenas algumas colunas para corrigir erros ortográficos, acentos, remover caracteres especiais etc.


1
Eu gosto dessa abordagem, mas acho que df.columns = ['a', 'b', 'c', 'd', 'e']é mais simples.
Christopher Pearson

1
Eu gosto desse método de compactar nomes antigos e novos. Podemos usar df.columns.valuespara obter os nomes antigos.
bkowshik

1
Eu exibo a exibição tabular e copio as colunas para old_names. Copio a matriz de requisitos para new_names. Em seguida, use dict (zip (old_names, new_names)) Solução muito elegante.
mythicalcoder

Costumo usar subconjuntos de listas de algo como myList = list(df) myList[10:20]:, etc - então isso é perfeito.
Tim Gottgetreu

É melhor usar os nomes antigos como o @bkowshik sugeriu, depois editá-los e inseri-los novamente, ou seja, namez = df.columns.valuesseguidos de algumas edições df.columns = namez.
pauljohn32 17/01

34

Soluções de uma linha ou pipeline

Vou me concentrar em duas coisas:

  1. OP afirma claramente

    Tenho os nomes das colunas editadas armazenados em uma lista, mas não sei como substituir os nomes das colunas.

    Não quero resolver o problema de como substituir '$'ou remover o primeiro caractere de cada cabeçalho da coluna. O OP já executou esta etapa. Em vez disso, quero focar na substituição do columnsobjeto existente por um novo, com uma lista de nomes de colunas de substituição.

  2. df.columns = newonde newestá a lista de novos nomes de colunas é o mais simples possível. A desvantagem dessa abordagem é que ela requer edição do columnsatributo do quadro de dados existente e isso não é feito em linha. Mostrarei algumas maneiras de fazer isso via pipelining sem editar o quadro de dados existente.


Configuração 1
Para focar na necessidade de renomear os nomes de colunas substituídos por uma lista preexistente, criarei um novo dataframe de amostra dfcom nomes de colunas iniciais e novos nomes de colunas 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 você tivesse um dicionário mapeando os nomes das colunas antigas para os novos, poderia 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 criar facilmente esse dicionário e incluí-lo na chamada para rename. A seguir, aproveita-se o fato de que, quando iteramos df, iteramos sobre o nome de cada 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

Isso funciona muito bem se os nomes das colunas originais forem exclusivos. Mas, se não estiverem, isso será interrompido.


Configurar 2
colunas não exclusivas

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 keysargumento

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 mapeamos a newlista como os nomes das colunas. Acabamos repetindo y765. Em vez disso, podemos usar o keysargumento da pd.concatfunção enquanto iteramos pelas 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
Reconstrua. Isso só deve ser usado se você tiver um único dtypepara todas as colunas. Caso contrário, você terminará com dtype objecttodas as colunas e convertê-las novamente exige mais trabalho de dicionário.

solteiro dtype

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

   x098  y765  z432
0     1     3     5
1     2     4     6

Misturado 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 enigmático com transposee set_index. pd.DataFrame.set_indexpermite definir um índice em linha, mas não há correspondência set_columns. Então podemos transpor, então set_index, e transpor de volta. No entanto, a mesma ressalva única dtypeversus mista dtypeda solução 3 se aplica aqui.

solteiro dtype

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

   x098  y765  z432
0     1     3     5
1     2     4     6

Misturado 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
Use a lambdaem pd.DataFrame.renameque percorre cada elemento de new
Nesta solução, passamos um lambda que leva, xmas depois o ignora. Também é preciso, ymas não o espera. Em vez disso, um iterador é fornecido como um valor padrão e eu posso usá-lo para percorrer um de cada vez, sem levar em conta qual é o valor x.

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

   x098  y765  z432
0     1     3     5
1     2     4     6

E, como me foi indicado pelo pessoal do chat do sopython , se eu adicionar um *entre xe y, posso proteger minha yvariável. Porém, neste contexto, não acredito que precise ser protegido. Ainda vale a pena mencionar.

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

   x098  y765  z432
0     1     3     5
1     2     4     6

Talvez possamos adicionardf.rename(lambda x : x.lstrip('$'),axis=1)
YOBEN_S

Olá @piRSquared, você poderia explicar como o pandas usa a função lambda na solução 5, por favor? Não entendo bem o que você quer dizer quando diz que xé ignorado?
Josmoor98

33

Nomes de colunas vs nomes de séries

Eu gostaria de explicar um pouco o que acontece nos bastidores.

Os quadros de dados são um conjunto de séries.

As séries, por sua vez, são uma extensão de um numpy.array

numpy.arrays tem uma propriedade .name

Este é o nome da série. Raramente os pandas respeitam esse atributo, mas permanecem em alguns lugares e podem ser usados ​​para invadir alguns comportamentos dos pandas.

Nomeando a lista de colunas

Muitas respostas aqui falam sobre o df.columnsatributo ser listquando, na verdade, é um Series. Isso significa que ele tem um .nameatributo.

É 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

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

Artefatos que permanecem

O .nameatributo permanece algumas vezes. Se você definir, df.columns = ['one', 'two']então df.one.nameserá 'one'.

Se você definir df.one.name = 'three', df.columnsainda lhe dará ['one', 'two']edf.one.name lhe dará'three'

MAS

pd.DataFrame(df.one) retornará

    three
0       1
1       2
2       3

Porque os pandas reutilizam o .namedos já definidos Series.

Nomes de colunas em vários níveis

O Pandas tem maneiras de criar nomes de colunas em várias camadas. Não há muita mágica envolvida, mas eu queria cobrir isso na minha resposta também, já que não vejo ninguém percebendo isso aqui.

    |one            |
    |one      |two  |
0   |  4      |  1  |
1   |  5      |  2  |
2   |  6      |  3  |

Isso é facilmente possível definindo colunas em listas, assim:

df.columns = [['one', 'one'], ['one', 'two']]

18

Se você possui o quadro de dados, o df.columns despeja tudo em uma lista que você pode manipular e depois reatribuir no quadro 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

Melhor maneira? SEI LÁ. Um caminho - sim.

Uma maneira melhor de avaliar todas as principais técnicas apresentadas nas respostas à pergunta é a seguir, usando o cProfile para medir a memória e o tempo de execução. @kadee, @kaitlyn e @eumiro tiveram as funções com os tempos de execução mais rápidos - embora essas funções sejam tão rápidas que estamos comparando o arredondamento de 0,000 e 0,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)')

Por que você precisa renomear o método? Algo como isso funcionou para mim # df.columns = [row.replace ( '$', '') para linha na df.columns]
shantanuo

Eu não entendo a parte das 'coisas'. O que eu tenho que substituir? As colunas antigas?
Andrea Ianni 5

18

Digamos que este seja seu quadro de dados.

insira a descrição da imagem aqui

Você pode renomear as colunas usando dois métodos.

  1. Usando dataframe.columns=[#list]

    df.columns=['a','b','c','d','e']

    insira a descrição da imagem aqui

    A limitação desse método é que, se uma coluna precisar ser alterada, a lista completa de colunas deverá ser passada. Além disso, esse método não é aplicável aos rótulos de índice. Por exemplo, se você passou isso:

    df.columns = ['a','b','c','d']

    Isso gerará um erro. Incompatibilidade de comprimento: o eixo esperado possui 5 elementos, novos valores possuem 4 elementos.

  2. Outro método é o rename()método Pandas , usado para renomear qualquer índice, coluna ou linha

    df = df.rename(columns={'$a':'a'})

    insira a descrição da imagem aqui

Da mesma forma, você pode alterar qualquer linha ou coluna.


17
df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1], '$d': [1], '$e': [1]})

Se sua nova lista de colunas estiver na mesma ordem que as colunas existentes, a atribuição será 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 você tivesse um dicionário digitado em nomes de colunas antigos para novos, você 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 você não possui um mapeamento de lista ou dicionário, pode retirar o $símbolo principal por meio de uma compreensão da lista:

df.columns = [col[1:] if col[0] == '$' else col for col in df]

2
Em vez de lambda col: d[col]você poder passar d.get... assim seria parecido comdf.columns.map(d.get)
piRSquared


15

Vamos entender a renomeação por um pequeno exemplo ...

1. Renomeando colunas usando o mapeamento:

df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}) #creating a df with column name A and B
df.rename({"A": "new_a", "B": "new_b"},axis='columns',inplace =True) #renaming column A with 'new_a' and B with 'new_b'

output:
   new_a  new_b
0  1       4
1  2       5
2  3       6

Renomear índice / Nome_da_Rota usando o mapeamento:

df.rename({0: "x", 1: "y", 2: "z"},axis='index',inplace =True) #Row name are getting replaced by 'x','y','z'.

output:
       new_a  new_b
    x  1       4
    y  2       5
    z  3       6

A resposta mais votada já tem esses exemplos ...
Itamar Mushkin

14

Outra maneira de substituir os rótulos das colunas originais é removendo os caracteres indesejados (aqui '$') dos rótulos das colunas originais.

Isso poderia ter sido feito executando um loop for sobre o df.columns e anexando as colunas removidas ao df.columns.

Em vez disso, podemos fazer isso ordenadamente em uma única declaração usando a compreensão de lista como abaixo:

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

(o stripmétodo em Python retira o caractere fornecido do início e do fim da string.)


2
Você pode explicar como / por que isso funciona? Isso tornará a resposta mais valiosa para futuros leitores.
Dan Lowe

12

Muito simples, basta usar

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

e atribuirá os nomes das colunas pela ordem em que você os colocou


10

Você poderia usar str.slicepara isso:

df.columns = df.columns.str.slice(1)

1
PS: Este é um equivalente mais detalhado de df.columns.str[1:]... provavelmente é melhor usá-lo, é mais curto e mais óbvio.
cs95 25/05/19

9

Eu sei que esta pergunta e resposta foram mastigadas até a morte. Mas eu me referi a ele como inspiração para um dos problemas que eu estava tendo. Eu era capaz de resolvê-lo usando pedaços de respostas diferentes, fornecendo minha resposta caso alguém precisasse.

Meu método é genérico, no qual você pode adicionar delimitadores adicionais separando vírgulas delimiters= variável e preparando-o para o 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

8

Observe que essas abordagens não funcionam 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

8

Outra opção é renomear 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

6

Se você precisar lidar com um monte de colunas nomeadas pelo sistema de fornecimento fora de seu controle, criei a seguinte abordagem, que é uma combinação de uma abordagem geral e substituições específicas de uma só vez.

Primeiro, crie um dicionário a partir dos nomes das colunas do quadro de dados usando expressões regex para descartar certos apêndices de nomes de colunas e, em seguida, adicione substituições específicas ao dicionário para nomear as colunas principais conforme o esperado posteriormente no banco de dados de recebimento.

Isso é aplicado ao quadro de dados de uma só 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)

5

Além da solução já fornecida, você pode substituir todas as colunas enquanto estiver lendo o arquivo. Nós podemos usar nameseheader=0 fazer isso.

Primeiro, criamos uma lista dos nomes que gostamos de usar como nomes de coluna:

import pandas as pd

ufo_cols = ['city', 'color reported', 'shape reported', 'state', 'time']
ufo.columns = ufo_cols

ufo = pd.read_csv('link to the file you are using', names = ufo_cols, header = 0)

Nesse caso, todos os nomes de colunas serão substituídos pelos nomes que você tem na sua lista.


4

Aqui está uma pequena função bacana que eu gosto de usar para reduzir a digitação:

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

1
O caso de uso para uma função como essa é extremamente raro. Na maioria dos casos, eu sei o que estou procurando e para o qual quero renomeá-lo; eu mesmo atribui / modifico.
cs95 25/05/19

1
@ cs95 Costumo trabalhar com grandes pesquisas nacionais ou internacionais em que variáveis ​​terão nomes de variáveis ​​codificados que começam com prefixos, dependendo das opções de resposta, escalas de Likert e ramificação (como EDU_2913.443, EDU_2913.421, ...). Esta função tem sido muito útil para mim em trabalhar com esses tipos de conjuntos, eu entendo se não for para você embora :)
seeiespi

4

Renomear colunas em pandas é uma tarefa fácil.

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

2

Supondo que você possa usar expressão regular. Esta solução elimina a necessidade de codificação manual usando regex

import pandas as pd
import re

srch=re.compile(r"\w+")

data=pd.read_csv("CSV_FILE.csv")
cols=data.columns
new_cols=list(map(lambda v:v.group(),(list(map(srch.search,cols)))))
data.columns=new_cols

2
É uma boa prática no Stack Overflow adicionar uma explicação sobre por que sua solução deve funcionar ou é melhor do que as soluções existentes. Para mais informações, leia Como responder .
Samuel Liew

Observe como a resposta mais bem avaliada exige alguma forma de codificação embutida e a resposta mais bem avaliada exige apenas abordagem descritiva e processual?
precisa

Existem soluções melhores (mais legíveis) que também utilizam regex do que isso. Isso está fazendo muito mais do que deveria para uma operação de renomeação simples. Também há o perigo de o padrão não corresponder a nada; nesse caso, você não fez nada para lidar com erros.
cs95
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.