404 Not Found

404 Not Found


nginx

Rリスト:Rの「ユニバーサルコンテナ」

これまでの3回のレッスンでは、ベクトルと行列について学びましたが、これらはいずれもすべての要素が同じ型であることが求められます。しかし、実際には、データは異種混在していることがよくあります。例えば、学生情報には、学生ID(数値)、氏名(文字列)、成績(ベクトル)などが含まれます。Rでは、リストを用いて、このような異種混在データの格納という問題を解決します。

リストはRの真の「スイスアーミーナイフ」です。リストにはあらゆる型(ベクトル、行列、データフレーム、関数、さらには他のリストさえも)を格納できます。データフレーム data.frame は、本質的に「等長のベクトルのリスト」です。このレッスンはフェーズ1において極めて重要です。

1. 学習内容



2. 学生情報管理に関する話

(1) 課題:異種データの保存

イワンは人事部門で働いており、ある社員に関する完全な情報を保存する必要があります:

R
Employee ID:2024001(Numbers)
Name:Alice(Character)
Department:Data Analysis Department(Character)
Salary:15000(Numbers)
Skills:c("R", "Python", "SQL")(Character vector)

ベクトルを使用する場合、すべての要素は同じ型でなければなりません――うまくいきません。データフレームを使用する場合、各列の列数が同じでなければなりません――これもうまくいきません

(2) リストを用いた解法

R
# One list Fits all types
employee <- list(
  id = 2024001,
  name = "Alice",
  department = "Data Analysis Department",
  salary = 15000,
  skills = c("R", "Python", "SQL"),
  is_active = TRUE
)

# Access any field
employee$name           # [1] "Alice"
employee$skills[1]      # [1] "R"
employee$salary * 12    # [1] 180000  (Annual Salary)

異なる型の6つのフィールドを含む単一のリスト。これこそがRのリストの真骨頂です。



3. list(): リストを作成する

(1) 基本的な構文

R
list(key1 = value1, key2 = value2, ...)

(2) 創作のための5つの方法

R
# 1. List of Names(Most Commonly Used)
person <- list(name = "Alice", age = 25, scores = c(85, 90, 92))
person
# $name
# [1] "Alice"
# 
# $age
# [1] 25
# 
# $scores
# [1] 85 90 92

# 2. Anonymous List(Browse by Location)
unnamed <- list("a", 1, TRUE)
# [[1]] "a"
# [[2]] 1
# [[3]] TRUE

# 3. Nested Lists
company <- list(
  hr = list(name = "HR", count = 5),
  it = list(name = "IT", count = 20)
)

# 4. Empty list
empty <- list()
length(empty)  # [1] 0

# 5. Use list() to convert vector (Maintain Heterogeneity)
as.list(c(1, 2, 3))
# [[1]] 1
# [[2]] 2
# [[3]] 3

(3) リストとベクトルの比較

100%
graph TB
    A[R Data Structures] --> B[Vector<br/>Homogeneous<br/>One-dimensional]
    A --> C[Matrix<br/>Homogeneous<br/>Two-dimensional]
    A --> D[List<br/>Heterogeneous<br/>Any type]
    A --> E[Data Frame<br/>List of vectors of equal length<br/>Two-dimensional]
    
    style A fill:#fff3cd
    style B fill:#cce5ff
    style C fill:#d4edda
    style D fill:#f8d7da
    style E fill:#e1d4ff
物件 ベクター c(1, 2, 3) リスト list(1, "a", TRUE)
要素の種類 同一でなければならない 異なる場合もある
要素の種類 6つの基本タイプ 任意のRオブジェクト(関数やデータフレームを含む)
アクセス v[1] l[[1]]
可変長 ✅(必要に応じて追加・削除可能)
Pythonに似ている tuple dict / list


4. 4 アクセス方法(要点)

(1) ルックアップテーブルの4つの種類

メソッド 構文 戻り値 目的
[[i]] i番目の要素 要素そのもの 単一の要素を取得する
[i] i番目の要素 部分リスト 部分集合を取り出す
$name 名前で 要素自体 指定された要素を取得
[["name"]] 名称 要素自体 同等 $name

(2) [[ ]] 対 [ ]:主な違い

R
person <- list(name = "Alice", age = 25, scores = c(85, 90, 92))

# [[ ]] Return the element itself
person[[1]]
# [1] "Alice"  ← Character

# [ ] Return to Sublist
person[1]
# $name
# [1] "Alice"  ← Or a list

# Key Differences: Using [ ] after extraction, attempting to access sub-elements may cause an error
person[1]$name  # ✅ $name Still accessible(Syntax sugar)
person[1][1]    # ❌ This is the 1 element,But there is only one child list $name

# Practical Application:Calculate the average score
mean(person[[3]])      # [1] 89  ← [[3]] Extract the vector
mean(person$scores)    # [1] 89  ← $scores Extract the vector
mean(person[3])        # Error: need numeric data
⚠️ 注意要素にアクセスするには [[ ]] または $ を、部分集合にアクセスするには [ ] を使用してください。これは、R でリストにアクセスする際に最も分かりにくい点です。

(3) $ 対 [["name"]]

R
# $ is syntactic sugar for [[ "name" ]]
person$name           # Equivalent person[["name"]]
person[["name"]]      # Equivalent person$name

# $ Supports partial matches(Not recommended)
person$na             # Automatically matched to "name"
# [1] "Alice"

# [[ ]] Partial matches are not supported(Safer)
person[["na"]]        # Error
💡 ヒント: 本番環境のコードには [[ "name" ]] を使用してください—明確で曖昧さがなく、部分一致に依存しません。

(4) ネストされたリストへのアクセス

R
company <- list(
  hr = list(name = "HR", count = 5, head = "Alice"),
  it = list(name = "IT", count = 20, head = "Bob")
)

# Accessing Nested Elements
company$hr$head                  # [1] "Alice"
company[["it"]][["head"]]        # [1] "Bob"
company$it$count                 # [1] 20


5. リスト内の項目の変更、追加、削除

(1) 要素を変更する

R
person <- list(name = "Alice", age = 25)

# Edit ([[ ]] or $ both can be changed)
person$age <- 26
person[["age"]]
# [1] 26

# Batch Edit
person$age <- person$age + 1
person$age  # [1] 27

(2) 要素を追加する

R
# Methods 1: Use $ to add
person$email <- "alice@example.com"

# Methods 2: Use [[ ]] to add
person[["phone"]] <- "13800000000"

# Methods 3: Use c() to merge
person <- c(person, address = "Haidian District, Beijing")

(3) 要素の削除

R
# Assign NULL to delete
person$phone <- NULL

# Or
person[["address"]] <- NULL

(4) リストの構造を確認する

R
# View Structure(Important Debugging Functions)
str(person)
# List of 4
#  $ name    : chr "Alice"
#  $ age     : num 27
#  $ email   : chr "alice@example.com"
#  $ address : chr "Haidian District, Beijing"

# View All Names
names(person)
# [1] "name" "age" "email" "address"


6. lapply(): リストのバッチ処理

(1) なぜ lapply を使うのか?

リスト内の要素の型は異なる場合があるため、単に sum() mean() のように記述することはできません。lapply 関数を使用すると、各要素に関数を適用することができます:

R
mixed_list <- list(
  numbers = 1:5,
  chars = c("a", "b", "c"),
  logical = c(TRUE, FALSE, TRUE)
)

# Calculate the length of each element
lapply(mixed_list, length)
# $numbers
# [1] 5
# 
# $chars
# [1] 3
# 
# $logical
# [1] 3

(2) lapply + カスタム関数

R
# CalculateFor each element,"Abstract"
summary_list <- lapply(mixed_list, function(x) {
  if (is.numeric(x)) {
    return(list(mean = mean(x), sum = sum(x)))
  } else {
    return(list(length = length(x), class = class(x)))
  }
})

summary_list$numbers
# $mean
# [1] 3
# 
# $sum
# [1] 15

(3) sapply() を用いた結果の簡略化

R
# lapply Back to List,sapply Simplify to a vector
sapply(mixed_list, length)
# numbers    chars  logical 
#       5        3        3


7. リストの結合:c() と unlist()

(1) c() リストの結合

R
# Merge Multiple Lists
list1 <- list(a = 1, b = 2)
list2 <- list(c = 3, d = 4)

merged <- c(list1, list2)
merged
# $a 1
# $b 2
# $c 3
# $d 4

(2) unlist() はベクトルに展開される

R
# Flatten the list into a vector(Only for"Atom"Element Valid)
numbers_list <- list(a = 1, b = 2, c = 3)
unlist(numbers_list)
# a b c
# 1 2 3

# Note:The type will be coerced after flattening.
mixed <- list(1, "a", TRUE)
unlist(mixed)
# [1] "1"    "a"    "TRUE"  ← Convert All to Strings


8. list2env(): リストを環境に変換する

リスト内の各要素をグローバル変数に変換します:

R
config <- list(
  host = "localhost",
  port = 3306,
  user = "root",
  password = "secret"
)

# Convert list elements to environment variables
list2env(config, envir = .GlobalEnv)

# You can use it right away
host    # [1] "localhost"
port    # [1] 3306
⚠️ 注意list2env() はグローバル環境を汚染する可能性があるため、使用には注意が必要です。これは主に、YAML や JSON から設定を読み込む場面で使用されます。



9. 一般的な操作の比較

(1) c() 対 list() 対 unlist()

関数 目的 入力 → 出力
c() 原子要素の組み合わせ c(1, 2, 3) → ベクトル
list() 異種コンテナの作成 list(1, "a") → リスト
unlist() リストをベクトルに変換する unlist(list(1,2,3)) → ベクトル

(2) リストをDataFrameに変換する

R
# A list of vectors of equal length can be converted data.frame
df <- as.data.frame(list(
  name = c("A", "B", "C"),
  age = c(20, 25, 30),
  score = c(85, 90, 78)
))
print(df)
#   name age score
# 1    A  20    85
# 2    B  25    90
# 3    C  30    78
💡 ヒント: データフレームとは、本質的に「同じ長さのベクトルのリスト」です。これについては、次のレッスンでさらに詳しく見ていきます。



10. 完全な例:従業員記録の管理

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

▶ サンプル:従業員ファイルの管理

R
# ============================================
# Employee File Management
# Features:Manage with Lists 3 Complete information about each employee
# ============================================

# 1. Create 3 List of employees
employees <- list(
  alice = list(
    id = 2024001,
    name = "Alice",
    department = "Data Analysis Department",
    salary = 15000,
    skills = c("R", "Python", "SQL"),
    projects = c("User Profiles", "Sales Forecast")
  ),
  bob = list(
    id = 2024002,
    name = "Bob",
    department = "Engineering Department",
    salary = 18000,
    skills = c("Java", "Go", "Docker"),
    projects = c("API Refactoring", "Microservice Migration")
  ),
  charlie = list(
    id = 2024003,
    name = "Charlie",
    department = "Product Department",
    salary = 20000,
    skills = c("Figma", "Axure"),
    projects = c("V2.0 Design", "User Research")
  )
)

# 2. View a specific employee's full profile
cat("=== Alice Full Information ===\n")
str(employees$alice)
# List of 6
#  $ id         : num 2024001
#  $ name       : chr "Alice"
#  $ department : chr "Data Analysis Department"
#  $ salary     : num 15000
#  $ skills     : chr [1:3] "R" "Python" "SQL"
#  $ projects   : chr [1:2] "User Profiles" "Sales Forecast"

# 3. Use sapply for batch processing
cat("\n=== Annual Salaries of All Employees ===\n")
annual_salaries <- sapply(employees, function(emp) emp$salary * 12)
print(annual_salaries)
#    alice      bob  charlie 
#   180000   216000   240000

# 4. Use sapply to count skills
cat("\n=== Number of skills per employee ===\n")
skill_counts <- sapply(employees, function(emp) length(emp$skills))
print(skill_counts)
#    alice      bob  charlie 
#        3         3         2

# 5. Use split for grouping by department
cat("\n=== Grouped by Department ===\n")
dept_groups <- split(
  sapply(employees, function(emp) emp$name),
  sapply(employees, function(emp) emp$department)
)
print(dept_groups)
# $Data Analysis Department
# [1] "Alice"
# 
# $Engineering Department
# [1] "Bob"
# 
# $Product Department
# [1] "Charlie"

# 6. Add a New Employee
employees$diana <- list(
  id = 2024004,
  name = "Diana",
  department = "Data Analysis Department",
  salary = 16000,
  skills = c("R", "Tableau"),
  projects = c("Data Visualization")
)

cat("\n=== Add Diana after ===\n")
cat("Total Number of Employees:", length(employees), "\n")
cat("Diana Department:", employees$diana$department, "\n")

# 7. Identify the employee with the highest salary
top_salary <- which.max(sapply(employees, function(emp) emp$salary))
cat("\nHighest Salary:", names(employees)[top_salary], "(", max(sapply(employees, function(emp) emp$salary)), "USD)\n")

# 8. Retrieve the skills of all employees(Merge all skill vectors)
all_skills <- unlist(lapply(employees, function(emp) emp$skills))
cat("\n=== Company-wide Skills Summary ===\n")
print(table(all_skills))
# all_skills
#   Axure  Docker    Figma      Go    Java   Python       R     SQL Tableau 
#       1       1       1       1       1       1       2       1       1
▶ 試してみよう

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

R
=== Alice Full Information ===
List of 6
 $ id         : num 2024001
 $ name       : chr "Alice"
 ...

=== Annual Salaries of All Employees ===
   alice      bob  charlie 
  180000   216000   240000 

=== Company-wide Skills Summary ===
all_skills
  Axure  Docker  Figma      Go   Java  Python     R   SQL Tableau 
      1       1       1       1       1       1       2       1       1 

❓ よくある質問

Q: [[ ]][ ] の違いは何ですか? A: [[ ]] は要素そのものを返します(これに対してさらに操作を行うことができます)。一方、[ ] は部分リストを返します(その要素に対してはそれ以上の操作を行うことはできません)。要素を取得するには [[ ]] または $ を、部分集合を取得するには [ ] を使用します。これは R の構文において最も分かりにくい点の一つです。

Q: $[[ "name" ]] は同じものですか? A: 基本的には同等です。ただし、$ は部分一致をサポートしています($na は「name」を自動的に一致させます)が、[[ ]] はサポートしていません。本番環境のコードでは、[[ "name" ]] を使用する方が安全です。

Q: リストとベクトルの関係はどのようなものですか? A: ベクトルは同質で1次元(すべての要素が同じ型)であるのに対し、リストは異質で、任意の次元を持つことができます(要素は任意の型であることができます)。data.frame 本質的に、リストとは「等長のベクトルのリスト」です。リストを理解することは、データフレームを理解することにつながります。

Q: lapply()sapply() のどちらを選べばよいですか? A: lapply() は(構造を保持したまま)リストを返しますが、sapply() は結果をベクトルまたは行列に簡略化します(読みやすくなります)。日常的なタスクには sapply を、関数型プログラミングのパイプラインには lapply を使用してください。

Q: unlist() いつ使用すべきですか? A: リストをベクトルに「フラット化」するためです。ただし、フラット化できるのは単一型の要素のみです。型が混在している場合は、型変換が行われます(例:list(1, "a") → c("1", "a"))。


📖 まとめ


📝 練習問題

  1. 基本演習student という名前のリストを作成し、その中に 4 つのフィールドを含めます:name(文字)、age(数値)、scores(値 c(85, 90, 92) のベクトル)、および passed(ブール値)。リストの構造 (str()) を出力し、name および scores[2] にアクセスしてください。

  2. 基本問題:3つのサブリスト fathermotherchild(それぞれが nameage を含む)を含むネストされたリスト family を作成してください。child$age にアクセスして、その値を出力してください。

  3. 基本問題lapply() を使用して、3人の従業員(自分で作成したもの)のリストに対する「年収」(salary * 12)を一括計算し、sapply() を使用して結果をベクトル出力に簡略化してください。

  4. 応用問題:名前付きリスト(id、name、dept、salary、skills=空のベクトル、is_active=TRUEを含む)を返す関数 create_employee(name, dept, salary) を記述してください。この関数を3回呼び出して3人の従業員を作成し、それらを大きなリストに格納してください。さらに、sapply() を使用して、全従業員の「年収」を抽出してください。

  5. 課題:「図書館」の管理をシミュレートするスクリプトを作成してください:① 3冊の本を含むリスト library を作成します(各本には、titleauthoryearavailable の4つのフィールドがあります); ② lapply を使用して、すべての書籍の available の値を FALSE(貸出中)に設定する; ③ sapply を使用して、貸出可能なすべての書籍を検索する (available == TRUE); ④ リストに新しい書籍を追加する。

Web-Tutorial.com

Web-Tutorial 技術チーム

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

100%