2014-04-25 3 views
51

Ich bin verwirrt über die Regeln, die Pandas verwendet, wenn sie entscheiden, dass eine Auswahl aus einem Datenrahmen eine Kopie des ursprünglichen Datenrahmens oder eine Ansicht auf das Original ist.Welche Regeln verwenden Pandas, um eine Ansicht im Vergleich zu einer Kopie zu generieren?

Wenn ich zum Beispiel

df = pd.DataFrame(np.random.randn(8,8), columns=list('ABCDEFGH'), index=range(1,9)) 

Ich verstehe, dass ein query eine Kopie zurück, so dass so etwas wie

foo = df.query('2 < index <= 5') 
foo.loc[:,'E'] = 40 

wird keine Auswirkungen auf den ursprünglichen Datenrahmen haben, df. Ich verstehe auch, dass skalare oder Named Scheiben eine Ansicht zurückkehren, so dass Zuordnungen zu diesen, wie

df.iloc[3] = 70 

oder

df.ix[1,'B':'E'] = 222 

wird df ändern. Aber ich bin verloren, wenn es um kompliziertere Fälle geht. Zum Beispiel

df[df.C <= df.B] = 7654321 

ändert df, aber

df[df.C <= df.B].ix[:,'B':'E'] 

nicht.

Gibt es eine einfache Regel, die Pandas verwendet, die ich gerade vermisse? Was passiert in diesen speziellen Fällen? und insbesondere, wie ändere ich alle Werte (oder eine Teilmenge von Werten) in einem Datenframe, die eine bestimmte Abfrage erfüllen (wie ich im letzten Beispiel oben versuche)?


Hinweis: Dies ist nicht das gleiche wie this question ist; und ich habe the documentation gelesen, bin aber nicht davon aufgeklärt. Ich habe auch die "verwandten" Fragen zu diesem Thema gelesen, aber ich vermisse immer noch die einfache Regel, die Pandas verwendet, und wie ich sie anwenden würde - zum Beispiel, um die Werte (oder eine Teilmenge von Werten) zu ändern. in einem Datenrahmen, der eine bestimmte Abfrage erfüllt.

Antwort

51

Hier die Regeln, spätere Überschreibung:

  • Alle Operationen eine Kopie erzeugen

  • Wenn inplace=True zur Verfügung gestellt wird, wird es an Ort und Stelle modifizieren; nur einige Operationen unterstützen dies

  • Ein Indexer, der z. .loc/.ix/.iloc/.iat/.at wird gesetzt.

  • Ein Indexer, der auf ein einzelnes dtyped Objekt gelangt, ist fast immer eine Ansicht (abhängig vom Speicherlayout ist dies möglicherweise nicht der Fall, weshalb dies nicht zuverlässig ist). Dies ist hauptsächlich für die Effizienz. (Das Beispiel von oben ist für .query, dies wird immer eine Kopie als ausgewertete Rückkehr von numexpr)

  • Einen Indexer, der auf einem Mehr dtyped Objekt wird immer eine Kopie.

Ihr Beispiel von chained indexing

df[df.C <= df.B].ix[:,'B':'E'] 

ist nicht garantiert werden (und damit shoulld Sie nie dies tun).

Stattdessen tun:

df.ix[df.C <= df.B, 'B':'E'] 

wie diese schneller ist und wird immer funktionieren

Die verkettete Indizierung ist 2 separate Python-Operationen und somit nicht zuverlässig durch Pandas abgefangen werden können (Sie werden oftmals eine bekommen SettingWithCopyWarning, aber das ist auch nicht 100% nachweisbar). Die dev docs, auf die Sie hingewiesen haben, bietet eine viel umfassendere Erklärung.

+0

Das öffnete meine Augen: "Die verkettete Indizierung ist 2 separate Python-Operationen und kann daher nicht * zuverlässig * von Pandas abgefangen werden ..." Das erklärt, warum die Dinge mir unberechenbar erscheinen und warum das Experimentieren nicht funktioniert Nieder. – orome

+1

Bezüglich der 2. und 5. Regeln (um zu sehen, ob ich verstehe): Wenn ich etwas, das ich indexiert habe (zB mit '.loc'), auf die LHS einer Aufgabe setze, wird es gesetzt (2. Regel); aber die gleich scheinende Operation parfümiert in "zwei Schritten" eine mit der Indexierung auf der RHS einer Zuweisung zu einer Variablen, und eine Sekunde mit einer Zuweisung zu dieser Variable wird das Original nicht ändern, weil der erste Stamm eine Kopie (5 Regel). Ist das richtig? – orome

+0

Ist das, was passiert in meinem letzten ("nie tun") Beispiel - die erste Indizierung, [df.C <= df.B] ', erhält eine Kopie (5. Regel), während die zweite,' .ix [ :, 'B': 'E'] ', ist (irrelevant, seit der erste eine Kopie bekam) das (zweite Regel). – orome