Convertir la ligne en en-tête de colonne pour Pandas DataFrame,


111

Les données avec lesquelles je dois travailler sont un peu désordonnées. Il a des noms d'en-tête à l'intérieur de ses données. Comment puis-je choisir une ligne dans un dataframe pandas existant et en faire (la renommer en) un en-tête de colonne?

Je veux faire quelque chose comme:

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

df.columns = header

Réponses:


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

Définissez les étiquettes de colonne pour qu'elles correspondent aux valeurs de la deuxième ligne (emplacement d'index 1):

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

Si l'index a des libellés uniques, vous pouvez supprimer la deuxième ligne en utilisant:

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

Si l'index n'est pas unique, vous pouvez utiliser:

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

L'utilisation df.drop(df.index[1])supprime toutes les lignes avec le même libellé que la deuxième ligne. Parce que les index non uniques peuvent conduire à des pierres d'achoppement (ou des bogues potentiels) comme celui-ci, il est souvent préférable de veiller à ce que l'index soit unique (même si Pandas n'en a pas besoin).


Merci beaucoup pour votre réponse rapide! Comment puis-je choisir une ligne par valeur au lieu de l'emplacement de l'index pour en faire un en-tête? Donc, pour votre exemple, quelque chose comme .. df.columns = df [df [0] == 'foo']
— EK

Le problème avec cela est qu'il pourrait y avoir plus d'une ligne qui a la valeur "foo". Une façon de contourner ce problème est de choisir explicitement la première telle ligne: df.columns = df.iloc[np.where(df[0] == 'foo')[0][0]].
— unutbu

Ah je vois pourquoi tu as fait ça. Pour mon cas, je sais qu'il n'y a qu'une seule ligne qui a la valeur "foo". Alors ça va. Je viens de faire de cette façon, je suppose que c'est le même que celui que vous m'avez donné ci-dessus. idx_loc = df [df [0] == 'toto']. index.tolist () [0] df.columns = df.iloc [idx_loc]
— EK

63

Cela fonctionne (pandas v'0.19.2 '):

df.rename(columns=df.iloc[0])

22
Vous pouvez supprimer la ligne "en-tête" en ajoutant.drop(df.index[0])
— ostrokach

J'aime mieux cela que la réponse acceptée. J'adore les solutions courtes en ligne.
— Javier

13

Il serait plus facile de recréer la trame de données. Cela interpréterait également les types de colonnes à partir de zéro.

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

4

Vous pouvez spécifier l'index de ligne dans les constructeurs read_csv ou read_html via le headerparamètre qui représente Row number(s) to use as the column names, and the start of the data. Cela a l'avantage de supprimer automatiquement toutes les lignes précédentes qui sont supposées être indésirables.

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.