Converter linha em cabeçalho de coluna para Pandas DataFrame,

111

Os dados com os quais tenho que trabalhar são um pouco confusos. Tem nomes de cabeçalho dentro de seus dados. Como posso escolher uma linha de um dataframe existente do pandas e torná-lo (renomeá-lo para) um cabeçalho de coluna?

Eu quero fazer algo como:

header = df[df['old_header_name1'] == 'new_header_name1']

df.columns = header
EK
fonte

Respostas:

196
In [21]: df = pd.DataFrame([(1,2,3), ('foo','bar','baz'), (4,5,6)])

In [22]: df
Out[22]: 
     0    1    2
0    1    2    3
1  foo  bar  baz
2    4    5    6

Defina os rótulos das colunas para serem iguais aos valores na 2ª linha (localização do índice 1):

In [23]: df.columns = df.iloc[1]

Se o índice tiver rótulos exclusivos, você pode descartar a 2ª linha usando:

In [24]: df.drop(df.index[1])
Out[24]: 
1 foo bar baz
0   1   2   3
2   4   5   6

Se o índice não for único, você pode usar:

In [133]: df.iloc[pd.RangeIndex(len(df)).drop(1)]
Out[133]: 
1 foo bar baz
0   1   2   3
2   4   5   6

Usar df.drop(df.index[1])remove todas as linhas com o mesmo rótulo da segunda linha. Como os índices não exclusivos podem levar a obstáculos (ou possíveis bugs) como esse, geralmente é melhor cuidar para que o índice seja exclusivo (mesmo que o Pandas não exija isso).

unutbu
fonte
Muito obrigado por sua resposta rápida! Como posso escolher uma linha por valor em vez da localização do índice para torná-lo cabeçalho? Então, para o seu exemplo, algo como .. df.columns = df [df [0] == 'foo']
EK
O problema com isso é que pode haver mais de uma linha com o valor "foo". Uma maneira de contornar esse problema é escolher explicitamente o primeiro tal consecutivas: df.columns = df.iloc[np.where(df[0] == 'foo')[0][0]].
unutbu 01 de
Ah, entendo porque você fez assim. No meu caso, sei que existe apenas uma linha com o valor "foo". Então está tudo bem. Acabei de fazer isso, acho que é o mesmo que você me deu acima. idx_loc = df [df [0] == 'foo']. index.tolist () [0] df.columns = df.iloc [idx_loc]
EK
63

Isso funciona (pandas v'0.19.2 '):

df.rename(columns=df.iloc[0])
Zachary Wilson
fonte
22
Você pode remover a linha "cabeçalho" adicionando.drop(df.index[0])
ostrokach
Gosto mais disso do que da resposta real aceita. Eu amo as soluções curtas on-line.
Javier
13

Seria mais fácil recriar o quadro de dados. Isso também interpretaria os tipos de colunas do zero.

headers = df.iloc[0]
new_df  = pd.DataFrame(df.values[1:], columns=headers)
shahar_m
fonte
4

Você pode especificar o índice da linha nos construtores read_csv ou read_html por meio do headerparâmetro que representa Row number(s) to use as the column names, and the start of the data. Isso tem a vantagem de eliminar automaticamente todas as linhas anteriores que supostamente são inúteis.

import pandas as pd
from io import StringIO

In[1]
    csv = '''junk1, junk2, junk3, junk4, junk5
    junk1, junk2, junk3, junk4, junk5
    pears, apples, lemons, plums, other
    40, 50, 61, 72, 85
    '''

    df = pd.read_csv(StringIO(csv), header=2)
    print(df)

Out[1]
       pears   apples   lemons   plums   other
    0     40       50       61      72      85
ccpizza
fonte