DataFrameGroupByには各グループを確認するためのいろいろな機能があります。たとえば、次のようなものです
メソッド | 説明 |
---|---|
get_group(グループ名) | 指定したグループのデータ(DataFrame)を取得 |
head(行数) | 各グループの先頭行を、指定した行数だけ取得(デフォルトでは5行) |
tail(行数) | 各グループの末尾行を、指定した行数だけ取得(デフォルトでは5行) |
nth(N) | N-1番目の行を取得(Nには整数を指定 |
また、groupby()
の結果をループと組み合わせると、各グループの名前(キー)とデータ(DataFrame)を取得できます。
# 各グループの名前(キー)とデータ(DataFrame)を取得
for name, group in grouped:
print(name) # グループ名(キー)
print(group) # グループのデータ(DataFrame)
生徒ID | クラス | 点数 | 学習時間(分) |
---|---|---|---|
ST001 | 1-A | 60 | 232 |
ST002 | 1-A | 87 | 345 |
ST003 | 1-B | 66 | 180 |
ST004 | 1-A | 72 | 22 |
ST005 | 1-B | 74 | 120 |
ST006 | 1-B | 58 | 215 |
列クラスでグループ化してfor文に渡した場合、次のように表示されます。nameには各グループの名前、groupには各グループのデータ(DataFrame)が代入されます。
# 列「クラス」でグループ化
grouped = df.groupby("クラス")
for name, group in grouped:
print(name) # グループ名(キー)
print("-------------------")
print(group) # グループのデータ(DataFrame)
print("==========")
1-A
-------------------
クラス 点数 学習時間(分)
生徒ID
ST001 1-A 60 232
ST002 1-A 87 345
ST004 1-A 72 22
==========
1-B
-------------------
クラス 点数 学習時間(分)
生徒ID
ST003 1-B 66 180
ST005 1-B 74 120
ST006 1-B 58 215
==========
演習
import pandas as pd
# 試験結果データを読み込み
df = pd.read_csv("dataset/score_basic.csv", index_col="生徒ID")
# 先頭5行を確認
df.head()
クラス | 点数 | |
---|---|---|
生徒ID | ||
ST001 | 1-A | 48 |
ST002 | 1-A | 88 |
ST003 | 1-B | 56 |
ST004 | 1-A | 66 |
ST005 | 1-A | 68 |
(1)各グループの名前と、そのグループに属するデータ
今回はクラスごとにグループ化したいので、groupby()
で列クラス
を指定します。前問のおさらいで、まずはgroups
属性で各グループに属する行を確認してみましょう。
# 列「クラス」でグループ化
grouped = df.groupby("クラス")
# 各グループのインデックスを確認
grouped.groups
{'1-A': ['ST001', 'ST002', 'ST004', 'ST005', 'ST007', 'ST011', 'ST012', 'ST017', 'ST019', 'ST020'], '1-B': ['ST003', 'ST006', 'ST008', 'ST009', 'ST010', 'ST013', 'ST014', 'ST015', 'ST016', 'ST018']}
DataFrameGroupByオブジェクトをfor文で使うと、各グループの名前(キー)とデータ(DataFrame)を確認できます。
# 各グループの情報を順に表示する
for name, group in grouped:
print(name) # グループ名(キー)
print() # 空行
print(group) # グループに属するデータ(DataFrame)
print("======================")
1-A
クラス 点数
生徒ID
ST001 1-A 48
ST002 1-A 88
ST004 1-A 66
ST005 1-A 68
ST007 1-A 49
ST011 1-A 100
ST012 1-A 84
ST017 1-A 81
ST019 1-A 78
ST020 1-A 90
======================
1-B
クラス 点数
生徒ID
ST003 1-B 56
ST006 1-B 58
ST008 1-B 79
ST009 1-B 75
ST010 1-B 40
ST013 1-B 58
ST014 1-B 83
ST015 1-B 62
ST016 1-B 69
ST018 1-B 51
======================
(2)グループ1-A
に属するデータ
次に、グループ1-A
に属するデータを確認しましょう。get_group()
を使うと、指定したグループに属するデータを取得できます。
# グループ「1-A」を取得
group_1_A = grouped.get_group("1-A")
group_1_A
クラス | 点数 | |
---|---|---|
生徒ID | ||
ST001 | 1-A | 48 |
ST002 | 1-A | 88 |
ST004 | 1-A | 66 |
ST005 | 1-A | 68 |
ST007 | 1-A | 49 |
ST011 | 1-A | 100 |
ST012 | 1-A | 84 |
ST017 | 1-A | 81 |
ST019 | 1-A | 78 |
ST020 | 1-A | 90 |
(3)各グループの成績上位者1〜3位のデータ(点数でソート後、各グループの先頭3行)
DataFrameGroupByオブジェクトのhead()
を使うと、各グループの先頭行を、指定した行数分だけ取得できます。
head()
を利用して、「各クラスの成績上位者1〜3位のデータ」を取得してみましょう。これは、各グループの行が列点数
の高い順で並んでいれば、「先頭3行」を取得することで1〜3位のデータが取得できます(今回は、1〜3位はそれぞれ1人ずつしかいないものとします)。
groupby()
後、各グループでは元のDataFrameの行の並び順が保持されています。そのため、各グループでソートしたい場合は、groupby()
を使う前にsort_values()
を使ってソートします。
# 列「点数」の降順でソート
sorted_df = df.sort_values("点数", ascending=False)
# 先頭10行を確認
sorted_df.head(10)
クラス | 点数 | |
---|---|---|
生徒ID | ||
ST011 | 1-A | 100 |
ST020 | 1-A | 90 |
ST002 | 1-A | 88 |
ST012 | 1-A | 84 |
ST014 | 1-B | 83 |
ST017 | 1-A | 81 |
ST008 | 1-B | 79 |
ST019 | 1-A | 78 |
ST009 | 1-B | 75 |
ST016 | 1-B | 69 |
列クラス
でグループ化してから、head()
を使って各グループの先頭3行を表示します。グループ化前のDataFrame(sorted_df
)と比較すると、1-Aと1-Bからそれぞれ成績上位3名分のデータが抽出されていることがわかります。
# 列「クラス」でグループ化
sorted_grouped = sorted_df.groupby("クラス")
# 各グループの先頭3行を取得
sorted_grouped.head(3)
クラス | 点数 | |
---|---|---|
生徒ID | ||
ST011 | 1-A | 100 |
ST020 | 1-A | 90 |
ST002 | 1-A | 88 |
ST014 | 1-B | 83 |
ST008 | 1-B | 79 |
ST009 | 1-B | 75 |
(4)各グループの成績上位者3位のデータ(点数でソート後、各グループの3番目の行)
nth()
を使うと、各グループから指定した位置のデータを取得します。
これを利用して、各クラスで3番目の成績上位者のデータを取得してみましょう。先頭から3番目なので、引数は2
を指定します。
実行結果を確認すると、クラス1-A
では88
点(生徒ST002
のデータ)、クラス1-B
では75
点(生徒ST009
のデータ)となっており、各グループで上から3行目のデータが取得できていることがわかります。
# 各グループの先頭から3行目(位置は2)を取得
sorted_grouped.nth(2)
点数 | |
---|---|
クラス | |
1-A | 88 |
1-B | 75 |
コメント