group_by() + summarise()
でグループ別集計ができるcount() でカテゴリの頻度を集計できるggplot2 でグラフ化できるこの回のコードは,すべて tidyverse
を読み込んだ状態で動きます。
RStudioを起動したら,まずこれを実行してください。
毎回必要です。読み込まないまま
filter()やggplot()を使うと, 「関数が見つかりません」というエラーになります。
summarise()
はデータ全体を1行(または数行)に集約します。
# 複数の統計量をまとめて計算
msleep |>
summarise(
n = n(),
mean_sleep = mean(sleep_total, na.rm = TRUE),
sd_sleep = sd(sleep_total, na.rm = TRUE),
min_sleep = min(sleep_total, na.rm = TRUE),
max_sleep = max(sleep_total, na.rm = TRUE)
)| 関数 | 意味 |
|---|---|
mean(x, na.rm=TRUE) |
平均値 |
sd(x, na.rm=TRUE) |
標準偏差 |
median(x, na.rm=TRUE) |
中央値 |
min(x) / max(x) |
最小値 / 最大値 |
n() |
データ件数 |
sum(x, na.rm=TRUE) |
合計 |
na.rm = TRUEは欠損値(NA)を除いて計算するオプションです。
group_by() と summarise()
を組み合わせると,グループごとに集計できます。
# 食性(vore)ごとの平均睡眠時間
msleep |>
group_by(vore) |>
summarise(
n = n(),
mean_sleep = mean(sleep_total, na.rm = TRUE),
sd_sleep = sd(sleep_total, na.rm = TRUE)
)<NA> の行は何か出力の最後に <NA>
という行があります。これは「NAという食性」ではありません。
msleep
には食性が記録されていない動物が7種あり,その7種がひとまとめにされて集計されています。
group_by()
は,欠損値も1つのグループとして扱います。黙って捨てたりはしません。
「そういうデータがある」と見せてくれている,と考えてください。
この行をどう扱うかは,分析する人が決めます。
- 食性どうしを比べるのが目的なら,除く(4節でそうしています)
- 「食性が不明な動物がこれだけいる」こと自体が情報なら,残す
どちらでも構いませんが,除いたことを自覚しておくのが大事です。 気づかないうちに7種が消えているのと,理由があって除くのとは違います。
# irisデータ:種ごとの平均と標準偏差
iris |>
group_by(Species) |>
summarise(
n = n(),
mean_sepal = mean(Sepal.Length),
sd_sepal = sd(Sepal.Length),
mean_petal = mean(Petal.Length),
sd_petal = sd(Petal.Length)
)ここでは食性どうしを比べたいので,2節で見た <NA>
の行を filter(!is.na(vore))
で除いてから集計します。
# 集計データを作成
sleep_summary <- msleep |>
filter(!is.na(vore)) |>
group_by(vore) |>
summarise(
mean_sleep = mean(sleep_total, na.rm = TRUE),
sd_sleep = sd(sleep_total, na.rm = TRUE),
n = n()
)
# 棒グラフ(geom_col で集計済みデータを使う)
ggplot(sleep_summary, aes(x = vore, y = mean_sleep, fill = vore)) +
geom_col() +
scale_fill_brewer(palette = "Set2") +
labs(title = "食性ごとの平均睡眠時間",
x = "食性", y = "平均睡眠時間(時間)",
fill = "食性") +
theme_bw()ggplot(sleep_summary, aes(x = vore, y = mean_sleep, fill = vore)) +
geom_col() +
geom_errorbar(aes(ymin = mean_sleep - sd_sleep,
ymax = mean_sleep + sd_sleep),
width = 0.2) +
scale_fill_brewer(palette = "Set2") +
labs(title = "食性ごとの平均睡眠時間(±SD)",
x = "食性", y = "平均睡眠時間(時間)") +
theme_bw() +
theme(legend.position = "none")
n()とna.rm = TRUEを並べるときは注意してください。
n()は行数を数えるだけで,欠損があるかどうかは見ていません。 一方mean(x, na.rm = TRUE)は欠損を除いて計算します。 つまり同じsummarise()の中に並べると,nと「平均に使われた件数」がずれます。msleep |> summarise(n = n(), mean_brain = mean(brainwt, na.rm = TRUE)) # n は 83 と出るが,平均に使われたのは 56 件(brainwt は27件が欠損)実際に使われた件数を数えたいときは
sum(!is.na(brainwt))を使います。 レポートや論文で n を書くときは,どちらの数字なのかをはっきりさせてください。
# 欠損値のある行を除いてから集計
msleep |>
filter(!is.na(sleep_rem)) |>
group_by(vore) |>
summarise(
n = n(),
mean_rem = mean(sleep_rem)
)ここまではRに最初から入っているデータを使ってきました。 自分で集めたデータを読み込むときは,次のように書きます。
read_csv() は UTF-8
という文字コードを前提にしています。 ところが
Windows版のExcelで「CSV(コンマ区切り)」として保存すると,多くの場合
Shift_JIS(CP932)になります。
この食い違いが起きると,こうなります。
> my_data
\x92n\x88\xe6 \x90l\x90\x94
1 \x93\x8c\x8b\x9e 10
2 \x8eD\x96y 20
本来は 地域 人数 東京
札幌 と表示されるはずのところが,\x
で始まる記号の列になります。
これが一番やりにくい点です。 エラーで止まりません。 読み込み自体は成功してしまうので,気づかないまま集計や作図に進み, グラフの軸ラベルが記号だらけになって初めて気づく,ということが起きます。 読み込んだ直後に必ず中身を表示して,日本語が読めているか確認してください。
対処は2つあります。
① 読み込むときに文字コードを指定する
# Windows版Excelで保存したCSVは,たいていこちら
my_data <- read_csv("data/my_data.csv", locale = locale(encoding = "CP932"))
# すでにUTF-8になっているCSV(指定しなくても読めます)
my_data <- read_csv("data/my_data.csv", locale = locale(encoding = "UTF-8"))② 保存するときにUTF-8にしておく(こちらを推奨)
Excelの「名前を付けて保存」で,ファイルの種類を
CSV UTF-8 (コンマ区切り) にします。
こうしておけば read_csv()
に何も足さずに読めますし,他の人とデータを共有するときも安全です。
どちらの文字コードか分からないときは,まず
read_csv()だけで試してください。 化けていたらlocale = locale(encoding = "CP932")を足す,という順番で構いません。
.xlsx
のまま読めば,文字コードの問題は起きません。
# install.packages("readxl") # 最初の1回だけ
library(readxl)
my_data <- read_excel("data/my_data.xlsx")
# シートを指定する場合
my_data <- read_excel("data/my_data.xlsx", sheet = "データ")Excelで管理しているデータなら,CSVに変換せずこちらのほうが確実です。
readxlは tidyverse に含まれていないので,install.packages("readxl")が別に必要です。
iris
データを使って,種(Species)ごとに以下を計算してください。
Petal.Length の平均・標準偏差・サンプルサイズ演習1で作った集計結果を使って,エラーバー付きの棒グラフを作成してください。
# まず集計
petal_summary <- iris |>
group_by(Species) |>
summarise(
mean_petal = mean(Petal.Length),
sd_petal = sd(Petal.Length)
)
# グラフ
ggplot(petal_summary, aes(x = ___, y = ___, fill = ___)) +
geom_col() +
geom_errorbar(aes(ymin = ___ - ___, ymax = ___ + ___), width = 0.2) +
scale_fill_brewer(palette = "Set2") +
labs(title = "種ごとの花びらの長さ(平均±SD)",
x = "___", y = "___") +
theme_bw()msleep の食性(vore)ごとのサンプルサイズを
count() で集計し,多い順に並べてください。
voreには欠損値(NA)が7件あります。count()はそのまま使うとNAも1つのカテゴリとして数えます。今回はNAを除いて集計してください。
summarise() でデータを集計できるgroup_by() と組み合わせるとグループ別集計が可能count() でカテゴリの頻度を数えられるggplot2 でグラフ化できるna.rm = TRUE で欠損値を除いた計算ができる