Daten auswählen und filtern#
Die Indizierung von Serien (obj[...])
funktioniert analog zur Indizierung von NumPy-Arrays, außer dass ihr Indexwerte der Serie statt nur Ganzzahlen verwenden könnt. Hier sind einige Beispiele dafür:
[1]:
import numpy as np
import pandas as pd
[2]:
idx = pd.date_range("2022-02-02", periods=7)
s = pd.Series(np.random.randn(7), index=idx)
[3]:
s
[3]:
2022-02-02 0.667979
2022-02-03 -1.263329
2022-02-04 2.526744
2022-02-05 -0.254690
2022-02-06 -0.057510
2022-02-07 1.543061
2022-02-08 -0.124643
Freq: D, dtype: float64
[4]:
s['2022-02-03']
[4]:
-1.2633292233510218
[5]:
s[1]
[5]:
-1.2633292233510218
[6]:
s[2:4]
[6]:
2022-02-04 2.526744
2022-02-05 -0.254690
Freq: D, dtype: float64
[7]:
s[['2022-02-04', '2022-02-03', '2022-02-02']]
[7]:
2022-02-04 2.526744
2022-02-03 -1.263329
2022-02-02 0.667979
dtype: float64
[8]:
s[[1, 3]]
[8]:
2022-02-03 -1.263329
2022-02-05 -0.254690
Freq: 2D, dtype: float64
[9]:
s[s > 0]
[9]:
2022-02-02 0.667979
2022-02-04 2.526744
2022-02-07 1.543061
dtype: float64
Zwar könnt ihr auf diese Weise Daten nach Label auswählen, doch die bevorzugte Methode zur Auswahl von Indexwerten ist der loc
-Operator:
[10]:
s.loc[['2022-02-04', '2022-02-03', '2022-02-02']]
[10]:
2022-02-04 2.526744
2022-02-03 -1.263329
2022-02-02 0.667979
dtype: float64
Der Grund für die Bevorzugung von loc
liegt in der unterschiedlichen Behandlung von Ganzzahlen bei der Indexierung mit []
. Bei der regulären []
-basierten Indizierung werden Ganzzahlen als Label behandelt, wenn der Index Ganzzahlen enthält, so dass das Verhalten je nach Datentyp des Index unterschiedlich ist. In unserem Beispiel wird der Ausdruck s.loc[[3, 2, 1]]
fehlschlagen, da der Index keine ganzen Zahlen enthält:
[11]:
s.loc[[3, 2, 1]]
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
/tmp/ipykernel_27238/2224307995.py in <module>
----> 1 s.loc[[3, 2, 1]]
~/spack/var/spack/environments/python-38/.spack-env/view/lib/python3.8/site-packages/pandas/core/indexing.py in __getitem__(self, key)
929
930 maybe_callable = com.apply_if_callable(key, self.obj)
--> 931 return self._getitem_axis(maybe_callable, axis=axis)
932
933 def _is_scalar_access(self, key: tuple):
~/spack/var/spack/environments/python-38/.spack-env/view/lib/python3.8/site-packages/pandas/core/indexing.py in _getitem_axis(self, key, axis)
1151 raise ValueError("Cannot index with multidimensional key")
1152
-> 1153 return self._getitem_iterable(key, axis=axis)
1154
1155 # nested tuple slicing
~/spack/var/spack/environments/python-38/.spack-env/view/lib/python3.8/site-packages/pandas/core/indexing.py in _getitem_iterable(self, key, axis)
1091
1092 # A collection of keys
-> 1093 keyarr, indexer = self._get_listlike_indexer(key, axis)
1094 return self.obj._reindex_with_indexers(
1095 {axis: [keyarr, indexer]}, copy=True, allow_dups=True
~/spack/var/spack/environments/python-38/.spack-env/view/lib/python3.8/site-packages/pandas/core/indexing.py in _get_listlike_indexer(self, key, axis)
1312 keyarr, indexer, new_indexer = ax._reindex_non_unique(keyarr)
1313
-> 1314 self._validate_read_indexer(keyarr, indexer, axis)
1315
1316 if needs_i8_conversion(ax.dtype) or isinstance(
~/spack/var/spack/environments/python-38/.spack-env/view/lib/python3.8/site-packages/pandas/core/indexing.py in _validate_read_indexer(self, key, indexer, axis)
1372 if use_interval_msg:
1373 key = list(key)
-> 1374 raise KeyError(f"None of [{key}] are in the [{axis_name}]")
1375
1376 not_found = list(ensure_index(key)[missing_mask.nonzero()[0]].unique())
KeyError: "None of [Int64Index([3, 2, 1], dtype='int64')] are in the [index]"
Während der loc
-Operator ausschließlich Label indiziert, indiziert der iloc
-Operator ausschließlich mit ganzen Zahlen:
[12]:
s.iloc[[3, 2, 1]]
[12]:
2022-02-05 -0.254690
2022-02-04 2.526744
2022-02-03 -1.263329
Freq: -1D, dtype: float64
Ihr könnt auch mit Labels slicen, aber das funktioniert anders als das normale Python-Slicing, da der Endpunkt inklusive ist:
[13]:
s.loc['2022-02-03':'2022-02-04']
[13]:
2022-02-03 -1.263329
2022-02-04 2.526744
Freq: D, dtype: float64
Durch die Einstellung mit diesen Methoden wird der entsprechende Abschnitt der Reihe geändert:
[14]:
s.loc['2022-02-03':'2022-02-04'] = 0
s
[14]:
2022-02-02 0.667979
2022-02-03 0.000000
2022-02-04 0.000000
2022-02-05 -0.254690
2022-02-06 -0.057510
2022-02-07 1.543061
2022-02-08 -0.124643
Freq: D, dtype: float64
Die Indizierung in einem DataFrame dient dazu, eine oder mehrere Spalten entweder mit einem einzelnen Wert oder einer Folge abzurufen:
[15]:
data = {'Code': ['U+0000', 'U+0001', 'U+0002', 'U+0003', 'U+0004', 'U+0005'],
'Decimal': [0, 1, 2, 3, 4, 5],
'Octal': ['001', '002', '003', '004', '004', '005'],
'Key': ['NUL', 'Ctrl-A', 'Ctrl-B', 'Ctrl-C', 'Ctrl-D', 'Ctrl-E']}
df = pd.DataFrame(data)
df = pd.DataFrame(data,
columns=['Decimal', 'Octal', 'Key'],
index=df['Code'])
df
[15]:
Decimal | Octal | Key | |
---|---|---|---|
Code | |||
U+0000 | 0 | 001 | NUL |
U+0001 | 1 | 002 | Ctrl-A |
U+0002 | 2 | 003 | Ctrl-B |
U+0003 | 3 | 004 | Ctrl-C |
U+0004 | 4 | 004 | Ctrl-D |
U+0005 | 5 | 005 | Ctrl-E |
[16]:
df['Key']
[16]:
Code
U+0000 NUL
U+0001 Ctrl-A
U+0002 Ctrl-B
U+0003 Ctrl-C
U+0004 Ctrl-D
U+0005 Ctrl-E
Name: Key, dtype: object
[17]:
df[['Decimal', 'Key']]
[17]:
Decimal | Key | |
---|---|---|
Code | ||
U+0000 | 0 | NUL |
U+0001 | 1 | Ctrl-A |
U+0002 | 2 | Ctrl-B |
U+0003 | 3 | Ctrl-C |
U+0004 | 4 | Ctrl-D |
U+0005 | 5 | Ctrl-E |
[18]:
df[:2]
[18]:
Decimal | Octal | Key | |
---|---|---|---|
Code | |||
U+0000 | 0 | 001 | NUL |
U+0001 | 1 | 002 | Ctrl-A |
[19]:
df[df['Decimal'] > 2]
[19]:
Decimal | Octal | Key | |
---|---|---|---|
Code | |||
U+0003 | 3 | 004 | Ctrl-C |
U+0004 | 4 | 004 | Ctrl-D |
U+0005 | 5 | 005 | Ctrl-E |
Die Zeilenauswahlsyntax df[:2]
wird aus Gründen der Bequemlichkeit bereitgestellt. Durch die Übergabe eines einzelnen Elements oder einer Liste an den []
-Operator werden Spalten ausgewählt.
Ein weiterer Anwendungsfall ist die Indizierung mit einem booleschen DataFrame, der beispielsweise durch einen Skalarvergleich erzeugt wird:
[20]:
df['Decimal'] > 2
[20]:
Code
U+0000 False
U+0001 False
U+0002 False
U+0003 True
U+0004 True
U+0005 True
Name: Decimal, dtype: bool
[21]:
df[df['Decimal'] > 2] = 'NA'
df
[21]:
Decimal | Octal | Key | |
---|---|---|---|
Code | |||
U+0000 | 0 | 001 | NUL |
U+0001 | 1 | 002 | Ctrl-A |
U+0002 | 2 | 003 | Ctrl-B |
U+0003 | NA | NA | NA |
U+0004 | NA | NA | NA |
U+0005 | NA | NA | NA |
Wie Series verfügt auch DataFrame über spezielle Operatoren loc
und iloc
für label-basierte bzw. ganzzahlige Indizierung. Da DataFrame zweidimensional ist, könnt ihr eine Teilmenge der Zeilen und Spalten mit NumPy-ähnlicher Notation auswählen, indem ihr entweder Achsenbeschriftungen (loc
) oder Ganzzahlen (iloc
) verwendet.
[22]:
df.loc['U+0002', ['Decimal', 'Key']]
[22]:
Decimal 2
Key Ctrl-B
Name: U+0002, dtype: object
[23]:
df.iloc[[2], [1, 2]]
[23]:
Octal | Key | |
---|---|---|
Code | ||
U+0002 | 003 | Ctrl-B |
[24]:
df.iloc[[0, 1], [1, 2]]
[24]:
Octal | Key | |
---|---|---|
Code | ||
U+0000 | 001 | NUL |
U+0001 | 002 | Ctrl-A |
Beide Indizierungsfunktionen arbeiten mit Slices zusätzlich zu einzelnen Label oder Listen von Label:
[25]:
df.loc[:'U+0003', 'Key']
[25]:
Code
U+0000 NUL
U+0001 Ctrl-A
U+0002 Ctrl-B
U+0003 NA
Name: Key, dtype: object
[26]:
df.iloc[:3, :3]
[26]:
Decimal | Octal | Key | |
---|---|---|---|
Code | |||
U+0000 | 0 | 001 | NUL |
U+0001 | 1 | 002 | Ctrl-A |
U+0002 | 2 | 003 | Ctrl-B |
Es gibt also viele Möglichkeiten, die in einem pandas-Objekt enthaltenen Daten auszuwählen und neu anzuordnen. Im folgenden stelle ich für DataFrames eine kurze Zusammenfassung der meisten dieser Möglichkeiten zusammen:
Typ |
Hinweis |
---|---|
|
wählt eine einzelne Spalte oder eine Folge von Spalten aus dem DataFrame aus |
|
wählt eine einzelne Zeile oder eine Teilmenge von Zeilen aus dem DataFrame nach Label aus |
|
wählt eine einzelne Spalte oder eine Teilmenge von Spalten nach dem Label aus |
|
wählt sowohl Zeilen als auch Spalten nach dem Label aus |
|
wählt eine einzelne Zeile oder eine Teilmenge von Zeilen aus dem DataFrame anhand der Ganzzahlposition aus |
|
Wählt eine einzelne Spalte oder eine Teilmenge von Spalten anhand einer ganzzahligen Position aus |
|
wählt einen Einzelwert nach Zeilen- und Spaltenbezeichnung aus |
|
wählt einen Einzelwert nach Zeilen- und Spaltenposition (Ganzzahlen) aus |
|
wählt Zeilen oder Spalten nach Labels aus |
|
veraltet seit Version 0.21.0: Verwendet stattdessen |