it-swarm.com.de

Wie unterscheiden sich iloc, ix und loc?

Kann jemand erklären, wie sich diese drei Schneidemethoden unterscheiden?
Ich habe gesehen die Dokumente und ich habe gesehen dieseAntworten , aber ich finde mich immer noch nicht in der Lage zu erklären, wie Die drei sind unterschiedlich. Für mich scheinen sie größtenteils austauschbar zu sein, weil sie sich auf der unteren Ebene des Schneidens befinden.

Angenommen, wir möchten die ersten fünf Zeilen eines DataFrame abrufen. Wie kommt es, dass alle drei funktionieren?

df.loc[:5]
df.ix[:5]
df.iloc[:5]

Kann jemand drei Fälle vorstellen, in denen die Unterscheidung in der Verwendung klarer ist?

535
AZhao

Hinweis: In pandas Version 0.20.0 und höher ist ixveraltet und die Verwendung von loc und iloc wird stattdessen empfohlen. Ich habe die Teile dieser Antwort, die ix beschreiben, als Referenz für Benutzer früherer Versionen von Pandas intakt gelassen. Unten wurden Beispiele hinzugefügt, die Alternativen zu ix zeigen.


Hier ist zunächst eine Zusammenfassung der drei Methoden:

  • loc ruft Zeilen (oder Spalten) mit bestimmten Bezeichnungen aus dem Index ab.
  • iloc ruft Zeilen (oder Spalten) an bestimmten Positionen im Index ab (es werden also nur ganze Zahlen verwendet).
  • ix versucht normalerweise, sich wie loc zu verhalten, greift jedoch auf das Verhalten von iloc zurück, wenn keine Bezeichnung im Index vorhanden ist.

Es ist wichtig, einige Feinheiten zu beachten, die die Verwendung von ix etwas schwierig machen können:

  • wenn der Index vom Typ Integer ist, verwendet ix nur die kennsatzbasierte Indizierung und greift nicht auf die positionsbasierte Indizierung zurück. Befindet sich die Bezeichnung nicht im Index, wird ein Fehler ausgelöst.

  • wenn der Index keine nur Ganzzahlen enthält, verwendet ix bei Angabe einer Ganzzahl sofort eine positionsbasierte Indexierung anstelle einer kennsatzbasierten Indexierung . Wenn jedoch ix einen anderen Typ (z. B. eine Zeichenfolge) erhält, kann die kennsatzbasierte Indizierung verwendet werden.


Betrachten Sie die folgenden Reihen, um die Unterschiede zwischen den drei Methoden zu veranschaulichen:

>>> s = pd.Series(np.nan, index=[49,48,47,46,45, 1, 2, 3, 4, 5])
>>> s
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN
4    NaN
5    NaN

Wir werden uns mit dem Integerwert 3 befassen.

In diesem Fall gibt s.iloc[:3] die ersten 3 Zeilen zurück (da 3 als Position behandelt wird) und s.loc[:3] die ersten 8 Zeilen zurück (da 3 als Bezeichnung behandelt wird):

>>> s.iloc[:3] # slice the first three rows
49   NaN
48   NaN
47   NaN

>>> s.loc[:3] # slice up to and including label 3
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN

>>> s.ix[:3] # the integer is in the index so s.ix[:3] works like loc
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN

Beachten Sie, dass s.ix[:3] dieselbe Serie wie s.loc[:3] zurückgibt, da zuerst nach dem Label gesucht wird, anstatt an der Position zu arbeiten (und der Index für s vom Typ Integer ist).

Was ist, wenn wir es mit einer Ganzzahl versuchen, die nicht im Index enthalten ist (sagen Sie 6)?

Hier gibt s.iloc[:6] die ersten 6 Zeilen der Serie wie erwartet zurück. s.loc[:6] löst jedoch einen KeyError aus, da 6 nicht im Index enthalten ist.

>>> s.iloc[:6]
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN

>>> s.loc[:6]
KeyError: 6

>>> s.ix[:6]
KeyError: 6

Gemäß den oben genannten Feinheiten löst s.ix[:6] jetzt einen KeyError aus, da versucht wird, wie loc zu arbeiten, jedoch kein 6 im Index gefunden wird. Da unser Index vom Integer-Typ ix ist, verhält er sich nicht wie iloc.

Wenn jedoch unser Index vom gemischten Typ wäre, würde sich eine gegebene Ganzzahl ix sofort wie iloc verhalten, anstatt einen KeyError auszulösen:

>>> s2 = pd.Series(np.nan, index=['a','b','c','d','e', 1, 2, 3, 4, 5])
>>> s2.index.is_mixed() # index is mix of different types
True
>>> s2.ix[:6] # now behaves like iloc given integer
a   NaN
b   NaN
c   NaN
d   NaN
e   NaN
1   NaN

Denken Sie daran, dass ix immer noch Nicht-Ganzzahlen akzeptieren und sich wie loc verhalten kann:

>>> s2.ix[:'c'] # behaves like loc given non-integer
a   NaN
b   NaN
c   NaN

Wenn Sie nur mit Beschriftungen oder nur mit ganzzahligen Positionen indizieren, halten Sie sich an loc oder iloc, um unerwartete Ergebnisse zu vermeiden. Verwenden Sie ix nicht.


Kombinieren von positionsbasierter und kennsatzbasierter Indizierung

Manchmal möchten Sie bei einem DataFrame die Indizierungsmethoden für Beschriftung und Position für die Zeilen und Spalten mischen.

Betrachten Sie beispielsweise den folgenden DataFrame. Wie schneidet man die Zeilen am besten bis einschließlich 'c' auf und nimmt die ersten vier Spalten?

>>> df = pd.DataFrame(np.nan, 
                      index=list('abcde'),
                      columns=['x','y','z', 8, 9])
>>> df
    x   y   z   8   9
a NaN NaN NaN NaN NaN
b NaN NaN NaN NaN NaN
c NaN NaN NaN NaN NaN
d NaN NaN NaN NaN NaN
e NaN NaN NaN NaN NaN

In früheren Versionen von pandas (vor 0.20.0) ix können Sie dies ganz ordentlich tun - wir können die Zeilen nach Beschriftung und die Spalten nach Position aufteilen (beachten Sie, dass für die Spalten ix verwendet standardmäßig positionsbasiertes Slicing, da 4 kein Spaltenname ist.):

>>> df.ix[:'c', :4]
    x   y   z   8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN

In späteren Versionen von Pandas können wir dieses Ergebnis mit iloc und der Hilfe einer anderen Methode erzielen:

>>> df.iloc[:df.index.get_loc('c') + 1, :4]
    x   y   z   8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN

get_loc() ist eine Indexmethode, die "Position des Etiketts in diesem Index ermitteln" bedeutet. Beachten Sie, dass beim Schneiden mit iloc der Endpunkt nicht berücksichtigt wird. Daher müssen wir diesem Wert 1 hinzufügen, wenn wir auch die Zeile 'c' verwenden möchten.

Es gibt weitere Beispiele in der Dokumentation von Pandas hier .

820
Alex Riley

iloc basiert auf der Ganzzahlpositionierung. So können Sie unabhängig von den Zeilenbezeichnungen immer beispielsweise die erste Zeile abrufen

df.iloc[0]

oder die letzten fünf Zeilen durch

df.iloc[-5:]

Sie können es auch für die Spalten verwenden. Dies ruft die 3. Spalte ab:

df.iloc[:, 2]    # the : in the first position indicates all rows

Sie können sie kombinieren, um Schnittpunkte von Zeilen und Spalten zu erhalten:

df.iloc[:3, :3] # The upper-left 3 X 3 entries (assuming df has 3+ rows and columns)

Andererseits verwendet .loc benannte Indizes. Richten wir einen Datenrahmen mit Zeichenfolgen als Zeilen- und Spaltenbeschriftung ein:

df = pd.DataFrame(index=['a', 'b', 'c'], columns=['time', 'date', 'name'])

Dann können wir die erste Reihe durch bekommen

df.loc['a']     # equivalent to df.iloc[0]

und die zweiten beiden Zeilen der Spalte 'date' von

df.loc['b':, 'date']   # equivalent to df.iloc[1:, 1]

und so weiter. Es ist wahrscheinlich erwähnenswert, dass die standardmäßigen Zeilen- und Spaltenindizes für DataFrame Ganzzahlen von 0 sind und in diesem Fall iloc und loc auf dieselbe Weise funktionieren würden. Deshalb sind Ihre drei Beispiele äquivalent. Wenn Sie einen nicht numerischen Index wie Zeichenfolgen oder Datumsangaben hättendf.loc[:5]würde einen Fehler auslösen.

Sie können den Spaltenabruf auch einfach mit dem __getitem__ des Datenrahmens durchführen:

df['time']    # equivalent to df.loc[:, 'time']

Angenommen, Sie möchten Positions- und benannte Indizierung mischen, d. H. Indizierung mit Namen in Zeilen und Positionen in Spalten (um dies zu verdeutlichen, wählen Sie aus unserem Datenrahmen aus, anstatt einen Datenrahmen mit Zeichenfolgen im Zeilenindex und Ganzzahlen in zu erstellen den Spaltenindex). Hier kommt .ix ins Spiel:

df.ix[:2, 'time']    # the first two rows of the 'time' column

Ich denke, es ist auch erwähnenswert, dass Sie boolesche Vektoren auch an die loc -Methode übergeben können. Zum Beispiel:

 b = [True, False, True]
 df.loc[b] 

Gibt die erste und dritte Reihe von df zurück. Dies entspricht df[b] für die Auswahl, kann jedoch auch für die Zuweisung über Boolesche Vektoren verwendet werden:

df.loc[b, 'name'] = 'Mary', 'John'
115
JoeCondron

Meiner Meinung nach ist die akzeptierte Antwort verwirrend, da ein DataFrame mit nur fehlenden Werten verwendet wird. Ich mag auch den Begriff positionsbasiert ​​für .iloc nicht und bevorzuge stattdessen ganzzahlige Position, da er viel aussagekräftiger ist und genau das ist, was .iloc steht für. Das Schlüsselwort ist INTEGER - .iloc braucht INTEGERS.

Weitere Informationen finden Sie in meinem äußerst detaillierten Blogserie zur Auswahl von Teilmengen


.ix ist veraltet und mehrdeutig und sollte niemals verwendet werden

Da .ix veraltet ist, konzentrieren wir uns nur auf die Unterschiede zwischen .loc und .iloc.

Bevor wir auf die Unterschiede eingehen, sollten Sie wissen, dass DataFrames über Bezeichnungen verfügen, mit denen sich jede Spalte und jeder Index identifizieren lässt. Schauen wir uns ein Beispiel für einen DataFrame an:

df = pd.DataFrame({'age':[30, 2, 12, 4, 32, 33, 69],
                   'color':['blue', 'green', 'red', 'white', 'gray', 'black', 'red'],
                   'food':['Steak', 'Lamb', 'Mango', 'Apple', 'Cheese', 'Melon', 'Beans'],
                   'height':[165, 70, 120, 80, 180, 172, 150],
                   'score':[4.6, 8.3, 9.0, 3.3, 1.8, 9.5, 2.2],
                   'state':['NY', 'TX', 'FL', 'AL', 'AK', 'TX', 'TX']
                   },
                  index=['Jane', 'Nick', 'Aaron', 'Penelope', 'Dean', 'Christina', 'Cornelia'])

enter image description here

Alle Wörter in fett ​​sind die Bezeichnungen. Die Bezeichnungen age, color, food, height, score und state werden für die Spalten verwendet. Die anderen Bezeichnungen Jane, Nick, Aaron, Penelope, Dean, Christina, Cornelia werden für index verwendet.


Die wichtigsten Methoden zum Auswählen bestimmter Zeilen in einem DataFrame sind die Indexer .loc und .iloc. Jeder dieser Indexer kann auch zum gleichzeitigen Auswählen von Spalten verwendet werden, es ist jedoch einfacher, sich vorerst nur auf Zeilen zu konzentrieren. Außerdem verwendet jeder der Indexer eine Reihe von Klammern, die unmittelbar hinter dem Namen stehen, um eine Auswahl zu treffen.

.loc wählt Daten nur anhand von Beschriftungen aus

Wir werden zuerst über den Indexer .loc sprechen, der nur Daten anhand der Index- oder Spaltenbezeichnungen auswählt. In unserem DataFrame-Beispiel haben wir aussagekräftige Namen als Werte für den Index angegeben. Viele DataFrames haben keine aussagekräftigen Namen und verwenden stattdessen standardmäßig nur die Ganzzahlen von 0 bis n-1, wobei n die Länge des DataFrames ist.

Es gibt drei verschiedene Eingänge, die Sie für .loc verwenden können.

  • Ein Faden
  • Eine Liste von Zeichenfolgen
  • Slice-Notation mit Strings als Start- und Stoppwert

Auswahl einer einzelnen Zeile mit .loc mit einem String

Um eine einzelne Datenzeile auszuwählen, platzieren Sie die Indexbezeichnung in den Klammern nach .loc.

df.loc['Penelope']

Dies gibt die Datenzeile als Serie zurück

age           4
color     white
food      Apple
height       80
score       3.3
state        AL
Name: Penelope, dtype: object

Auswählen mehrerer Zeilen mit .loc mit einer Liste von Zeichenfolgen

df.loc[['Cornelia', 'Jane', 'Dean']]

Dies gibt einen DataFrame mit den Zeilen in der in der Liste angegebenen Reihenfolge zurück:

enter image description here

Auswählen mehrerer Zeilen mit .loc in Slice-Notation

Die Slice-Notation wird durch Start-, Stopp- und Schrittwerte definiert. Beim Schneiden nach Etikett bezieht pandas den Stoppwert in die Rückgabe ein. Die folgenden Slices von Aaron bis Dean inklusive. Die Schrittgröße ist nicht explizit definiert, sondern standardmäßig auf 1 festgelegt.

df.loc['Aaron':'Dean']

enter image description here

Komplexe Slices können auf dieselbe Weise aufgenommen werden wie Listen mit Python.

.iloc wählt Daten nur nach ganzzahliger Position aus

Wenden wir uns nun .iloc zu. Jede Datenzeile und -spalte in einem DataFrame hat eine ganzzahlige Position, die sie definiert. Dies ist zusätzlich zu der Beschriftung, die in der Ausgabe angezeigt wird . Die Ganzzahlposition ist einfach die Anzahl der Zeilen/Spalten von oben/links beginnend bei 0.

Es gibt drei verschiedene Eingänge, die Sie für .iloc verwenden können.

  • Eine ganze Zahl
  • Eine Liste von ganzen Zahlen
  • Slice-Notation mit Ganzzahlen als Start- und Stoppwert

Auswahl einer einzelnen Zeile mit .iloc mit einer ganzen Zahl

df.iloc[4]

Dies gibt die 5. Zeile (ganzzahlige Position 4) als eine Reihe zurück

age           32
color       gray
food      Cheese
height       180
score        1.8
state         AK
Name: Dean, dtype: object

Mehrere Zeilen mit .iloc mit einer Liste von ganzen Zahlen auswählen

df.iloc[[2, -2]]

Dies gibt einen DataFrame der dritten und vorletzten Zeile zurück:

enter image description here

Auswählen mehrerer Zeilen mit .iloc in Slice-Notation

df.iloc[:5:3]

enter image description here


Gleichzeitige Auswahl von Zeilen und Spalten mit .loc und .iloc

Eine ausgezeichnete Fähigkeit von beiden .loc/.iloc ist ihre Fähigkeit, sowohl Zeilen als auch Spalten gleichzeitig auszuwählen. In den obigen Beispielen wurden alle Spalten aus jeder Auswahl zurückgegeben. Wir können Spalten mit denselben Eingabetypen wie für Zeilen auswählen. Wir müssen einfach die Zeilen- und Spaltenauswahl mit einem Komma trennen.

Zum Beispiel können wir die Zeilen Jane und Dean mit nur den Spalten height, score und state wie folgt auswählen:

df.loc[['Jane', 'Dean'], 'height':]

enter image description here

Dies verwendet eine Liste von Beschriftungen für die Zeilen und eine Slice-Notation für die Spalten

Wir können natürlich ähnliche Operationen mit .iloc ausführen, indem wir nur ganze Zahlen verwenden.

df.iloc[[1,4], 2]
Nick      Lamb
Dean    Cheese
Name: food, dtype: object

Gleichzeitige Auswahl mit Bezeichnungen und ganzzahliger Position

.ix wurde verwendet, um eine Auswahl gleichzeitig mit Beschriftungen und einer Ganzzahlposition zu treffen, was nützlich, aber manchmal verwirrend und mehrdeutig war und zum Glück veraltet war. Für den Fall, dass Sie eine Auswahl mit einer Mischung aus Beschriftungen und Ganzzahlpositionen treffen müssen, müssen Sie beide Beschriftungen oder Ganzzahlpositionen auswählen.

Wenn Sie beispielsweise die Zeilen Nick und Cornelia zusammen mit den Spalten 2 und 4 auswählen möchten, können Sie .loc verwenden, indem Sie die Ganzzahlen in Bezeichnungen mit den folgenden Werten konvertieren:

col_names = df.columns[[2, 4]]
df.loc[['Nick', 'Cornelia'], col_names] 

Alternativ können Sie die Indexbeschriftungen mit der Indexmethode get_loc in Ganzzahlen konvertieren.

labels = ['Nick', 'Cornelia']
index_ints = [df.index.get_loc(label) for label in labels]
df.iloc[index_ints, [2, 4]]

Boolesche Auswahl

Der .loc-Indexer kann auch eine Boolesche Auswahl vornehmen. Wenn wir beispielsweise alle Zeilen mit einem Alter von mehr als 30 Jahren finden und nur die Spalten food und score zurückgeben möchten, können wir Folgendes tun:

df.loc[df['age'] > 30, ['food', 'score']] 

Sie können dies mit .iloc replizieren, es kann jedoch keine Boolesche Reihe übergeben werden. Sie müssen die Boolesche Reihe in ein Numpy-Array wie folgt konvertieren:

df.iloc[(df['age'] > 30).values, [2, 4]] 

Auswahl aller Zeilen

Es ist möglich, .loc/.iloc nur für die Spaltenauswahl zu verwenden. Sie können alle Zeilen mit einem Doppelpunkt wie folgt auswählen:

df.loc[:, 'color':'score':2]

enter image description here


Der Indizierungsoperator [] kann auch Zeilen und Spalten auswählen, jedoch nicht gleichzeitig.

Die meisten Benutzer kennen den Hauptzweck des DataFrame-Indizierungsoperators, nämlich die Auswahl von Spalten. Eine Zeichenfolge wählt eine einzelne Spalte als Serie aus, und eine Liste von Zeichenfolgen wählt mehrere Spalten als DataFrame aus.

df['food']

Jane          Steak
Nick           Lamb
Aaron         Mango
Penelope      Apple
Dean         Cheese
Christina     Melon
Cornelia      Beans
Name: food, dtype: object

Wenn Sie eine Liste verwenden, werden mehrere Spalten ausgewählt

df[['food', 'score']]

enter image description here

Weniger bekannt ist, dass bei Verwendung der Slice-Notation die Auswahl nach Zeilenbezeichnungen oder nach ganzzahliger Position erfolgt. Das ist sehr verwirrend und etwas, das ich fast nie benutze, aber es funktioniert.

df['Penelope':'Christina'] # slice rows by label

enter image description here

df[2:6:2] # slice rows by integer location

enter image description here

Die explizite Angabe von .loc/.iloc für die Auswahl von Zeilen wird sehr bevorzugt. Der Indizierungsoperator allein kann nicht gleichzeitig Zeilen und Spalten auswählen.

df[3:5, 'color']
TypeError: unhashable type: 'slice'
95
Ted Petrou