it-swarm.com.de

Pandas: Ändern Sie einen bestimmten Spaltennamen in einem Datenrahmen mit mehrstufigen Spalten

Ich möchte herausfinden, wie der Name einer bestimmten Spalte in einem mehrstufigen Datenrahmen geändert wird.

Mit diesen Daten:

data = {
    ('A', '1', 'I'): [1, 2, 3, 4, 5], 
    ('B', '2', 'II'): [1, 2, 3, 4, 5], 
    ('C', '3', 'I'): [1, 2, 3, 4, 5], 
    ('D', '4', 'II'): [1, 2, 3, 4, 5], 
    ('E', '5', 'III'): [1, 2, 3, 4, 5], 
}

dataDF = pd.DataFrame(data)

Dieser Code funktioniert nicht:

dataDF.rename(columns = {('A', '1', 'I'):('Z', '100', 'Z')}, inplace=True)

Ergebnis:

    A   B   C   D   E
    1   2   3   4   5
    I   II  I   II  III
0   1   1   1   1   1
1   2   2   2   2   2
2   3   3   3   3   3
3   4   4   4   4   4
4   5   5   5   5   5

Und auch nicht:

dataDF.columns.values[0] = ('Z', '100', 'Z')

Ergebnis:

    A   B   C   D   E
    1   2   3   4   5
    I   II  I   II  III
0   1   1   1   1   1
1   2   2   2   2   2
2   3   3   3   3   3
3   4   4   4   4   4
4   5   5   5   5   5

Aber mit Kombination der oben genannten Codes funktioniert !!!

dataDF.columns.values[0] = ('Z', '100', 'Z')
dataDF.rename(columns = {('A', '1', 'I'):('Z', '100', 'Z')}, inplace=True)
dataDF

Ergebnis:

    Z   B   C   D   E
    100 2   3   4   5
    Z   II  I   II  III
0   1   1   1   1   1
1   2   2   2   2   2
2   3   3   3   3   3
3   4   4   4   4   4
4   5   5   5   5   5

Ist dieser Bug von Pandas?

7
sh.jeon

Das ist meine Theorie

pandas wollen nicht, dass pd.Indexs veränderbar ist. Wir können das sehen, wenn wir versuchen, das erste Element des Index selbst zu ändern

dataDF.columns[0] = ('Z', '100', 'Z')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-32-2c0b76762235> in <module>()
----> 1 dataDF.columns[0] = ('Z', '100', 'Z')

//anaconda/envs/3.5/lib/python3.5/site-packages/pandas/indexes/base.py in __setitem__(self, key, value)
   1372 
   1373     def __setitem__(self, key, value):
-> 1374         raise TypeError("Index does not support mutable operations")
   1375 
   1376     def __getitem__(self, key):

TypeError: Index does not support mutable operations

Pandas können jedoch nicht kontrollieren, was Sie mit dem Attribut values tun.

dataDF.columns.values[0] = ('Z', '100', 'Z')

wir sehen, dass dataDF.columns gleich aussieht, aber dataDF.columns.values spiegelt die Änderung eindeutig wider. Leider ist df.columns.values nicht das, was auf der Anzeige des Datenrahmens angezeigt wird.


Auf der anderen Seite scheint das wirklich zu funktionieren. Die Tatsache, dass es mir nicht falsch vorkommt.

dataDF.rename(columns={('A', '1', 'I'): ('Z', '100', 'Z')}, inplace=True)

Ich glaube, der Grund, warum dies funktioniert, nachdem die Werte geändert wurden, ist, dass rename die Rekonstruktion der Spalten erzwingt, indem sie die Werte betrachtet. Da wir die Werte ändern, funktioniert es jetzt. Das ist ausnahmslos kludgy und ich empfehle nicht, einen Prozess zu bauen, der darauf angewiesen ist.


meine Empfehlung

  • geben Sie den Ort des Spaltennamens an, den Sie ändern möchten
  • weisen Sie dem Wertefeld den Namen der Spalte zu
  • baue neue Säulen von Grund auf, explicity

from_col = ('A', '1', 'I')
to_col = ('Z', '100', 'Z')
colloc = dataDF.columns.get_loc(from_col)
cvals = dataDF.columns.values
cvals[colloc] = to_col

dataDF.columns = pd.MultiIndex.from_tuples(cvals.tolist())

dataDF

[![enter code here][1]][1]
10
piRSquared

Sie können es einfach ändern wie DF.columns.levels=[[u'Z', u'B', u'C', u'D', u'E'],[u'5', u'2', u'3', u'4', u'5'],[u'IIIIII', u'II', u'III']]

1
Dark Matter

Ich stieß auf diese Frage, als ich selbst nach einer Lösung für das Umbenennen der Spaltennamen in einem Datenrahmen mit mehreren Ebenen suchte. Ich habe die von @Dark Matter bereitgestellte Lösung ausprobiert, da es sich um eine sehr einfache Lösung handelte:

dataDF.columns.levels = [[u'Z', u'B', u'C', u'D', u'E'], [u'100', u'2', u'3', u'4', u'5'], [u'Z', u'II', u'III']]

Es wurde jedoch eine Fehlermeldung angezeigt:

C:\anaconda3\lib\site-packages\ipykernel_launcher.py:1: FutureWarning: setting `levels` directly is deprecated. Use set_levels instead
  """Entry point for launching an IPython kernel.

Es scheint, dass es funktioniert hat, aber nicht mehr funktioniert. Also habe ich benutzt:

dataDF.columns.set_levels([['Z', 'B', 'C', 'D', 'E'],
                           ['100', '2', '3', '4', '5'],
                           ['Z', 'II', 'III']],
                          [0, 1, 2], inplace=True)

Ergebnis: dataDF

Z   B   C   D   E
100 2   3   4   5
Z   II  Z   II  III
0   1   1   1   1   1
1   2   2   2   2   2
2   3   3   3   3   3
3   4   4   4   4   4
4   5   5   5   5   5
1
novastar