pandas
Grupowanie danych
Szukaj…
Podstawowe grupowanie
Grupuj według jednej kolumny
Korzystanie z następujących DataFrame
df = pd.DataFrame({'A': ['a', 'b', 'c', 'a', 'b', 'b'],
'B': [2, 8, 1, 4, 3, 8],
'C': [102, 98, 107, 104, 115, 87]})
df
# Output:
# A B C
# 0 a 2 102
# 1 b 8 98
# 2 c 1 107
# 3 a 4 104
# 4 b 3 115
# 5 b 8 87
Grupuj według kolumny A i uzyskaj średnią wartość z innych kolumn:
df.groupby('A').mean()
# Output:
# B C
# A
# a 3.000000 103
# b 6.333333 100
# c 1.000000 107
Grupuj według wielu kolumn
df.groupby(['A','B']).mean()
# Output:
# C
# A B
# a 2 102.0
# 4 104.0
# b 3 115.0
# 8 92.5
# c 1 107.0
Zauważ, jak po zgrupowaniu każdy wiersz w wynikowej ramce DataFrame jest indeksowany przez krotkę lub MultiIndex (w tym przypadku parę elementów z kolumn A i B).
Aby zastosować kilka metod agregacji jednocześnie, na przykład policzyć liczbę elementów w każdej grupie i obliczyć ich średnią, użyj funkcji agg
:
df.groupby(['A','B']).agg(['count', 'mean'])
# Output:
# C
# count mean
# A B
# a 2 1 102.0
# 4 1 104.0
# b 3 1 115.0
# 8 2 92.5
# c 1 1 107.0
Grupowanie liczb
Dla następujących DataFrame:
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame({'Age': np.random.randint(20, 70, 100),
'Sex': np.random.choice(['Male', 'Female'], 100),
'number_of_foo': np.random.randint(1, 20, 100)})
df.head()
# Output:
# Age Sex number_of_foo
# 0 64 Female 14
# 1 67 Female 14
# 2 20 Female 12
# 3 23 Male 17
# 4 23 Female 15
Grupuj Age
w trzy kategorie (lub pojemniki). Pojemniki można podać jako
- liczba całkowita
n
wskazująca liczbę przedziałów - w tym przypadku dane ramki danych są podzielone nan
przedziałów o równej wielkości - sekwencja liczb całkowitych oznaczających punkt końcowy przedziałów lewych otwartych, w których dane są podzielone na - na przykład przedziały
bins=[19, 40, 65, np.inf]
tworzy trzy grupy wiekowe(19, 40]
,(40, 65]
i(65, np.inf]
.
Pandy automatycznie przypisują ciąg znaków wersji przedziałów jako etykietę. Możliwe jest również definiowanie własnych etykiet poprzez zdefiniowanie parametru labels
jako listy ciągów znaków.
pd.cut(df['Age'], bins=4)
# this creates four age groups: (19.951, 32.25] < (32.25, 44.5] < (44.5, 56.75] < (56.75, 69]
Name: Age, dtype: category
Categories (4, object): [(19.951, 32.25] < (32.25, 44.5] < (44.5, 56.75] < (56.75, 69]]
pd.cut(df['Age'], bins=[19, 40, 65, np.inf])
# this creates three age groups: (19, 40], (40, 65] and (65, infinity)
Name: Age, dtype: category
Categories (3, object): [(19, 40] < (40, 65] < (65, inf]]
Użyj go w groupby
aby uzyskać średnią liczbę foo:
age_groups = pd.cut(df['Age'], bins=[19, 40, 65, np.inf])
df.groupby(age_groups)['number_of_foo'].mean()
# Output:
# Age
# (19, 40] 9.880000
# (40, 65] 9.452381
# (65, inf] 9.250000
# Name: number_of_foo, dtype: float64
Tabele krzyżowe grup wiekowych i płci:
pd.crosstab(age_groups, df['Sex'])
# Output:
# Sex Female Male
# Age
# (19, 40] 22 28
# (40, 65] 18 24
# (65, inf] 3 5
Wybór kolumny grupy
Kiedy tworzysz grupę, możesz wybrać pojedynczą kolumnę lub listę kolumn:
In [11]: df = pd.DataFrame([[1, 1, 2], [1, 2, 3], [2, 3, 4]], columns=["A", "B", "C"]) In [12]: df Out[12]: A B C 0 1 1 2 1 1 2 3 2 2 3 4 In [13]: g = df.groupby("A") In [14]: g["B"].mean() # just column B Out[14]: A 1 1.5 2 3.0 Name: B, dtype: float64 In [15]: g[["B", "C"]].mean() # columns B and C Out[15]: B C A 1 1.5 2.5 2 3.0 4.0
Możesz także użyć agg
aby określić kolumny i agregację, aby wykonać:
In [16]: g.agg({'B': 'mean', 'C': 'count'}) Out[16]: C B A 1 2 1.5 2 1 3.0
Agregowanie według wielkości w stosunku do liczby
Różnica między size
a count
wynosi:
size
liczy wartości NaN
, count
nie.
df = pd.DataFrame(
{"Name":["Alice", "Bob", "Mallory", "Mallory", "Bob" , "Mallory"],
"City":["Seattle", "Seattle", "Portland", "Seattle", "Seattle", "Portland"],
"Val": [4, 3, 3, np.nan, np.nan, 4]})
df
# Output:
# City Name Val
# 0 Seattle Alice 4.0
# 1 Seattle Bob 3.0
# 2 Portland Mallory 3.0
# 3 Seattle Mallory NaN
# 4 Seattle Bob NaN
# 5 Portland Mallory 4.0
df.groupby(["Name", "City"])['Val'].size().reset_index(name='Size')
# Output:
# Name City Size
# 0 Alice Seattle 1
# 1 Bob Seattle 2
# 2 Mallory Portland 2
# 3 Mallory Seattle 1
df.groupby(["Name", "City"])['Val'].count().reset_index(name='Count')
# Output:
# Name City Count
# 0 Alice Seattle 1
# 1 Bob Seattle 1
# 2 Mallory Portland 2
# 3 Mallory Seattle 0
Grupy agregujące
In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: df = pd.DataFrame({'A': list('XYZXYZXYZX'), 'B': [1, 2, 1, 3, 1, 2, 3, 3, 1, 2],
'C': [12, 14, 11, 12, 13, 14, 16, 12, 10, 19]})
In [4]: df.groupby('A')['B'].agg({'mean': np.mean, 'standard deviation': np.std})
Out[4]:
standard deviation mean
A
X 0.957427 2.250000
Y 1.000000 2.000000
Z 0.577350 1.333333
W przypadku wielu kolumn:
In [5]: df.groupby('A').agg({'B': [np.mean, np.std], 'C': [np.sum, 'count']})
Out[5]:
C B
sum count mean std
A
X 59 4 2.250000 0.957427
Y 39 3 2.000000 1.000000
Z 35 3 1.333333 0.577350
Eksportuj grupy do różnych plików
Możesz iterować na obiekcie zwróconym przez groupby()
. Iterator zawiera krotki (Category, DataFrame)
.
# Same example data as in the previous example.
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame({'Age': np.random.randint(20, 70, 100),
'Sex': np.random.choice(['Male', factor'Female'], 100),
'number_of_foo': np.random.randint(1, 20, 100)})
# Export to Male.csv and Female.csv files.
for sex, data in df.groupby('Sex'):
data.to_csv("{}.csv".format(sex))
za pomocą transformacji, aby uzyskać statystyki na poziomie grupy, zachowując oryginalną ramkę danych
przykład:
df = pd.DataFrame({'group1' : ['A', 'A', 'A', 'A',
'B', 'B', 'B', 'B'],
'group2' : ['C', 'C', 'C', 'D',
'E', 'E', 'F', 'F'],
'B' : ['one', np.NaN, np.NaN, np.NaN,
np.NaN, 'two', np.NaN, np.NaN],
'C' : [np.NaN, 1, np.NaN, np.NaN,
np.NaN, np.NaN, np.NaN, 4]})
df
Out[34]:
B C group1 group2
0 one NaN A C
1 NaN 1.0 A C
2 NaN NaN A C
3 NaN NaN A D
4 NaN NaN B E
5 two NaN B E
6 NaN NaN B F
7 NaN 4.0 B F
Chcę uzyskać liczbę niebrakującymi obserwacji B dla każdej kombinacji group1
i group2
. groupby.transform
to bardzo potężna funkcja, która właśnie to robi.
df['count_B']=df.groupby(['group1','group2']).B.transform('count')
df
Out[36]:
B C group1 group2 count_B
0 one NaN A C 1
1 NaN 1.0 A C 1
2 NaN NaN A C 1
3 NaN NaN A D 0
4 NaN NaN B E 1
5 two NaN B E 1
6 NaN NaN B F 0
7 NaN 4.0 B F 0