2.4 리스트(list)

  • 리스트(list): (key, value) 형태로 데이터를 저장한 배열(벡터)
  • 서로 다른 데이터 타입을 가진 객체를 원소로 가질 수 있는 벡터
    • 예: 한 리스트 안에는 상이한 데이터 타입(숫자형, 문자형, 논리형 등)을 갖는 원소(객체)들을 포함할 수 있음

리스트 예시: 통계프로그래밍언어 중간고사 성적 테이블

  • 중간고사 성적 테이블은 이름, 학번, 출석률, 점수, 등급으로 이루어졌다고 가정하면 “김상자”의 성적 리스트는 다음과 같이 나타낼 수 있음
  • LIST(이름 = "김상자", 학번 = "202015115", 점수 = 95, 등급 = "A-")
  • 위 record에서 보듯이 문자형과 숫자형이 LIST 안에 같이 표현되고 있음

  • 위 record를 벡터 생성함수 c()로 생성한 경우
# 벡터로 위 record를 입력한 경우
vec <- c(`이름` = "김상자", `학번` = "202015115", 
         `점수` = 95, `등급` = "A-")
vec
       이름        학번        점수        등급 
   "김상자" "202015115"        "95"        "A-" 
typeof(vec)
[1] "character"

객체 명칭 규칙을 벗어나는 이름을 객제명으로 사용하고 싶다면 다음과 같이 홀따옴표 `object_name` 표시를 통해 사용 가능함

> #공백이 있는 이름을 객체 명칭으로 사용
> `golf score` <- c(75, 82, 92)
> `golf score`
[1] 75 82 92
> `3x` <- c(3, 6, 9, 12)
> `3x`
[1]  3  6  9 12

2.4.1 리스트 생성

  • list() 함수를 사용해 list 객체 생성
# list 함수 사용 prototype
list(name_1 = object_1, ..., name_m = object_m)

# name_1, ..., name_m: 리스트 원소 이름
# object_1, ..., object_m: 리스트 원소에 대응한 객체

  • 중간고사 성적 테이블 예시
# lst 객체 생성
lst <- list(`이름` = "김상자", 
            `학번` = "202015115", 
            `점수` = 95, 
            `등급` = "A-")
lst
$이름
[1] "김상자"

$학번
[1] "202015115"

$점수
[1] 95

$등급
[1] "A-"
# lst 내 객체의 데이터 타입 확인
# lapply(): lst 객체에 동일한 함수 적용 (추후 학습)
lapply(lst, typeof)
$이름
[1] "character"

$학번
[1] "character"

$점수
[1] "double"

$등급
[1] "character"

  • 리스트 원소에 이름이 부여된 경우 names()를 통해 확인 가능
names(lst)
[1] "이름" "학번" "점수" "등급"

  • 이름(name_1, .., name_n) 없이도 리스트 생성 가능하나, 가급적 이름을 부여 하는 것이 더 명확
list("김상자", "202015115", 95, "A-")
[[1]]
[1] "김상자"

[[2]]
[1] "202015115"

[[3]]
[1] 95

[[4]]
[1] "A-"

  • 리스트는 벡터이므로 vector() 함수를 통해 생성 가능
# 길이가 1이고 객체가 NULL인 리스트 생성
z <- vector(mode = "list", length=1)
z
[[1]]
NULL

  • 리스트의 값이 어떤 객체든 관계 없음
x <- list(name = c("A", "B", "C"), 
          salary = c(500, 450, 600), union = T)
x
$name
[1] "A" "B" "C"

$salary
[1] 500 450 600

$union
[1] TRUE

2.4.2 리스트 색인

  • 리스트에 포함된 객체에 접근는 기본적으로 벡터의 색인 방법과 동일하게 색인 번호 또는 키(이름)을 통해 접근 가능
  • 리스트에 포함된 모든 객체의 원소값을 쉽게 확인하는 함수는 unlist()
lval <- unlist(x)
typeof(lval)
[1] "character"

Table 2.5: 리스트 데이터 접근 방법
색인방법 동작
x$name 리스트 x 에서 객체명(name)에 해당하는 객체에 접근
x[[i]] 또는 x[[name]] 리스트 x 에서 i 번째 또는 name에 해당하는 객체 반환
x[i] 또는 x[name] 리스트 x 에서 i 번째 또는 name에 해당하는 부분 리스트 반환

  • x$name을 통해 리스트 내 객체 접근
lst$`학번`
[1] "202015115"

  • x[[i]] 또는 x[[name]] 을 통해 리스트 내 객체 접근
lst[[2]]
[1] "202015115"
z <- lst[["학번"]]
z
[1] "202015115"
typeof(z)
[1] "character"

  • x[i] 또는 x[name] 을 통해 리스트 내 부분 리스트 추출
lst[2]
$학번
[1] "202015115"
j <- lst["학번"]
j
$학번
[1] "202015115"
typeof(j)
[1] "list"

  • 리스트 또한 벡터로 볼 수 있기 때문에 여러 개의 부분 리스트 추출 가능
# 리스트 lst 에서 1 ~ 3 번째 까지 부분 리스트 추출
lst[1:3]
$이름
[1] "김상자"

$학번
[1] "202015115"

$점수
[1] 95

  • 리스트를 구성하는 객체 내 색인
x
$name
[1] "A" "B" "C"

$salary
[1] 500 450 600

$union
[1] TRUE
# salary에서 2-3번째 원소 추출
x$salary[2:3]
[1] 450 600
x[[2]][2:3]
[1] 450 600
x[["salary"]][2:3]
[1] 450 600
# 부분 리스트도 길이가 1인 리스트이므로, 
# 부분 리스트 내 객제 접근 시 리스트 접근이 선행
# x의 2번째 부분 리스트에서 첫 번째 객체의 2-3번째 원소 추출
x[2][[1]][2:3]
[1] 450 600

  • 리스트의 길이 반환: 벡터와 마찬가지로 length() 함수 적용 가능
length(lst); length(x)
[1] 4
[1] 3

2.4.3 리스트에 원소 추가/제거

  • 주어진 리스트 x에 새로운 원소를 x$new_obj <- value 명령어 형태로 추가
  • 이미 존재하고 있는 리스트 원소 제거는 x$exist_obj <- NULL 형태로 제거
# 리스트 lst 에 5회 차 퀴즈 점수 추가
lst$quiz <- c(10, 8, 9, 9, 8)

# 리스트 lst이 원소 quiz 제거
lst$quiz <- NULL
lst
$이름
[1] "김상자"

$학번
[1] "202015115"

$점수
[1] 95

$등급
[1] "A-"
# 벡터 색인을 이용해 원소 추가 가능
lst[[5]] <- c(10, 8, 9, 9, 8)
lst
$이름
[1] "김상자"

$학번
[1] "202015115"

$점수
[1] 95

$등급
[1] "A-"

[[5]]
[1] 10  8  9  9  8
# 부분 리스트 괄호에서도 색인 통해 추가/삭제 가능
lst[5] <- NULL
lst
$이름
[1] "김상자"

$학번
[1] "202015115"

$점수
[1] 95

$등급
[1] "A-"
# 여러 개의 리스트 동시 추가/삭제 가능
lst[5:9] <-  c(10, 8, 9, 9, 8)
lst
$이름
[1] "김상자"

$학번
[1] "202015115"

$점수
[1] 95

$등급
[1] "A-"

[[5]]
[1] 10

[[6]]
[1] 8

[[7]]
[1] 9

[[8]]
[1] 9

[[9]]
[1] 8
lst[5:9] <-  NULL
lst
$이름
[1] "김상자"

$학번
[1] "202015115"

$점수
[1] 95

$등급
[1] "A-"

2.4.4 리스트의 결합

  • 두 개 이상의 리스트를 결합 시 c() 사용
# 리스트 lst와 x 결합
c(lst, x)
$이름
[1] "김상자"

$학번
[1] "202015115"

$점수
[1] 95

$등급
[1] "A-"

$name
[1] "A" "B" "C"

$salary
[1] 500 450 600

$union
[1] TRUE

리스트 내에 리스트를 가질 수 있다. 이를 재귀 리스트(recursive list)라고 한다. 예를 들어 위 예제에서 각 학생의 성적 데이터가 리스트로 구성되어 있다면, 전체 성적 데이터베이스는 리스트로 구성된 리스트임. 아래 예제 처럼 간단한 재귀 리스트 구현이 가능

kim <- list(id = "20153345", sex = "Male", score = 85, grade = "B+")
lee <- list(id = "20153348", sex = "Female", score = 75, grade = "B0")

gr <- list(kim=kim, lee=lee)
gr
$kim
$kim$id
[1] "20153345"

$kim$sex
[1] "Male"

$kim$score
[1] 85

$kim$grade
[1] "B+"


$lee
$lee$id
[1] "20153348"

$lee$sex
[1] "Female"

$lee$score
[1] 75

$lee$grade
[1] "B0"