Unterteilen und Kategorisieren von Daten¶
Kontinuierliche Daten werden häufig in Bereiche unterteilt oder auf andere Weise für die Analyse gruppiert.
Angenommen, ihr habt Daten über eine Gruppe von Personen in einer Studie, die ihr in diskrete Altersgruppen einteilen möchtet. Hierfür generieren wir uns einen Dataframe mit 250 Einträgen zwischen 0
und 99
:
[1]:
import numpy as np
import pandas as pd
ages = np.random.randint(0, 99, 250)
df = pd.DataFrame({"Age": ages})
df
[1]:
Age | |
---|---|
0 | 77 |
1 | 33 |
2 | 50 |
3 | 83 |
4 | 49 |
... | ... |
245 | 41 |
246 | 95 |
247 | 97 |
248 | 74 |
249 | 23 |
250 rows × 1 columns
Anschließend bietet uns pandas mit pandas.cut eine einfache Möglichkeit, die Ergebnisse in zehn Bereiche aufzuteilen. Um nur ganze Jahre zu erhalten, setzen wir zusätzlich precision=0
:
[2]:
cats = pd.cut(ages, 10, precision=0)
cats
[2]:
[(68.0, 78.0], (29.0, 39.0], (48.0, 58.0], (78.0, 87.0], (48.0, 58.0], ..., (39.0, 48.0], (87.0, 97.0], (87.0, 97.0], (68.0, 78.0], (19.0, 29.0]]
Length: 250
Categories (10, interval[float64, right]): [(-0.1, 10.0] < (10.0, 19.0] < (19.0, 29.0] < (29.0, 39.0] ... (58.0, 68.0] < (68.0, 78.0] < (78.0, 87.0] < (87.0, 97.0]]
Mit pandas.Categorical.categories könnt ihr euch die Kategorien anzeigen lassen:
[3]:
cats.categories
[3]:
IntervalIndex([(-0.1, 10.0], (10.0, 19.0], (19.0, 29.0], (29.0, 39.0],
(39.0, 48.0], (48.0, 58.0], (58.0, 68.0], (68.0, 78.0],
(78.0, 87.0], (87.0, 97.0]],
dtype='interval[float64, right]')
…oder auch nur eine einzelne Kategorie:
[4]:
cats.categories[0]
[4]:
Interval(-0.1, 10.0, closed='right')
Mit pandas.Categorical.codes könnt ihr euch ein Array anzeigen lassen, in dem für jeden Wert die zugehörige Kategorie angezeigt wird:
[5]:
cats.codes
[5]:
array([7, 3, 5, 8, 5, 3, 7, 5, 2, 4, 9, 4, 0, 5, 4, 8, 4, 3, 8, 9, 0, 6,
8, 6, 4, 0, 2, 0, 4, 2, 4, 8, 3, 6, 1, 5, 0, 7, 9, 8, 2, 6, 0, 1,
4, 0, 0, 8, 4, 7, 7, 6, 9, 5, 6, 7, 5, 8, 6, 1, 3, 8, 8, 0, 6, 9,
2, 3, 7, 1, 6, 1, 7, 4, 1, 3, 4, 7, 5, 0, 5, 9, 7, 8, 1, 9, 9, 6,
5, 2, 0, 8, 9, 8, 9, 8, 9, 6, 3, 6, 3, 4, 6, 9, 7, 4, 3, 9, 5, 9,
2, 2, 8, 4, 4, 0, 3, 9, 8, 6, 6, 9, 0, 6, 3, 1, 8, 6, 5, 4, 8, 1,
2, 4, 9, 9, 0, 6, 6, 8, 5, 8, 6, 2, 2, 9, 2, 8, 9, 7, 6, 6, 2, 1,
5, 7, 7, 0, 1, 8, 4, 9, 9, 4, 7, 8, 7, 2, 3, 5, 4, 8, 3, 6, 2, 9,
2, 9, 3, 5, 1, 2, 8, 6, 2, 0, 7, 3, 2, 1, 8, 1, 3, 2, 6, 6, 6, 5,
9, 3, 8, 8, 9, 3, 9, 8, 3, 7, 2, 9, 6, 6, 1, 9, 8, 4, 8, 0, 6, 8,
4, 2, 1, 9, 8, 1, 6, 4, 5, 7, 7, 8, 1, 3, 4, 6, 2, 1, 9, 3, 9, 3,
3, 9, 9, 4, 9, 9, 7, 2], dtype=int8)
Mit value_counts
können wir uns nun anschauen, wie sich die Anzahl auf die einzelnen Bereiche verteilt:
[6]:
pd.Series(cats).value_counts()
[6]:
(87.0, 97.0] 36
(78.0, 87.0] 34
(58.0, 68.0] 32
(39.0, 48.0] 25
(19.0, 29.0] 24
(29.0, 39.0] 24
(68.0, 78.0] 21
(10.0, 19.0] 19
(48.0, 58.0] 18
(-0.1, 10.0] 17
Name: count, dtype: int64
Auffalend ist, dass die Altersbereiche nicht gleich viele Jahre enthalten, sondern mit 20.0, 29.0
und 69.0, 78.0
zwei Bereiche nur 9 Jahre umfassen. Dies hängt damit zusammen, dass der Altersumfang nur von 0
bis 98
reicht:
[7]:
df.min()
[7]:
Age 0
dtype: int64
[8]:
df.max()
[8]:
Age 97
dtype: int64
Mit pandas.qcut wird die Menge hingegen in Bereiche unterteilt, die annähernd gleich groß sind:
[9]:
cats = pd.qcut(ages, 10, precision=0)
[10]:
pd.Series(cats).value_counts()
[10]:
(-1.0, 14.0] 27
(14.0, 26.0] 27
(58.0, 65.0] 26
(75.0, 84.0] 26
(84.0, 90.0] 26
(26.0, 34.0] 25
(65.0, 75.0] 24
(34.0, 45.0] 23
(45.0, 58.0] 23
(90.0, 97.0] 23
Name: count, dtype: int64
Wollen wir gewährleisten, dass jede Altersgruppe tatsächlich genau zehn Jahre umfasst, können wir dies mit pandas.Categorical direkt angeben:
[11]:
age_groups = ["{0} - {1}".format(i, i + 9) for i in range(0, 109, 10)]
cats = pd.Categorical(age_groups)
cats.categories
[11]:
Index(['0 - 9', '10 - 19', '100 - 109', '20 - 29', '30 - 39', '40 - 49',
'50 - 59', '60 - 69', '70 - 79', '80 - 89', '90 - 99'],
dtype='object')
Für die Gruppierung wird nun pandas.cut verwendet:
[12]:
df["Age group"] = pd.cut(df.Age, range(0, 111, 10), right=False, labels=cats)
df
[12]:
Age | Age group | |
---|---|---|
0 | 77 | 70 - 79 |
1 | 33 | 30 - 39 |
2 | 50 | 50 - 59 |
3 | 83 | 80 - 89 |
4 | 49 | 40 - 49 |
... | ... | ... |
245 | 41 | 40 - 49 |
246 | 95 | 90 - 99 |
247 | 97 | 90 - 99 |
248 | 74 | 70 - 79 |
249 | 23 | 20 - 29 |
250 rows × 2 columns