Wenn Ihr Datenrahmen einen einfachen Spaltenindex hat, dann gibt es keinen Unterschied. Zum Beispiel
In [8]: df = pd.DataFrame(np.arange(12).reshape(4,3), columns=list('ABC'))
In [9]: df.loc[:, ['A','B']]
Out[9]:
A B
0 0 1
1 3 4
2 6 7
3 9 10
In [10]: df.loc[:, ('A','B')]
Out[10]:
A B
0 0 1
1 3 4
2 6 7
3 9 10
Aber wenn der Datenrahmen einen Multiindex hat, kann es ein großer Unterschied sein:
df = pd.DataFrame(np.random.randint(10, size=(5,4)),
columns=pd.MultiIndex.from_arrays([['foo']*2+['bar']*2,
list('ABAB')]),
index=pd.MultiIndex.from_arrays([['baz']*2+['qux']*3,
list('CDCDC')]))
# foo bar
# A B A B
# baz C 7 9 9 9
# D 7 5 5 4
# qux C 5 0 5 1
# D 1 7 7 4
# C 6 4 3 5
In [27]: df.loc[:, ('foo','B')]
Out[27]:
baz C 9
D 5
qux C 0
D 7
C 4
Name: (foo, B), dtype: int64
In [28]: df.loc[:, ['foo','B']]
KeyError: 'MultiIndex Slicing requires the index to be fully lexsorted tuple len (1), lexsort depth (0)'
Die KeyError sagt, dass der Multiindex lexsorted werden muss. Wenn wir das tun, erhalten wir immer noch ein anderes Ergebnis:
In [29]: df.sortlevel(axis=1).loc[:, ('foo','B')]
Out[29]:
baz C 9
D 5
qux C 0
D 7
C 4
Name: (foo, B), dtype: int64
In [30]: df.sortlevel(axis=1).loc[:, ['foo','B']]
Out[30]:
foo
A B
baz C 7 9
D 7 5
qux C 5 0
D 1 7
C 6 4
Warum ist das? df.sortlevel(axis=1).loc[:, ('foo','B')]
wählt die Spalte aus, in der die erste Spaltenebene foo
und die zweite Spaltenebene B
ist.
Im Gegensatz dazu wählt df.sortlevel(axis=1).loc[:, ['foo','B']]
die Spalten aus, in denen die erste Spalte entweder foo
oder B
ist. In Bezug auf die erste Spaltebene gibt es keine B
Spalten, aber es gibt zwei foo
Spalten.
denke ich, das Funktionsprinzip mit Pandas, dass, wenn Sie df.loc[...]
als ein Ausdruck verwenden, sollten Sie davon ausgehen, df.loc
kann eine Kopie oder eine Ansicht zurückkehren. In den Pandas-Dokumenten sind keine Regeln angegeben, die Sie erwarten sollten. Wenn Sie jedoch eine Zuordnung der Form
df.loc[...] = value
dann machen Sie Pandas vertrauen df
selbst zu verändern.
Der Grund, warum die Dokumentation über den Unterschied zwischen den Ansichten und Kopien warnt, so dass Sie
df.loc[...][...] = value
Hier kennt die Gefahr der Verwendung von Ketten Zuordnungen der Form sind, Pandas df.loc[...]
zuerst auswertet, die sein kann, eine Ansicht oder eine Kopie. Nun, wenn es eine Kopie ist, dann
df.loc[...][...] = value
ist eine Kopie eines bestimmten Teils der df
zu verändern, und hat somit keinen Einfluss auf df
selbst.Um die Verletzung zu beleidigen, ist auch der Effekt auf die Kopie verloren, da es keine Verweise auf die Kopie gibt und somit keine Möglichkeit besteht, auf die Kopie zuzugreifen, nachdem die Zuweisungsanweisung abgeschlossen ist, und (zumindest in CPython) daher bald Müll gesammelt werden.
Ich weiß nicht, von einem praktischen todsicheren a priori Art und Weise zu bestimmen, ob df.loc[...]
eine Ansicht oder eine Kopie zurückkehren wird.
Allerdings gibt es einige Faustregeln, die Ihre Intuition leiten helfen können (aber beachten Sie, dass wir hier über Implementierungsdetails sprechen, so gibt es keine Garantie, dass Pandas auf diese Weise in der Zukunft verhalten muss):
- Wenn der resultierende NDFrame nicht als Basisscheibe des zugrunde liegenden NumPy-Arrays ausgedrückt werden kann, handelt es sich wahrscheinlich um eine Kopie. Somit führt eine Auswahl von beliebigen Zeilen oder Spalten zu einer Kopie. Eine Auswahl von sequentiellen Zeilen und/oder sequenziellen Spalten (die als Slice ausgedrückt werden können) kann eine Ansicht zurückgeben.
- Wenn der resultierende NDFrame Spalten verschiedener Dtypes enthält, gibt
df.loc
wahrscheinlich erneut eine Kopie zurück.
Allerdings gibt es eine einfache Möglichkeit, zu bestimmen, ob x = df.loc[..]
eine Ansicht ist ein posteriori: Einfach sehen, ob ein Wert in x
Ändern df
auswirkt. Wenn dies der Fall ist, ist es eine Ansicht, wenn nicht, ist x
eine Kopie.
beide sind die gleichen und werden eine Ansicht – EdChum
zurückgeben und wie können Sie sagen, außer ein Pandas Jedi zu sein – user3659451
Die Dokumentation besagt, dies ist so, plus, wenn Sie etwas versuchen wie 'df [:] [['a', 'b']] = 5 'es wird eine Warnung ausgelöst – EdChum