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.
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
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)
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)
Conforme documentado em http://pandas.pydata.org/pandas-docs/stable/text.html:
df.columns = df.columns.str.replace('$','')
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)
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âmetroaxis
que pode ser definido comocolumns
ou1
. Esta atualização faz com que este método corresponda ao resto da API pandas. Ele ainda tem os parâmetrosindex
ecolumns
mas você não é mais forçado a usá-los. - a
set_axis
o método com oinplace
definido emFalse
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()
df.columns = ['a', 'b', 'c', 'd', 'e']
Substituirá os nomes existentes pelos nomes que indicar, pela ordem que indicar.
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.
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.
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 denumpy.array
numpy.array
s têm uma propriedade .name
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 permanecemO 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']]
Uma linha ou soluções de oleoduto
Vou concentrar-me em duas coisas:-
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 existentecolumns
por um novo um deles deu uma lista de nomes de colunas de substituição. df.columns = new
ondenew
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 existentecolumns
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 1pd.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 2pd.concat
usando o keys
argumento
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
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.
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]
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)')
df = df.rename(columns=lambda n: n.replace('$', ''))
É uma maneira funcional de resolver isto
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.)
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
Muito simples apenas use
df.columns = ['Name1', 'Name2', 'Name3'...]
E irá atribuir os nomes das colunas pela ordem que os colocares
Podias usar str.slice
para isso:
df.columns = df.columns.str.slice(1)
df.rename(index=str,columns={'A':'a','B':'b'})
Https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rename.html
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
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(' ', '_')
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)
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
df.rename(index=str, columns={"$a": "a", "$b": "b", "$c" : "c", "$d" : "d", "$e" : "e"})
df.columns = ['a', 'b',index=False]
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')
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