Zeile in Spaltenüberschrift für Pandas DataFrame konvertieren,

111

Die Daten, mit denen ich arbeiten muss, sind etwas chaotisch. Die Daten enthalten Headernamen. Wie kann ich eine Zeile aus einem vorhandenen Pandas-Datenrahmen auswählen und daraus einen Spaltenkopf machen (umbenennen)?

Ich möchte so etwas tun wie:

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

df.columns = header
EK
quelle

Antworten:

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

Stellen Sie die Spaltenbeschriftungen so ein, dass sie den Werten in der 2. Zeile (Indexposition 1) entsprechen:

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

Wenn der Index eindeutige Beschriftungen hat, können Sie die zweite Zeile mit folgenden Elementen löschen:

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

Wenn der Index nicht eindeutig ist, können Sie Folgendes verwenden:

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

Mit df.drop(df.index[1])wird alle Zeilen mit derselben Bezeichnung wie die zweite Zeile entfernt. Da nicht eindeutige Indizes zu solchen Stolpersteinen (oder potenziellen Fehlern) führen können, ist es oft besser, darauf zu achten, dass der Index eindeutig ist (obwohl Pandas dies nicht benötigt).

unutbu
quelle
Vielen Dank für Ihre schnelle Antwort! Wie kann ich eine Zeile nach Wert anstelle der Indexposition auswählen, um sie als Header zu erstellen? Also für dein Beispiel so etwas wie .. df.columns = df [df [0] == 'foo']
EK
Das Problem dabei ist, dass es mehr als eine Zeile geben kann, die den Wert hat "foo". Eine Möglichkeit, dieses Problem zu umgehen, besteht darin, die erste Zeile dieser Art explizit auszuwählen : df.columns = df.iloc[np.where(df[0] == 'foo')[0][0]].
Unutbu
Ah, ich verstehe, warum du das so gemacht hast. Für meinen Fall weiß ich, dass es nur eine Zeile gibt, die den Wert "foo" hat. Also ist es ok. Ich habe es einfach so gemacht, ich denke, es ist das gleiche wie das, das du mir oben gegeben hast. idx_loc = df [df [0] == 'foo']. index.tolist () [0] df.columns = df.iloc [idx_loc]
EK
63

Dies funktioniert (pandas v'0.19.2 '):

df.rename(columns=df.iloc[0])
Zachary Wilson
quelle
22
Sie können die "Header" .drop(df.index[0])
-Zeile
Mir gefällt das besser als die tatsächlich akzeptierte Antwort. Ich liebe die kurzen Online-Lösungen.
Javier
13

Es wäre einfacher, den Datenrahmen neu zu erstellen. Dies würde auch die Spaltentypen von Grund auf neu interpretieren.

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

Sie können den Zeilenindex in den Konstruktoren read_csv oder read_html über den headerParameter angeben, der darstellt Row number(s) to use as the column names, and the start of the data. Dies hat den Vorteil, dass automatisch alle vorhergehenden Zeilen gelöscht werden, die angeblich Junk sind.

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
quelle