Convertir fila en encabezado de columna para Pandas DataFrame,

111

Los datos con los que tengo que trabajar están un poco desordenados. Tiene nombres de encabezado dentro de sus datos. ¿Cómo puedo elegir una fila de un marco de datos de pandas existente y convertirlo (cambiarle el nombre a) un encabezado de columna?

Quiero hacer algo como:

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

df.columns = header
EK
fuente

Respuestas:

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

Configure las etiquetas de las columnas para que sean iguales a los valores de la segunda fila (ubicación del índice 1):

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

Si el índice tiene etiquetas únicas, puede quitar la segunda fila usando:

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

Si el índice no es único, puede 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

El uso df.drop(df.index[1])elimina todas las filas con la misma etiqueta que la segunda fila. Debido a que los índices no únicos pueden generar obstáculos (o errores potenciales) como este, a menudo es mejor tener cuidado de que el índice sea único (aunque Pandas no lo requiera).

unutbu
fuente
¡Muchas gracias por tu rápida respuesta! ¿Cómo puedo elegir una fila por valor en lugar de la ubicación del índice para convertirlo en encabezado? Entonces, para su ejemplo, algo como ... df.columns = df [df [0] == 'foo']
EK
El problema con eso es que podría haber más de una fila que tenga el valor "foo". Una forma de evitar este problema es elegir de manera explícita la primera fila: df.columns = df.iloc[np.where(df[0] == 'foo')[0][0]].
unutbu
Ah, veo por qué lo hiciste de esa manera. En mi caso, sé que solo hay una fila que tiene el valor "foo". Entonces está bien. Lo acabo de hacer de esta manera, supongo que es el mismo que me diste anteriormente. idx_loc = df [df [0] == 'foo']. index.tolist () [0] df.columns = df.iloc [idx_loc]
EK
63

Esto funciona (pandas v'0.19.2 '):

df.rename(columns=df.iloc[0])
Zachary Wilson
fuente
22
Puede eliminar la fila "encabezado" agregando.drop(df.index[0])
ostrokach
Me gusta esto más que la respuesta aceptada real. Me encantan las soluciones breves en línea.
Javier
13

Sería más fácil recrear el marco de datos. Esto también interpretaría los tipos de columnas desde cero.

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

Puede especificar el índice de fila en los constructores read_csv o read_html a través del headerparámetro que representa Row number(s) to use as the column names, and the start of the data. Esto tiene la ventaja de eliminar automáticamente todas las filas anteriores que supuestamente son basura.

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
fuente