Rの集計関数:summarise()とgroup_by()の例
⚡ スマートサマリー
R言語のdplyrパッケージを使った集計関数は、多数の行をグループごとに1つの統計量に集約します。このチュートリアルでは、Lahman選手の打撃データに対してgroup_by()関数とsummarise()関数を組み合わせ、104,324件の観測値について平均値、合計値、スプレッド、カウント、ポジション値を計算します。

このチュートリアルで使用されるデータセット
変数を要約することでデータの概要を把握できますが、グループごとに要約することで値の分布についてより詳細な情報を得ることができます。このチュートリアルでは、dplyrライブラリを使用してデータセットをグループごとに集計する方法を説明します。
このチュートリアルでは、Lahman 打撃データセットを使用します。インポートして、ping 以下にリストされている9つの列のみを対象として、作業用データフレームには104,324の観測値と9つの変数が含まれています。
- playerID: プレイヤーIDコード。 要素
- yearID: 年。 要素
- チームID: チーム。 要素
- lgID: リーグ。 要因: AA AL FL NL PL UA
- AB:打席です。 数値
- G: ゲーム: プレイヤーによるゲーム数。 数値
- R:走ります。 数値
- HR: ホームラン。 数値
- SH:犠打。 数値
要約を実行する前に、次の手順を実行してデータを準備します。
- ステップ 1: データをインポートする
- ステップ 2: 関連する変数を選択する
- ステップ 3: データを並べ替える
library(dplyr) # Step 1 data <- read.csv("https://raw.githubusercontent.com/guru99-edu/R-Programming/master/lahman-batting.csv") %>% # Step 2 select(c(playerID, yearID, AB, teamID, lgID, G, R, HR, SH)) %>% # Step 3 arrange(playerID, teamID, yearID)
データセットをインポートするときは、glance() 関数を使用してデータセットの構造について把握することをお勧めします。
# Structure of the data glimpse(data)
出力:
Observations: 104,324 Variables: 9 $ playerID <fctr> aardsda01, aardsda01, aardsda01, aardsda01, aardsda01, a... $ yearID <int> 2015, 2008, 2007, 2006, 2012, 2013, 2009, 2010, 2004, 196... $ AB <int> 1, 1, 0, 2, 0, 0, 0, 0, 0, 603, 600, 606, 547, 516, 495, ... $ teamID <fctr> ATL, BOS, CHA, CHN, NYA, NYN, SEA, SEA, SFN, ATL, ATL, A... $ lgID <fctr> NL, AL, AL, NL, AL, NL, AL, AL, NL, NL, NL, NL, NL, NL, ... $ G <int> 33, 47, 25, 45, 1, 43, 73, 53, 11, 158, 155, 160, 147, 15... $ R <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 113, 84, 100, 103, 95, 75... $ HR <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 39, 29, 44, 38, 47, 34, 40... $ SH <int> 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, ...
要約する()
summarise() の構文は基本的なものであり、dplyr ライブラリに含まれる他の動詞と一致しています。
summarise(df, variable_name=condition) arguments: - `df`: Dataset used to construct the summary statistics - `variable_name=condition`: Formula to create the new variable
以下のコードを見てください。
summarise(data, mean_run =mean(R))
Code 説明
- summarise(data, mean_run = mean(R)): データセットデータからの列実行の平均であるmean_runという変数を作成します。
出力:
## mean_run ## 1 19.20114
必要なだけ変数を追加できます。平均ゲーム数と平均犠牲ヒット数を返します。
summarise(data, mean_games = mean(G), mean_SH = mean(SH, na.rm = TRUE))
Code 説明
- mean_SH = mean(SH, na.rm = TRUE): 2 番目の変数を要約します。列 SH に欠損値が含まれているため、na.rm = TRUE を設定します。
出力:
## mean_games mean_SH ## 1 51.98361 2.340085
group_by() と group_by() なしの比較
summarise() を単独で使用すると、上記の例に示すように、データフレーム全体が 1 つの行にまとめられます。その真の力は、group_by() を追加したときに現れます。 dplyr ライブラリは、同じ計算を各グループに個別に適用し、グループごとに1行を返します。
group_by は他のすべての動詞 (つまり、mutate()、filter()、arrange() など) と完全に連携することに注意してください。
複数のステップがある場合は、パイプライン演算子を使用すると便利です。野球リーグごとの平均ホームランを計算できます。
data %>% group_by(lgID) %>% summarise(mean_run = mean(HR))
Code 説明
- data: 要約統計量の構築に使用されるデータセット
- group_by(lgID): 集計前にlgIDの値でデータを分割します
- summarise(mean_run = mean(HR)): 平均ホームランを計算する
出力:
## # A tibble: 7 x 2 ## lgID mean_run ## <fctr> <dbl> ## 1 AA 0.9166667 ## 2 AL 3.1270988 ## 3 FL 1.3131313 ## 4 NL 2.8595953 ## 5 PL 2.5789474 ## 6 UA 0.6216216 ## 7 <NA> 0.2867133
パイプはggplot()でも機能するため、生データから完成したグラフまでの処理全体を1つのステートメントで実行できます。以下のコードは、group_by()、summarise()、ggplot()を組み合わせて、リーグごとの平均ホームラン数を棒グラフで表示します。
次の手順を実行します。
- ステップ 1: データ フレームを選択する
- ステップ 2: データをグループ化する
- ステップ3: データを要約する
- ステップ 4: 要約統計量をプロットする
library(ggplot2) # Step 1 data %>% #Step 2 group_by(lgID) %>% #Step 3 summarise(mean_home_run = mean(HR)) %>% #Step 4 ggplot(aes(x = lgID, y = mean_home_run, fill = lgID)) + geom_bar(stat = "identity") + theme_classic() + labs( x = "baseball league", y = "Average home run", title = paste( "Example group_by() with summarise()" ) )
出力:
summarise() 関数内で使用できる関数
動詞 summarise() は、R のほぼすべての関数と互換性があります。summarise() と一緒に使用できる便利な関数の短いリストを以下に示します。
| DevOps Tools Engineer試験のObjective | 演算 | 詳細説明 |
|---|---|---|
| Basic | 平均() | ベクトル x の平均 |
| 中央値() | ベクトル x の中央値 | |
| 和() | ベクトル x の合計 | |
| 変動 | SD() | ベクトル x の標準偏差 |
| IQR() | ベクトル x の四分位数 | |
| レンジ | min() | ベクトル x の最小値 |
| max() | ベクトル x の最大値 | |
| 分位数() | ベクトル x の分位数 | |
| 役職 | 最初() | group_by() と併用 グループの最初の観察 |
| 過去() | group_by() と一緒に使用します。 グループの最後の観察 | |
| nth() | group_by() と一緒に使用します。 グループのn回目の観察 | |
| 数量カウント | n() | group_by() と一緒に使用します。 行数を数える |
| n_distinct() | group_by() と一緒に使用します。 個別の観測値の数を数える |
以下のセクションでは、上の表の各関数の例を解説します。パイプやその他の動詞に慣れていない場合は、 選択、フィルタリング、配置チュートリアル.
基本機能
前の例では、要約統計量をデータ フレームに保存しませんでした。
要約からデータフレームを生成するには、次の2つの手順を実行します。
- ステップ 1: 今後使用するためにデータ フレームを保存する
- ステップ 2: データセットを使用して折れ線プロットを作成する
ステップ1) 年ごとにプレイされるゲームの平均数を計算します。
## Mean ex1 <- data %>% group_by(yearID) %>% summarise(mean_game_year = mean(G)) head(ex1)
Code 説明
- 打撃データセットの要約統計量はデータフレーム ex1 に格納されます。
出力:
## # A tibble: 6 x 2 ## yearID mean_game_year ## <int> <dbl> ## 1 1871 23.42308 ## 2 1872 18.37931 ## 3 1873 25.61538 ## 4 1874 39.05263 ## 5 1875 28.39535 ## 6 1876 35.90625
ステップ2) 折れ線グラフで要約統計量を表示し、傾向を確認します。
# Plot the graph ggplot(ex1, aes(x = yearID, y = mean_game_year)) + geom_line() + theme_classic() + labs( x = "Year", y = "Average games played", title = paste( "Average games played from 1871 to 2016" ) )
出力:
サブセット化
関数 summarise() はサブセット化と互換性があります。
## Subsetting + Median data %>% group_by(lgID) %>% summarise(median_at_bat_league = median(AB), #Compute the median without the zero median_at_bat_league_no_zero = median(AB[AB > 0]))
Code 説明
- median_at_bat_league_no_zero = median(AB[AB > 0]): 変数 AB には 0 がたくさん含まれています。中央値を比較できます。 打席で 0 を含む変数と XNUMX を含まない変数。
出力:
## # A tibble: 7 x 3 ## lgID median_at_bat_league median_at_bat_league_no_zero ## <fctr> <dbl> <dbl> ## 1 AA 130 131 ## 2 AL 38 85 ## 3 FL 88 97 ## 4 NL 56 67 ## 5 PL 238 238 ## 6 UA 35 35 ## 7 <NA> 101 101
合計
変数を集計するためのもう XNUMX つの便利な関数は sum() です。
どのリーグのホームラン数が多いかを確認できます。
## Sum data %>% group_by(lgID) %>% summarise(sum_homerun_league = sum(HR))
出力:
## # A tibble: 7 x 2 ## lgID sum_homerun_league ## <fctr> <int> ## 1 AA 341 ## 2 AL 29426 ## 3 FL 130 ## 4 NL 29817 ## 5 PL 98 ## 6 UA 46 ## 7 <NA> 41
標準偏差
データの広がりは、標準偏差または R の sd() を使用して計算されます。
# Spread data %>% group_by(teamID) %>% summarise(sd_at_bat_league = sd(HR))
出力:
## # A tibble: 148 x 2 ## teamID sd_at_bat_league ## <fctr> <dbl> ## 1 ALT NA ## 2 ANA 8.7816395 ## 3 ARI 6.0765503 ## 4 ATL 8.5363863 ## 5 BAL 7.7350173 ## 6 BFN 1.3645163 ## 7 BFP 0.4472136 ## 8 BL1 0.6992059 ## 9 BL2 1.7106757 ## 10 BL3 1.0000000 ## # ... with 138 more rows
ホームランの差はチームによって大きく異なり、ALT関数は該当チームのデータが1行しかないため、標準偏差を計算できずNAを返します。
最小および最大
関数 min() および max() を使用して、ベクトルの最小値と最大値にアクセスできます。
以下のコードは、プレーヤーがシーズン中にプレーしたゲームの最小数と最大数を返します。
# Min and max data %>% group_by(playerID) %>% summarise(min_G = min(G), max_G = max(G))
出力:
## # A tibble: 10,395 x 3 ## playerID min_G max_G ## <fctr> <int> ## 1 aardsda01 53 73 ## 2 aaronha01 120 156 ## 3 aasedo01 24 66 ## 4 abadfe01 18 18 ## 5 abadijo01 11 11 ## 6 abbated01 3 153 ## 7 abbeybe01 11 11 ## 8 abbeych01 80 132 ## 9 abbotgl01 5 23 ## 10 abbotji01 13 29 ## # ... with 10,385 more rows
数量カウント
グループごとに観測値を数えることは常に有益です。Rでは、n()関数は現在のグループの行数を返します。
たとえば、以下のコードは各プレーヤーのプレー年数を計算します。
# count observations data %>% group_by(playerID) %>% summarise(number_year = n()) %>% arrange(desc(number_year))
出力:
## # A tibble: 10,395 x 2 ## playerID number_year ## <fctr> <int> ## 1 pennohe01 11 ## 2 joosted01 10 ## 3 mcguide01 10 ## 4 rosepe01 10 ## 5 davisha01 9 ## 6 johnssi01 9 ## 7 kaatji01 9 ## 8 keelewi01 9 ## 9 marshmi01 9 ## 10 quirkja01 9 ## # ... with 10,385 more rows
始めと終わり
グループの最初、最後、または n 番目の位置を選択できます。
たとえば、各プレーヤーの最初の年と最後の年を見つけることができます。
# first and last data %>% group_by(playerID) %>% summarise(first_appearance = first(yearID), last_appearance = last(yearID))
出力:
## # A tibble: 10,395 x 3 ## playerID first_appearance last_appearance ## <fctr> <int> <int> ## 1 aardsda01 2009 2010 ## 2 aaronha01 1973 1975 ## 3 aasedo01 1986 1990 ## 4 abadfe01 2016 2016 ## 5 abadijo01 1875 1875 ## 6 abbated01 1905 1897 ## 7 abbeybe01 1894 1894 ## 8 abbeych01 1895 1897 ## 9 abbotgl01 1973 1979 ## 10 abbotji01 1992 1996 ## # ... with 10,385 more rows
n回目の観測
nth() 関数は first() 関数と last() 関数を補完するものです。各グループ内で、指定されたインデックスにある観測値を返します。
たとえば、チームがプレーした 2 年目だけをフィルタリングできます。
# nth data %>% group_by(teamID) %>% summarise(second_game = nth(yearID, 2)) %>% arrange(second_game)
出力:
## # A tibble: 148 x 2 ## teamID second_game ## <fctr> <int> ## 1 BS1 1871 ## 2 CH1 1871 ## 3 FW1 1871 ## 4 NY2 1871 ## 5 RC1 1871 ## 6 BR1 1872 ## 7 BR2 1872 ## 8 CL1 1872 ## 9 MID 1872 ## 10 TRO 1872 ## # ... with 138 more rows
異なる数の観測
n() は現在のグループ内の行数を返します。関連する n_distinct() は、代わりに一意の値をカウントします。
次の例では、全期間中にチームが採用した選手の合計を合計します。
# distinct values data %>% group_by(teamID) %>% summarise(number_player = n_distinct(playerID)) %>% arrange(desc(number_player))
Code 説明
- group_by(teamID): チームごとにグループ化
- 要約(プレイヤー数 = n_distinct(playerID)): チームごとの異なるプレイヤー数をカウントします
- assign(desc(number_player)): データをプレイヤー数でソートします。
出力:
## # A tibble: 148 x 2 ## teamID number_player ## <fctr> <int> ## 1 CHN 751 ## 2 SLN 729 ## 3 PHI 699 ## 4 PIT 683 ## 5 CIN 679 ## 6 BOS 647 ## 7 CLE 646 ## 8 CHA 636 ## 9 DET 623 ## 10 NYA 612 ## # ... with 138 more rows
複数のグループ
複数のグループ間で要約統計を実現できます。
# Multiple groups data %>% group_by(yearID, teamID) %>% summarise(mean_games = mean(G)) %>% arrange(desc(teamID, yearID))
Code 説明
- group_by(年ID, チームID): 年ごとにグループ化します。 (NAIST) と チーム
- summarise(mean_games = mean(G)): プレイされたゲーム数の平均値
- assign(desc(teamID, yearID)): データをチームと年で並べ替えます。
出力:
## # A tibble: 2,829 x 3 ## # Groups: yearID [146] ## yearID teamID mean_games ## <int> <fctr> <dbl> ## 1 1884 WSU 20.41667 ## 2 1891 WS9 46.33333 ## 3 1886 WS8 22.00000 ## 4 1887 WS8 51.00000 ## 5 1888 WS8 27.00000 ## 6 1889 WS8 52.42857 ## 7 1884 WS7 8.00000 ## 8 1875 WS6 14.80000 ## 9 1873 WS5 16.62500 ## 10 1872 WS4 4.20000 ## # ... with 2,819 more rows
フィルター
操作を実行する前に、データセットをフィルタリングできます。データセットは 1871 年から始まり、分析では 1980 年より前の年は必要ありません。
# Filter data %>% filter(yearID > 1980) %>% group_by(yearID) %>% summarise(mean_game_year = mean(G))
Code 説明
- filter(yearID > 1980): データをフィルタリングして、関連する年 (つまり 1980 年以降) のみを表示します。
- group_by(yearID): 年ごとにグループ化します。
- summarise(mean_game_year = mean(G)): データを要約する
出力:
## # A tibble: 36 x 2 ## yearID mean_game_year ## <int> <dbl> ## 1 1981 40.64583 ## 2 1982 56.97790 ## 3 1983 60.25128 ## 4 1984 62.97436 ## 5 1985 57.82828 ## 6 1986 58.55340 ## 7 1987 48.74752 ## 8 1988 52.57282 ## 9 1989 58.16425 ## 10 1990 52.91556 ## # ... with 26 more rows
グループ解除
最後に、グループを削除する必要がありますping 計算を実行するレベルを変更する前に。ungroup() を使用しない場合、2 番目の summarise() は依然としてプレイヤーごとに実行されます。
# Ungroup the data data %>% filter(HR > 0) %>% group_by(playerID) %>% summarise(average_HR_game = sum(HR) / sum(G)) %>% ungroup() %>% summarise(total_average_homerun = mean(average_HR_game))
Code 説明
- filter(HR >0) : ゼロホームランを除外します
- group_by(playerID): プレイヤーごとにグループ化
- summarise(average_HR_game = sum(HR)/sum(G)): 選手ごとの平均ホームラン数を計算する
- ungroup(): グループを削除しますping
- summarise(total_average_homerun = mean(average_HR_game)): データを要約する
出力:
## # A tibble: 1 x 1 ## total_average_homerun ## <dbl> ## 1 0.06882226
across() を使用して複数の列を集計する方法
上記の例では、一度に1つの列を指定しています。複数の列に対して同じ統計情報が必要な場合は、across() 関数を使用すると、1回の呼び出しですべての列に統計情報を適用できます。
# One function, several columns data %>% group_by(lgID) %>% summarise(across(c(R, HR, G), mean, .names = "mean_{.col}")) # Every numeric column at once data %>% group_by(lgID) %>% summarise(across(where(is.numeric), mean, na.rm = TRUE)) # Several functions applied to several columns data %>% group_by(teamID) %>% summarise(across(c(R, HR), list(avg = mean, total = sum)))
動作を制御する引数は3つあります。
- .cols: 操作対象の列。select() と同じヘルパーを使用して記述され、where(is.numeric) も含まれます。
- .fns各列に適用する関数、または関数の名前付きリスト。
- .names: 出力の命名パターン。{.col} は列、{.fn} は関数名です。
dplyr 1.0.0 では、従来の summarise_all()、summarise_at()、summarise_if() ヘルパー関数が across() に置き換えられました。これらのヘルパー関数は引き続き動作しますが、置き換えられたため、新しいコードでは across() を使用する必要があります。
summarise() 関数でよく発生するエラーとその修正方法
集計処理の失敗の大部分は、以下の4つの問題に起因する。
- 結果はNAです。 mean() と sum() は、いずれかの値が欠落している場合、NA を返します。上記の mean_SH の例のように、na.rm = TRUE を追加してください。
- 「summarise() の出力がグループ化されています」というメッセージ。 グロウping 2 つの変数でグループ化すると、結果は最初の変数でグループ化されます。.groups = “drop” を渡してグループを削除します。pingまたは、後で ungroup() を呼び出す。
- 後の計算では誤った数値が算出された。 データフレームは、グループを解除するまでグループ化された状態が維持されるため、各グループごとに2回目のsummarise()が実行されます。これは、ungroup()の例がまさに示しているとおりです。
- 出力結果の行数が予想より多い。 summarise() はグループごとに 1 行を返すため、意図しないグループping 変数は出力に乗算されます。tibble の上に表示される「Groups:」行を確認してください。
# Drop the grouping as part of the call data %>% group_by(yearID, teamID) %>% summarise(mean_games = mean(G), .groups = "drop")
summarise() 関数 (R の関数リファレンス)
グループごとの要約を返すには、まずデータを分割します。
# group by X1, X2, X3 group_by(df, X1, X2, X3)
そしてグループを削除するping 計算レベルが変更される場合:
ungroup(df)
以下の表は、このチュートリアルで summarise() 関数とともに使用されるすべての関数を示しています。
| 方法 | 演算 | Code |
|---|---|---|
| 意味する | 意味する |
summarise(df, mean_x1 = mean(x1))
|
| 中央値 | 中央値 |
summarise(df, median_x1 = median(x1)) |
| 合計 | 合計 |
summarise(df, sum_x1 = sum(x1))
|
| 標準偏差 | sd |
summarise(df, sd_x1 = sd(x1)) |
| 四分位 | I.Q.R. |
summarise(df, interquartile_x1 = IQR(x1)) |
| 最小 | 分 |
summarise(df, minimum_x1 = min(x1)) |
| マックス |
summarise(df, maximum_x1 = max(x1))
|
|
| 分位 | 分位 |
summarise(df, quantile_x1 = quantile(x1, probs = 0.75))
|
| 最初の観察 | 最初の |
summarise(df, first_x1 = first(x1)) |
| 最後の観察 | last |
summarise(df, last_x1 = last(x1)) |
| n回目の観測 | n番目の |
summarise(df, nth_x1 = nth(x1, 2)) |
| 出現数 | n |
summarise(df, n_x1 = n()) |
| 個別の出現の数 | n_distinct |
summarise(df, n_distinct_x1 = n_distinct(x1)) |


