Soluções de uma linha ou pipeline
Vou me concentrar em duas coisas:
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 columns
objeto existente por um novo, com uma lista de nomes de colunas de substituição.
df.columns = new
onde new
está a lista de novos nomes de colunas é o mais simples possível. A desvantagem dessa abordagem é que ela requer edição do columns
atributo 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 df
com 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 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 mapeamos a new
lista como os nomes das colunas. Acabamos repetindo y765
. Em vez disso, podemos usar o keys
argumento da pd.concat
funçã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 dtype
para todas as colunas. Caso contrário, você terminará com dtype
object
todas 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 transpose
e set_index
. pd.DataFrame.set_index
permite 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 dtype
versus mista dtype
da 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 lambda
em pd.DataFrame.rename
que percorre cada elemento de new
Nesta solução, passamos um lambda que leva, x
mas depois o ignora. Também é preciso, y
mas 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 x
e y
, posso proteger minha y
variá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