404 Not Found

404 Not Found


nginx

Rによる記述統計:平均、中央値、標準偏差の完全ガイド

これまでの22回のレッスンでは、Rの「ツール」――ベクトル、データフレーム、ggplot2――について学びました。これからは、Rの真の「価値」である統計分析に移ります。このレッスンでは、最も基本的な概念である「記述統計」から始めます。Rを使って、平均、中央値、標準偏差といった主要な指標を計算し、データをいくつかの数値に「要約」していきます。

このレッスンを修了すると、たった3行のRコードを使って、どのようなデータセットに対しても「統計レポート」を作成できるようになります。

1. 学習内容



2. ある生徒の成績表にまつわる物語

(1) 課題:1,000人の生徒をどのように「要約」すればよいでしょうか?

学期の終わりに、ボブ教授は1,000人の学生の成績表を作成する必要があります。各学生は5つの科目を履修しており、各科目について、以下の計算を行う必要があります:

手計算?Excelの関数?それだと2時間かかるけど、Rを使えば summary()——

(2) Rを用いた解決策

R
# 1. One line summary shows 5 key metrics
summary(scores$math)
#   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#   45.0    72.0    82.0    81.5    92.0    99.0

# 2. One line skimr View the full report
library(skimr)
skim(scores$math)
# ── Variable type: numeric ──
#   min  max mean sd   p25  p50  p75  hist
#   45  99  81.5 12  72  82  92  ▇▇▇▇▇

# 3. One line dplyr Grouped Statistics
scores |> group_by(class) |> summarise(
  Average Score = mean(math),
  Median = median(math),
  Standard Deviation = sd(math),
  Highest = max(math),
  Lowest = min(math),
  Number of people = n()
)

たった3行のコードで、成績表が完成



3. 記述統計の3つの主要な分類

(1) 3つの主要カテゴリーの概要

100%
graph TB
    A[Descriptive Statistics] --> B[Central Tendency<br/>Central Tendency]
    A --> C[Degree of dispersion<br/>Dispersion]
    A --> D[Distribution Patterns<br/>Shape]
    B --> E[mean Median mode]
    C --> F[sd var range IQR]
    D --> G[Skewness skewness<br/>Fengdu kurtosis]
    
    style A fill:#fff3cd
    style B fill:#d4edda
    style C fill:#cce5ff
    style D fill:#f8d7da

(2) クイックリファレンス表

カテゴリ 機能 意味
中央傾向 mean() 算術平均
中央傾向 median() 中央値(50パーセンタイル)
集中型 mode() モード(DescTools パッケージが必要)
離散 sd() 標準偏差
離散 var() 分散
離散 range() 極値(最小値/最大値)
離散型 IQR() 四分位範囲 (Q3-Q1)
離散型 mad() 中央値絶対偏差
分布 skewness() 歪度(e1071 が必要)
分布 kurtosis() 尖度(e1071 が必要)


4. 中央傾向

(1) mean() 平均

R
x <- c(85, 90, 78, 92, 88)

mean(x)              # [1] 86.6
mean(x, na.rm = TRUE) # Skip NA
mean(x, trim = 0.1)   # Truncated Mean (Remove the top and bottom 10%)
⚠️ 注意平均値は外れ値の影響を強く受けます。データに10,000という値の外れ値が1つ含まれているだけで、平均値は上方へ偏ってしまいます。偏った分布の場合は中央値を使用してください

(2) median() 中央値

R
median(c(85, 90, 78, 92, 88))  # [1] 88
median(c(85, 90, 78, 92, 10000))  # [1] 90  ← Not affected by 10000 Impact
💡 ヒント中央値は平均値よりも頑健です。実際のプロジェクトでは、中央値を優先して使用してください(特に、所得や住宅価格のような偏った分布の場合)。

(3) モード(特殊機能)

R
# R does not have a built-in mode(), use the DescTools package
install.packages("DescTools")
library(DescTools)

Mode(c(1, 2, 2, 3, 3, 3, 4))  # [1] 3


5. 分散の度合い

(1) sd() / var() 標準偏差 / 分散

R
x <- c(85, 90, 78, 92, 88)

sd(x)    # [1] 5.32  ← Standard Deviation
var(x)   # [1] 28.3  <- Variance (sd^2)

標準偏差 = データ点が平均値から離れている「平均的な距離」。この値が大きいほど、データのばらつきは大きくなります。

(2) range()の極値

R
x <- c(85, 90, 78, 92, 88)

range(x)              # [1] 78 92  ← Minimum and Maximum
diff(range(x))        # [1] 14   ← Range

(3) IQR() 四分位範囲

R
x <- c(85, 90, 78, 92, 88, 70, 95, 65, 88, 92)

IQR(x)                # [1] 11.5  ← Q3 - Q1
quantile(x, c(0.25, 0.5, 0.75))
#   25%   50%   75% 
# 78.25  88.0  89.75
💡 ヒント: IQRはロバストな離散指標です。外れ値の影響を受けず、異常値の特定によく用いられます(Q1 - 1.5*IQRQ3 + 1.5*IQR)。

(4) mad()における中央値の絶対偏差

R
mad(c(85, 90, 78, 92, 10000))  # Extremely Robust Discrete Measures
# [1] 4.45


6. 分位数

(1) quantile() 分位数

R
x <- 1:100

# Default 0%, 25%, 50%, 75%, 100%
quantile(x)
#   0%  25%  50%  75% 100% 
#  1.0 25.75 50.5 75.25 100.0

# Custom Percentiles
quantile(x, probs = c(0.1, 0.5, 0.9))
#  10%  50%  90% 
# 10.9 50.5 90.1

(2) 一般的なパーセンタイル

パーセンタイル 関数 意味
Q0 (0%) min(x) 最小値
第1四半期 (25%) quantile(x, 0.25) 下位四分位
第2四半期 (50%) median(x) 中央値
第3四半期 (75%) quantile(x, 0.75) 上位四分位
第4四半期 (100%) max(x) 最大値


7. summary()—1行で表示される要約統計量

R
x <- c(85, 90, 78, 92, 88, NA, 75, 95)

summary(x)
#    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
#   75.00   81.50   88.00   87.62   90.50   95.00       1

6つの主要指標+NA件数—すべて1行にまとめて!

R
# Data Frame
df <- data.frame(
  age = c(20, 25, 30, 35),
  score = c(85, 90, 78, 92)
)
summary(df)
#       age            score     
#  Min.   :20.00   Min.   :78.00  
#  1st Qu.:23.75   1st Qu.:83.25  
#  Median :27.50   Median :87.50  
#  Mean   :27.50   Mean   :86.25  
#  3rd Qu.:31.25   3rd Qu.:90.50  
#  Max.   :35.00   Max.   :92.00


8. skimr:高度で包括的な統計機能

R
install.packages("skimr")
library(skimr)

x <- c(85, 90, 78, 92, 88, 70, 95, 65, 88, 92)

skim(x)
# ── Data Summary ────────────────────────
# Values                           x
# Number of rows                   10
# Number of distinct                8
# Mean                            84.2
# Standard deviation             10.13
# Min                              65
# Max                              95
# Median                          87.5
# ... (More Metrics)

skim()20以上の指標を提供しており、summary() よりも10倍詳細です。



9. グループ別の記述統計

(1) dplyr + group_by + summarise

R
library(dplyr)

# Simulation 3 Cls × 5 Student Grades
scores <- tibble(
  class = rep(c("1Cls", "2Cls", "3Cls"), each = 5),
  student = paste0("S", 1:15),
  math = c(85, 78, 92, 65, 88,    # 1 Cls
           90, 75, 80, 95, 70,    # 2 Cls
           82, 88, 76, 91, 85),   # 3 Cls
  english = c(78, 85, 88, 70, 92,
              82, 80, 90, 88, 75,
              88, 90, 78, 92, 85)
)

# Class Statistics
class_stats <- scores |>
  group_by(class) |>
  summarise(
    Number of people = n(),
    Mathematical Average = mean(math),
    Median in Mathematics = median(math),
    Mathematical Standard Deviation = sd(math),
    Top in Math = max(math),
    Lowest in Math = min(math),
    MathematicsIQR = IQR(math),
    Average English Score = mean(english)
  )

print(class_stats)
# A tibble: 3 × 9
#   class  Number of people Mathematical Average Median in Mathematics Mathematical Standard Deviation Top in Math Lowest in Math MathematicsIQR Average English Score
#   <chr> <int>    <dbl>    <dbl>      <dbl>    <dbl>    <dbl>   <dbl>    <dbl>
# 1 1Cls       5     81.6       85       11.4       92       65    17       82.6
# 2 2Cls       5     82        80        10.5       95       70    20       83
# 3 3Cls       5     84.4       85        6.02      91       76    12      86.6

(2) 複数指標の内訳 (across)

R
# Calculate statistics for all numeric columns at once
scores |>
  group_by(class) |>
  summarise(across(where(is.numeric), list(
    mean = mean,
    sd = sd,
    median = median
  )))

(3) tapply の旧構文(参考用)

R
# Use tapply
tapply(scores$math, scores$class, mean)
# 1Cls 2Cls 3Cls 
# 81.6 82.0 84.4


10. 実践演習:1,000人の生徒を対象とした総合成績表の作成

以下は、このレッスンで取り上げたすべての記述統計を結びつける完全なワークフローの例です。

▶ サンプル:1,000人の学生と5つのコースに関する包括的なレポート

R
# ============================================
# 1000 Student 5 Course Comprehensive Grade Report
# Features: Complete Descriptive Statistics + Grouping + Ranking
# ============================================

library(dplyr)
library(tidyr)
library(ggplot2)

# 1. Prepare data
set.seed(42)
n <- 1000
students <- tibble(
  id = 1:n,
  class = sample(c("1Cls", "2Cls", "3Cls", "4Cls", "5Cls"), n, replace = TRUE),
  gender = sample(c("M", "F"), n, replace = TRUE),
  math = round(rnorm(n, 80, 12)),
  english = round(rnorm(n, 78, 15)),
  physics = round(rnorm(n, 75, 14)),
  chemistry = round(rnorm(n, 76, 13)),
  biology = round(rnorm(n, 80, 10))
)

cat("=== Data Volume:", nrow(students), "rows ===\n")

# 2. University-wide Comprehensive Statistics
cat("\n=== University-wide Comprehensive Statistics ===\n")
overall <- students |>
  summarise(across(c(math, english, physics, chemistry, biology),
                   list(mean = mean, sd = sd, median = median),
                   .names = "{.col}_{.fn}"))
print(overall)

# 3. Statistics by Class
cat("\n=== Math Statistics for Each Class ===\n")
class_stats <- students |>
  group_by(class) |>
  summarise(
    Number of people = n(),
    Average = round(mean(math), 2),
    Median = median(math),
    Standard Deviation = round(sd(math), 2),
    Highest = max(math),
    Lowest = min(math),
    Q1 = quantile(math, 0.25),
    Q3 = quantile(math, 0.75),
    IQR = round(IQR(math), 2)
  ) |>
  arrange(desc(Average))
print(class_stats)

# 4. Grouped by gender
cat("\n=== All genders 5 Class Average ===\n")
gender_stats <- students |>
  group_by(gender) |>
  summarise(across(c(math, english, physics, chemistry, biology),
                   mean, .names = "{.col}_Average"))
print(gender_stats)

# 5. Each Student's Total Score and Rank
cat("\n=== Top 10 Students (Total Score) ===\n")
students <- students |>
  mutate(total = math + english + physics + chemistry + biology,
         average = round(total / 5, 2))

top10 <- students |>
  arrange(desc(total)) |>
  head(10) |>
  select(id, class, gender, total, average)
print(top10)

# 6. Identify the outliers (IQR method)
cat("\n=== Students with Outliers in Math Scores ====\n")
math_q1 <- quantile(students$math, 0.25)
math_q3 <- quantile(students$math, 0.75)
math_iqr <- IQR(students$math)
lower <- math_q1 - 1.5 * math_iqr
upper <- math_q3 + 1.5 * math_iqr

outliers <- students |>
  filter(math < lower | math > upper) |>
  select(id, class, math)

cat("Normal Range:", lower, "-", upper, "\n")
cat("Number of outliers:", nrow(outliers), "\n")
print(head(outliers, 5))

# 7. Use summary() to view by subject
cat("\n=== Mathematics summary ===\n")
print(summary(students$math))

# 8. Use skimr for advanced report
library(skimr)
cat("\n=== skimr Report ===\n")
print(skim(students |> select(math, english, physics)))

# 9. Write a report
write_csv(students, "student_report.csv")
write_csv(class_stats, "class_stats.csv")
cat("\n=== The report has been generated ===\n")
▶ 試してみよう

期待される出力(抜粋):

R
=== Math Statistics for Each Class ===
# A tibble: 5 × 9
  class  Number of people Average Median Standard Deviation Highest Lowest    Q1    Q3   IQR
  <chr> <int> <dbl> <dbl>  <dbl> <int> <int> <dbl> <dbl> <dbl>
1 5Cls    201  81.0    81   12.0   114    44  72    90    18
2 1Cls    195  80.6    81   11.6   115    47  73    88    15
3 3Cls    203  79.8    80   11.8   110    49  71    88    17
4 2Cls    201  79.4    80   12.1   109    44  70    88    18
5 4Cls    200  79.1    79   12.4   116    45  70    89    19

❓ よくある質問

Q sd か var か?
A すべての単位について一貫して sd を使用してください
Q summary()skim()、どちらを選べばいいですか?
A summary は簡潔(6つの指標)で、skim は詳細(20以上の指標)です。
Q NA はどう扱うべきですか?
A NA をスキップするには、すべての関数に na.rm = TRUE を追加してください。そうしないと、NA を含むベクトルの結果はすべて NA になってしまいます。
Q 歪度と尖度はどうやって計算しますか?
A e1071::skewness()e1071::kurtosis() を使用します。歪度が 0 より大きい場合、分布は右偏りであり、0 より小さい場合は左偏りです。尖度が 0 より大きい場合、その分布は正規分布よりも尖っており、0 より小さい場合は、より平坦です。

📖 まとめ


📝 練習問題

  1. 基本問題:ベクトル x <- c(85, 90, 78, 92, 88, NA, 75, 95) を構築し、mean()median()sd()、および var() を用いて値を計算し(na.rm = TRUE に注意)、8つの結果を確認する。

  2. 基本演習summary()quantile(x, c(0, 0.25, 0.5, 0.75, 1)) を使用して、同じベクトルの統計指標を計算し、2つの結果を比較してください。

  3. 基本問題:データフレーム(3クラス × 5人の生徒 × 2科目:数学と英語)を作成し、dplyr::group_by + summarise + across を使用して、すべてのクラスの全科目について、1回の操作で平均値と標準偏差を計算してください。

  4. 応用演習:5つのコースに在籍する1,000人の学生の成績をシミュレートし、skimr::skim() を使用して完全なレポートを生成し、(IQR法を用いて)数学の得点における外れ値を特定し、外れ値の得点を持つ学生の割合を算出してください。

  5. 課題:ワークフローを完了させる—5つのコースに在籍する1,000人の学生の成績をシミュレートする:① 全体的な概要 ② クラスごとの概要 ③ 性別ごとの概要 ④ 順位付け ⑤ 外れ値の検出 ⑥ CSVレポートとMarkdown形式のテキストレポートを生成する(表の表示にはknitr::kable()を使用)。プロセスのスクリーンショットを保存する。

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%