404 Not Found

404 Not Found


nginx

Rのデータフレームとファクター:tidyverseを用いたデータサイエンスの基礎

これまでの9回のレッスンでは、ベクトル、行列、リストについて学びましたが、これらにはそれぞれ限界があります。データフレーム(data.frame)は、これらの問題をすべて解決してくれます。Excelのスプレッドシートのように読みやすく、行列と同じくらい効率的です。このレッスンでは、Rの真の「主役」であるデータフレームについて学びます。

データフレームとtidyverseは、Rを用いたデータサイエンスの中核をなしています。このレッスンから、いよいよ「Rを用いたデータ分析」の世界に本格的に踏み込んでいきます。

1. 学習内容



2. ExcelをRに変換した話

(1) 課題:Excelでは対応できない

陳氏の市場調査用スプレッドシートは、10,000行×8列で構成されています:

R
EmployeesID  Name  Department    Salary   Years Performance Gender Start Date
2024001 Alice  Data Department  15000  3    A   M  2021-03-15
2024002 Bob  Engineering Department  18000  5    A+  M  2019-08-20
...

「部署」ごとの平均給与の算出、「業績」順の並べ替え、高収入の従業員の特定……。Excelでは、数式が複雑にネストされ、クラッシュしそうになるほどで、これらを行うのに30分もかかります。

(2) Rを用いた解決策

R
library(dplyr)

# 5 Code execution complete 5 An Analysis
df |>
  group_by(Department) |>
  summarise(Average Wage = mean(Salary), Number of people = n()) |>
  arrange(desc(Average Wage)) |>
  filter(Average Wage > 15000)

Excelで30分かかる作業を、たった5行のコードで。これこそがDataFrameとdplyrの真価です。



3. data.frame:Rの「主役」

(1) データフレームとは何ですか?

100%
graph TB
    A["Data Frame data.frame"] --> B["Each column = 1 equal-length vectors"]
    A --> C["Each line = 1 records"]
    A --> D["Mixed Types(Each column is independent)"]
    A --> E["The bottom layer is'A list of vectors of equal length'"]
    
    style A fill:#fff3cd
    style B fill:#cce5ff
    style C fill:#d4edda
    style D fill:#f8d7da
    style E fill:#e1d4ff

データフレームとは、「等長のベクトルのリスト」のことです:

(2) データフレームを作成する

R
# Methods 1:data.frame()(Basics R)
df <- data.frame(
  name = c("Alice", "Bob", "Charlie"),
  age = c(25, 30, 35),
  score = c(95, 88, 92),
  passed = c(TRUE, TRUE, TRUE)
)
print(df)
#       name age score passed
# 1    Alice  25    95   TRUE
# 2      Bob  30    88   TRUE
# 3 Charlie  35    92   TRUE

# Methods 2:tibble(tidyverse Version,Recommendations)
# install.packages("tibble")
library(tibble)
df2 <- tibble(
  name = c("Alice", "Bob", "Charlie"),
  age = c(25, 30, 35),
  score = c(95, 88, 92)
)
print(df2)

(3) data.frame と tibble の比較

機能 data.frame tibble
印刷 デフォルトですべての行を印刷(データ量が多い場合、システムがフリーズする可能性があります) デフォルトで最初の10行と列の型を印刷
列名 特殊文字のサポート 有効性の強制
部分集合の部分集合 df[, "col"] ベクトルを返す 常に tibble を返す
パフォーマンス 遅い 速い
文字列 デフォルトで因子に変換 文字列のまま保持
R
# View Structure
str(df)
# 'data.frame':	3 obs. of  4 variables:
#  $ name  : chr  "Alice" "Bob" "Charlie"
#  $ age   : num  25 30 35
#  $ score : num  95 88 92
#  $ passed: logi  TRUE TRUE TRUE

# Summary Statistics
summary(df)
#      name                age        score          passed
#  Length:3           Min.   :25   Min.   :88   Mode :logical
#  Class :character   1st Qu.:27   Median :92   TRUE:3
#  Mode  :character   Mean   :30   Mean   :91   NA's :0
#                     3rd Qu.:32   3rd Qu.:93
#                     Max.   :35   Max.   :95


4. DataFrameへのアクセス

(1) アクセス方法 4 つ

メソッド 構文 戻り値 目的
df[i, j] 行 i、列 j スカラー/ベクトル/データフレーム 行と列の組み合わせ
df[i, ] 行 i DataFrame 行を取得
df[, j] 列 j ベクトル(R標準) / データフレーム 列の抽出
df$name 列名 ベクトル 列の取得
df[["name"]] 列名 ベクトル 列の取得
R
df <- data.frame(
  name = c("Alice", "Bob", "Charlie"),
  age = c(25, 30, 35),
  score = c(95, 88, 92)
)

# Retrieve a single element
df[2, 3]              # [1] 88
df[2, "score"]        # [1] 88

# Select the entire row
df[1, ]               # Entire row (Data Frame)
#     name age score
# 1 Alice  25    95

# Round an entire column
df[, "age"]           # Digital Vectors [1] 25 30 35
df$age                # Ibid.
df[["age"]]           # Ibid.

(2) 論理インデックス(フィルター)

R
# Find the Fraction > 90 line
df[df$score > 90, ]
#       name age score
# 1    Alice  25    95
# 3 Charlie  35    92

# Multiple conditions
df[df$age > 25 & df$score > 85, ]

(3) ⚠️ 重要:ベースRとtibbleにおける列の取得の違い

R
# base R:Retrieve the column return vector
df[, "age"]           # [1] 25 30 35  ← Digital Vectors

# tibble:Retrieve and return the column tibble
library(tibble)
tb <- as_tibble(df)
tb[, "age"]           # ← tibble(1 row 1 col)

# Want to extract a vector from tibble: Use [[ ]] or $
tb[["age"]]           # [1] 25 30 35  ← Digital Vectors
⚠️ 注意:tibbleの[, "col"]自動的にベクトルに変換されません。これは「安全」を目的とした設計上の機能であり、大規模なデータフレームが誤ってベクトルと解釈され、出力全体がフリーズしてしまうのを防ぐためのものです。



5. データフレームの変更

(1) 列を追加する

R
# Use $ to add
df$city <- c("Beijing", "Shanghai", "Guangzhou")

# Use transform()
df <- transform(df, bonus = score * 100)

# Use within() to reference column names
df <- within(df, level <- ifelse(score >= 90, "A", "B"))

print(df)
#       name age score   city bonus level
# 1    Alice  25    95   Beijing  9500     A
# 2      Bob  30    88   Shanghai  8800     B
# 3 Charlie  35    92   Guangzhou  9200     A

(2) 列の変更

R
# Array Assignment
df$age <- df$age + 1

# Condition Modification
df$score[df$name == "Bob"] <- 90

(3) 列を削除する

R
# Assign NULL
df$bonus <- NULL
df$level <- NULL

(4) 行の追加・削除

R
# Add a row: Use rbind
new_row <- data.frame(name = "Diana", age = 28, score = 85, city = "Shenzhen")
df <- rbind(df, new_row)

# Delete Row:Using Negative Indexes
df <- df[-1, ]  # Delete 1st row


6. 因子:カテゴリ変数

(1) なぜ因子が必要なのか?

Rでは、カテゴリ変数(「低/中/高」など)を表す際に、factors を使用する方が、文字ベクトルを使用するよりも強力です:

R
# Character vector(Disorder)
gender_char <- c("M", "F", "M", "F", "M")

# factor(Orderly + Finite values)
gender_factor <- factor(gender_char, levels = c("M", "F"))
gender_factor
# [1] M F M F M
# Levels: M F

(2) ファクターの利点

100%
graph TB
    A["Character vector 'Low' 'Mid' 'High'"] --> B["factor factor<br/>+ levels Order<br/>+ Finite values<br/>+ Save memory"]
    A --> C["Disadvantages: Cannot sort and compare"]
    B --> D["Advantages: Can be compared for size<br/>Can be grouped in order<br/>Statistics/Knowing the Number of Categories in Modeling"]
    
    style A fill:#f8d7da
    style B fill:#d4edda
    style D fill:#cce5ff
# Compare Sizes(Characters cannot,Factors can)
sizes <- factor(c("S", "L", "Mid", "L", "S"),
                levels = c("S", "Mid", "L"),
                ordered = TRUE)

sizes[1] < sizes[2]   # TRUE  <- Characters can't do that!

(3) 因数に対する一般的な演算

R
# View levels
levels(sizes)
# [1] "S" "Mid" "L"

# Frequency Count
table(sizes)
# sizes
# S Mid L
#  2  1  2

# Reorder
sizes <- factor(sizes, levels = c("L", "Mid", "S"))  # Reverse the order
levels(sizes)
# [1] "L" "Mid" "S"
⚠️ 注意:tidyverseの時代においては、ファクターの処理にはforcatsパッケージ(第11課で解説)を使用することをお勧めします。これは、ベースRよりも洗練されているためです。

(4) データフレーム内の要因

R
# data.frame() Convert character strings to factors by default (This is a trap!)
df <- data.frame(
  name = c("Alice", "Bob"),  # Character vector
  stringsAsFactors = FALSE   # Disable Auto-Conversion(Recommendations)
)
str(df)
# $ name: chr "Alice" "Bob"  ← Preserve characters
💡 ヒント: Rの新バージョン(4.x)では、デフォルトで stringsAsFactors = FALSE が使用されますが、古いコードでは異なる値が使用されている可能性があります。明示的に stringsAsFactors = FALSE と記述することをお勧めします。



7. dplyr入門:データ処理の5つの基本

dplyr は tidyverse の核となる存在であり、5つの関数でデータ処理シナリオの80%をカバーしています:

(1) インストールと読み込み

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

(2) 5部構成の関数

関数 目的 対応するSQL
filter() 行のフィルタリング WHERE
select() 列を選択 SELECT
mutate() 列の追加・変更
arrange() 並べ替え ORDER BY
summarise() 集計統計 GROUP BY

(3) 連鎖演算子 |>

R
# |> is R 4.1+'s "pipe symbol", Pass the result from the previous step to the next step
df |> filter(age > 25) |> select(name, age)

(4) 実践編:従業員データの処理

R
# Prepare the data
employees <- tibble(
  id = 2024001:2024010,
  name = c("Alice", "Bob", "Charlie", "Diana", "Eve",
           "Frank", "Grace", "Henry", "Ivy", "Jack"),
  department = c("Data Department", "Engineering Department", "Data Department", "Product Department", "Engineering Department",
                "Data Department", "Engineering Department", "Product Department", "Data Department", "Engineering Department"),
  salary = c(15000, 18000, 16000, 20000, 17000,
            15500, 19000, 21000, 16500, 17500),
  years = c(3, 5, 4, 7, 4, 2, 6, 8, 3, 5),
  performance = factor(
    c("A", "A+", "B", "A+", "A", "B", "A", "A+", "B", "A"),
    levels = c("B", "A", "A+"),
    ordered = TRUE
  )
)

# 1. filter:Screening Data Department Employees
data_dept <- employees |> filter(department == "Data Department")

# 2. select:Select a subset of columns
basic_info <- employees |> select(name, department, salary)

# 3. mutate:Add an "Annual Salary" column
employees <- employees |> mutate(annual_salary = salary * 12)

# 4. arrange:Sort by salary in descending order
ranked <- employees |> arrange(desc(salary))

# 5. summarise:By Department
dept_stats <- employees |>
  group_by(department) |>
  summarise(
    Number of people = n(),
    Average Wage = mean(salary),
    Highest Salary = max(salary),
    Total Annual Salary = sum(annual_salary)
  ) |>
  arrange(desc(Average Wage))

print(dept_stats)
# # A tibble: 3 × 5
#   department Number of people Average Wage Highest Salary Total Annual Salary
#   `<chr>`    `<int>`    `<dbl>`    `<dbl>`  `<dbl>`
# 1 Product Department       2   20500    21000 492000
# 2 Engineering Department       4   17875    19000 858000
# 3 Data Department       4   15750    16500 756000

(5) 5段階の組み合わせの例

R
# Comprehensive Example:Identify High-Performing, High-Earning Employees
top_talent <- employees |>
  filter(performance %in% c("A+", "A")) |>     # Performance Screening A+ or A
  filter(salary > 16000) |>                     # ② Filter by High Salary
  mutate(salary_level = ifelse(salary > 18000, "High", "Upper-middle")) |>  # ③ Add Category
  arrange(desc(salary)) |>                      # ④ Sort
  select(name, department, salary, performance, salary_level)  # ⑤ Select Column

print(top_talent)
# # A tibble: 3 × 5
#   name   department salary performance salary_level
#   `<chr>`  `<chr>`       `<dbl>` `<ord>`       `<chr>`       
# 1 Henry  Product Department      21000 A+          High          
# 2 Diana  Product Department      20000 A+          High          
# 3 Bob    Engineering Department      18000 A+          Upper-middle


8. 完全な例:従業員データの包括的な分析

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

▶ サンプル:企業の従業員データの包括的な分析

R
# ============================================
# Comprehensive Analysis of Company Employee Data
# Features:Using a DataFrame + dplyr Comprehensive Analysis 10 employees
# ============================================

library(dplyr)

# 1. Prepare data
employees <- tibble(
  id = 2024001:2024010,
  name = c("Alice", "Bob", "Charlie", "Diana", "Eve",
           "Frank", "Grace", "Henry", "Ivy", "Jack"),
  department = c("Data Department", "Engineering Department", "Data Department", "Product Department", "Engineering Department",
                "Data Department", "Engineering Department", "Product Department", "Data Department", "Engineering Department"),
  salary = c(15000, 18000, 16000, 20000, 17000,
            15500, 19000, 21000, 16500, 17500),
  years = c(3, 5, 4, 7, 4, 2, 6, 8, 3, 5),
  performance = factor(
    c("A", "A+", "B", "A+", "A", "B", "A", "A+", "B", "A"),
    levels = c("B", "A", "A+"),
    ordered = TRUE
  )
)

cat("=== Raw Data ===\n")
print(employees)

# 2. View Structure
cat("\n=== Data Structures ===\n")
str(employees)

# 3. Summary Statistics
cat("\n=== Abstract ===\n")
summary(employees)

# 4. By Department
cat("\n=== By Department ===\n")
dept_summary <- employees |>
  group_by(department) |>
  summarise(
    Number of people = n(),
    Average Wage = mean(salary),
    Median Wage = median(salary),
    Highest Salary = max(salary),
    Minimum Wage = min(salary),
    Average Length of Service = round(mean(years), 1)
  ) |>
  arrange(desc(Average Wage))
print(dept_summary)

# 5. Identify High-Performing Employees (A+ or A)
cat("\n=== Employees with Outstanding Performance ===\n")
top_perf <- employees |>
  filter(performance %in% c("A+", "A")) |>
  arrange(desc(salary)) |>
  select(name, department, salary, performance, years)
print(top_perf)

# 6. Add"Pay Grade"col
cat("\n=== Salary Grade Classification ===\n")
employees <- employees |>
  mutate(
    salary_level = factor(
      ifelse(salary >= 18000, "High",
      ifelse(salary >= 16000, "Mid", "Low")),
      levels = c("Low", "Mid", "High"),
      ordered = TRUE
    ),
    annual_salary = salary * 12
  )

# By Pay Grade
level_summary <- employees |>
  group_by(salary_level) |>
  summarise(Number of people = n(), Average Wage = mean(salary))
print(level_summary)

# 7. Identify the Best Employees (High Salary + High Performance + Senior)
cat("\n=== Top Employee (High Salary + Outstanding Performance + Senior) ===\n")
top_talent <- employees |>
  filter(salary >= 17000, performance == "A+", years >= 5) |>
  select(name, department, salary, years, performance, annual_salary)
print(top_talent)
▶ 試してみよう

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

R
=== By Department ===
# A tibble: 3 × 7
  department  Number of people Average Wage Median Wage Highest Salary Minimum Wage Average Length of Service
  `<chr>`     `<int>`    `<dbl>`    `<dbl>`    `<dbl>`    `<dbl>`    `<dbl>`
1 Product Department        2   20500    20500    21000    20000      7.5
2 Engineering Department        4   17875    17750    19000    17000      4.5
3 Data Department        4   15750    15750    16500    15000      3  

=== Employees with Outstanding Performance ===
# A tibble: 6 × 5
  name   department salary performance years
  `<chr>`  `<chr>`       `<dbl>` `<ord>`       `<dbl>`
1 Henry  Product Department      21000 A+              8
2 Diana  Product Department      20000 A+              7
3 Bob    Engineering Department      18000 A+              5
4 Grace  Engineering Department      19000 A                6
5 Eve    Engineering Department      17000 A                4
6 Jack   Engineering Department      17500 A                5

❓ よくある質問

Q ファクターにはどのような利点がありますか?
A 主に3つの利点があります:① 大きさの比較が可能である(ordered = TRUE)② メモリを節約できる(整数エンコーディングのみを格納する)③ カテゴリ数が既知の場合、統計分析やモデリングが可能になる(「未知の値」の問題を回避できる)。

📖 まとめ


📝 練習問題

  1. 基本演習data.frame() を使用して、students というデータフレーム(学生 6 人 × 4 列:名前/年齢/得点/合格)を作成してください。データフレーム、str()、および summary() を出力し、3 行目のすべての列にアクセスしてください。

  2. 基本問題:前の問題の name 列を factor(3 段階)に変換し、as.character()as.numeric() の違いを比較する。この因子が大きさの比較(>)に対応していることを確認する。

  3. 基本問題dplyr をインストールして読み込み、filter() を使用して、前の問題で求めた students に基づいて score > 85 から学生を抽出します。その後、arrange() を使用して、得点の降順で並べ替えます。

  4. 応用演習tibble を使用して、sales データフレーム(10行×4列:製品/地域/数量/日付)を作成してください。① mutate() を使用して discount = amount * 0.1 の合計を算出する;② group_by(region) + summarise() を使用して各地域の総売上高を算出する;③ arrange(desc()) を使用して地域を順位付けする。

  5. 課題:模擬の従業員データ(従業員10名、3つの部署、給与・勤続年数・業績)を用いて、以下の7段階の分析を完了してください:① dplyrを読み込む ② 部署ごとの従業員数と平均給与を算出する ③ 勤続年数が5年以上で給与の高い従業員を特定する ④ mutate を使用して年俸の列を追加する ⑤ case_when(またはifelse)を使用して給与帯ごとに分類する ⑥ 業績順に並べ替える ⑦ 新しいデータフレームtop_employeesに書き出し、CSVファイルとして保存する(write.csv())。

Web-Tutorial.com

Web-Tutorial 技術チーム

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

100%