R 객체의 인덱싱과 슬라이싱
이 글은 2018~2019년에 작성한 R 기반 강의 노트를 옮긴 것입니다. 코드 일부는 현재 패키지 버전과 다를 수 있습니다.
객체별 인덱싱, 원소의 추가, 삭제 및 변경하기
- R은 대괄호(square brackets,
[])를 사용하여 원하는 객체에 대하여 특정 위치의 데이터를 찾고, 자를 수 있습니다. - 객체에 따라 인덱싱, 원소의 추가/삭제/변경하는 방법에 차이가 있습니다.
- 데이터 전처리 과정에서 가장 유용하게 사용되는 방법이므로 반드시 숙달하여야 합니다.
벡터
- 벡터는 1차원이므로, 대괄호 안에 위치에 해당하는 숫자 벡터를 할당합니다.
- 숫자 벡터 앞에
-기호를 넣으면 해당 조건에 맞는 요소들을 삭제합니다.
# 1에서 10의 정수를 갖는 벡터 a를 생성하고 결과를 출력합니다.
a <- letters[1:10]
print(a)
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
# 벡터 a의 3번째 데이터를 출력합니다.
print(a[3])
## [1] "c"
# 벡터 a의 5번째 데이터를 출력합니다.
print(a[5])
## [1] "e"
# 벡터 a의 3, 5번째 데이터를 출력합니다.
print(a[c(3, 5)])
## [1] "c" "e"
# 벡터 a의 마지막 데이터를 출력합니다.
# length() 함수는 벡터의 길이를 반환해줍니다.
print(length(a))
## [1] 10
print(a[length(a)])
## [1] "j"
# 벡터 a의 11번째 위치에 새로운 원소를 추가하고 출력합니다.
a[11] <- "A"
print(a)
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "A"
# 벡터 a의 1번째 원소를 제거하고 출력합니다.
a <- a[-1]
print(a)
## [1] "b" "c" "d" "e" "f" "g" "h" "i" "j" "A"
# 벡터 a의 10번째 원소 "A"를 "B"로 변경하고 출력합니다.
a[10] <- "B"
print(a)
## [1] "b" "c" "d" "e" "f" "g" "h" "i" "j" "B"
행렬
- 행렬은 2차원이므로, 대괄호 안에 컴마(,)를 구분자로 2개의 숫자 벡터를 할당합니다.
- 앞의 숫자 벡터로는 행을 찾고, 뒤의 숫자 벡터로는 열을 찾습니다.
- 특정한 숫자를 입력하지 않으면 해당 행 또는 열 전체를 인식합니다.
# 1부터 12의 정수를 갖는 벡터로 3행 4열을 갖는 행렬 b를 생성합니다.
b <- matrix(data = 1:12, nrow = 3)
print(b)
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
# 행렬 b의 1행 전체를 출력합니다.
print(b[1, ])
## [1] 1 4 7 10
# 행렬 b의 2열 전체를 출력합니다.
print(b[, 2])
## [1] 4 5 6
# 행렬 b의 1행, 2열을 출력합니다.
print(b[1, 2])
## [1] 4
# 행렬 b의 2~3행, 4열을 출력합니다.
print(b[c(2, 3), 4])
## [1] 11 12
# 행렬 b에 13~16인 값을 갖는 숫자 벡터를 행 기준으로 추가합니다.
# 이 때 rbind() 함수를 사용하여 행 추가를 할 수 있습니다.
# 단, 열의 수가 같아야 합니다.
b <- rbind(b, c(13:16))
print(b)
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
## [4,] 13 14 15 16
# 행렬 b에 20~23인 값을 갖는 숫자 벡터를 열 기준으로 추가합니다.
# 이 때 cbind() 함수를 사용하여 열 추가를 할 수 있습니다.
# 단, 행의 수가 같아야 합니다.
b <- cbind(b, c(20:23))
print(b)
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 4 7 10 20
## [2,] 2 5 8 11 21
## [3,] 3 6 9 12 22
## [4,] 13 14 15 16 23
# 행렬 b의 1행 전체를 삭제합니다.
b <- b[-1, ]
print(b)
## [,1] [,2] [,3] [,4] [,5]
## [1,] 2 5 8 11 21
## [2,] 3 6 9 12 22
## [3,] 13 14 15 16 23
# 행렬 b의 4열 전체를 삭제합니다.
b <- b[, -4]
print(b)
## [,1] [,2] [,3] [,4]
## [1,] 2 5 8 21
## [2,] 3 6 9 22
## [3,] 13 14 15 23
# 행렬 b의 1행 2열의 원소를 99로 변경합니다.
b[1, 2] <- 99
print(b)
## [,1] [,2] [,3] [,4]
## [1,] 2 99 8 21
## [2,] 3 6 9 22
## [3,] 13 14 15 23
배열
- 배열을 인덱싱할 때는 대괄호 안에 “행, 열, 층”의 순서로 위치를 지정합니다.
# 1~12 정수형 벡터를 2*3 행렬을 3층으로 쌓은 배열을 생성합니다.
c <- array(1:12, c(2, 3, 3))
print(c)
## , , 1
##
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
##
## , , 2
##
## [,1] [,2] [,3]
## [1,] 7 9 11
## [2,] 8 10 12
##
## , , 3
##
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
# 1번째 행렬의 1열 2행에 속하는 원소를 출력합니다.
print(c[1, 2, 1])
## [1] 3
# 2번째 행렬의 1~2열 2~3행에 속하는 원소를 출력합니다.
print(c[1:2, 2:3, 2])
## [,1] [,2]
## [1,] 9 11
## [2,] 10 12
# 3번째 행렬을 모두 삭제합니다.
c <- c[, , -3]
print(c)
## , , 1
##
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
##
## , , 2
##
## [,1] [,2] [,3]
## [1,] 7 9 11
## [2,] 8 10 12
# 모든 행렬의 3열의 원소를 99로 변경합니다.
c[, 3, ] <- 99
print(c)
## , , 1
##
## [,1] [,2] [,3]
## [1,] 1 3 99
## [2,] 2 4 99
##
## , , 2
##
## [,1] [,2] [,3]
## [1,] 7 9 99
## [2,] 8 10 99
데이터프레임
- 데이터프레임 인덱싱은 행렬과 유사합니다.
- 인덱스를 지정하는 방법에 따라 출력되는 속성이 서로 다릅니다.
# 먼저 3개의 열을 갖는 데이터프레임을 생성합니다.
a <- 1:10
b <- letters[1:10]
c <- rep(c(T, F), 5)
d <- data.frame(num = a, cha = b, log = c)
print(d)
## num cha log
## 1 1 a TRUE
## 2 2 b FALSE
## 3 3 c TRUE
## 4 4 d FALSE
## 5 5 e TRUE
## 6 6 f FALSE
## 7 7 g TRUE
## 8 8 h FALSE
## 9 9 i TRUE
## 10 10 j FALSE
# 1행 전체를 출력합니다. (데이터프레임)
print(d[1, ])
## num cha log
## 1 1 a TRUE
# 2열 전체를 출력합니다. (벡터)
print(d[, 2])
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
# 1행, 2열에 속하는 원소를 출력합니다. (벡터)
print(d[1, 2])
## [1] "a"
# 1, 5행 전체를 출력합니다. (데이터프레임)
print(d[c(1, 5), ])
## num cha log
## 1 1 a TRUE
## 5 5 e TRUE
# 1, 3열 전체를 출력합니다. (데이터프레임)
print(d[, c(1, 3)])
## num log
## 1 1 TRUE
## 2 2 FALSE
## 3 3 TRUE
## 4 4 FALSE
## 5 5 TRUE
## 6 6 FALSE
## 7 7 TRUE
## 8 8 FALSE
## 9 9 TRUE
## 10 10 FALSE
# 컬럼명이 num인 열 전체를 출력합니다. (벡터)
print(d$num)
## [1] 1 2 3 4 5 6 7 8 9 10
# 컬럼명이 cha인 열의 1~5번째 원소만 출력합니다. (벡터)
print(d$cha[1:5])
## [1] "a" "b" "c" "d" "e"
# 컬럼명이 log인 열의 6~10번째 원소만 출력합니다. (벡터)
print(d$log[6:10])
## [1] FALSE TRUE FALSE TRUE FALSE
# 컬럼명이 num인 열 전체를 출력합니다.
print(d[, 1])
## [1] 1 2 3 4 5 6 7 8 9 10
print(d[, "num"])
## [1] 1 2 3 4 5 6 7 8 9 10
# 데이터프레임 객체를 컴마(,) 없이 인덱싱할 경우 컬럼명으로 인식되며
# 결과 객체는 데이터프레임 속성을 갖습니다.
print(d[1])
## num
## 1 1
## 2 2
## 3 3
## 4 4
## 5 5
## 6 6
## 7 7
## 8 8
## 9 9
## 10 10
print(d["num"])
## num
## 1 1
## 2 2
## 3 3
## 4 4
## 5 5
## 6 6
## 7 7
## 8 8
## 9 9
## 10 10
# 데이터프레임은 리스트이므로 아래와 같이 인덱싱을 하면 벡터를 출력합니다.
print(d[[1]])
## [1] 1 2 3 4 5 6 7 8 9 10
# 컬럼명이 num, cha인 열 전체를 출력합니다.
# 인덱스를 지정하는 방법에 따라 출력되는 속성이 서로 다릅니다.
print(d[, c(1, 2)])
## num cha
## 1 1 a
## 2 2 b
## 3 3 c
## 4 4 d
## 5 5 e
## 6 6 f
## 7 7 g
## 8 8 h
## 9 9 i
## 10 10 j
print(d[, c("num", "cha")])
## num cha
## 1 1 a
## 2 2 b
## 3 3 c
## 4 4 d
## 5 5 e
## 6 6 f
## 7 7 g
## 8 8 h
## 9 9 i
## 10 10 j
# 데이터프레임 객체를 컴마(,) 없이 인덱싱할 경우 컬럼명이 지정됩니다.
print(d[c("num", "cha")])
## num cha
## 1 1 a
## 2 2 b
## 3 3 c
## 4 4 d
## 5 5 e
## 6 6 f
## 7 7 g
## 8 8 h
## 9 9 i
## 10 10 j
print(d[c(1, 2)])
## num cha
## 1 1 a
## 2 2 b
## 3 3 c
## 4 4 d
## 5 5 e
## 6 6 f
## 7 7 g
## 8 8 h
## 9 9 i
## 10 10 j
# 2열 전체를 데이터프레임으로 가져온 후, 그 데이터프레임의 1~5열을 출력합니다.
# d[2]는 데이터프레임이므로 뒤에 오는 대괄호 안에 컴마(,)가 추가되어야 합니다.
print(d[2][1:5, ])
## [1] "a" "b" "c" "d" "e"
# 2번 전체를 벡터로 가져온 후, 그 벡터의 1~5번째 원소를 출력합니다.
# d[[2]]는 벡터이므로 뒤에 오는 대괄호 안에 컴마(,)가 없어야 합니다.
print(d[[2]][1:5])
## [1] "a" "b" "c" "d" "e"
# 데이터프레임에 열과 행을 추가할 때, 행렬과 같은 방식을 사용하면 됩니다.
# 행 기준으로 추가하려면 rbind() 함수를 사용합니다.
d <- rbind(d, c(11, "k", TRUE))
print(d)
## num cha log
## 1 1 a TRUE
## 2 2 b FALSE
## 3 3 c TRUE
## 4 4 d FALSE
## 5 5 e TRUE
## 6 6 f FALSE
## 7 7 g TRUE
## 8 8 h FALSE
## 9 9 i TRUE
## 10 10 j FALSE
## 11 11 k TRUE
# 열 기준으로 추가하려면 cbind() 함수를 사용합니다.
d <- cbind(d, add = seq(from = 1, to = 10, length.out = 11))
print(d)
## num cha log add
## 1 1 a TRUE 1.0
## 2 2 b FALSE 1.9
## 3 3 c TRUE 2.8
## 4 4 d FALSE 3.7
## 5 5 e TRUE 4.6
## 6 6 f FALSE 5.5
## 7 7 g TRUE 6.4
## 8 8 h FALSE 7.3
## 9 9 i TRUE 8.2
## 10 10 j FALSE 9.1
## 11 11 k TRUE 10.0
# 11행 전체를 삭제합니다.
d <- d[-11, ]
print(d)
## num cha log add
## 1 1 a TRUE 1.0
## 2 2 b FALSE 1.9
## 3 3 c TRUE 2.8
## 4 4 d FALSE 3.7
## 5 5 e TRUE 4.6
## 6 6 f FALSE 5.5
## 7 7 g TRUE 6.4
## 8 8 h FALSE 7.3
## 9 9 i TRUE 8.2
## 10 10 j FALSE 9.1
# 3열 전체를 삭제합니다.
d <- d[, -3]
print(d)
## num cha add
## 1 1 a 1.0
## 2 2 b 1.9
## 3 3 c 2.8
## 4 4 d 3.7
## 5 5 e 4.6
## 6 6 f 5.5
## 7 7 g 6.4
## 8 8 h 7.3
## 9 9 i 8.2
## 10 10 j 9.1
# 5행, 2열에 속하는 원소를 NA로 변경합니다.
d[5,2] <- NA
print(d)
## num cha add
## 1 1 a 1.0
## 2 2 b 1.9
## 3 3 c 2.8
## 4 4 d 3.7
## 5 5 <NA> 4.6
## 6 6 f 5.5
## 7 7 g 6.4
## 8 8 h 7.3
## 9 9 i 8.2
## 10 10 j 9.1
리스트
- 리스트 객체를 인덱싱할 때는 홑대괄호(
[])와 겹대괄호([[]])에 따라 결과가 다릅니다. - 홑대괄호를 사용하면, 리스트로 출력합니다.
- 겹대괄호를 사용하면, 해당 원소의 속성대로 출력합니다.
# 다양한 속성을 가진 객체들을 생성합니다.
a <- 1:8
b <- letters[1:12]
c <- rep(c(T, F), 3)
d <- list(num = a, cha = b, log = c)
# 위에서 생성한 객체들을 원소로 갖는 리스트를 생성합니다.
# 리스트는 리스트를 원소로 가질 수 있습니다.
e <- list(a, b, c, d)
print(e)
## [[1]]
## [1] 1 2 3 4 5 6 7 8
##
## [[2]]
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
##
## [[3]]
## [1] TRUE FALSE TRUE FALSE TRUE FALSE
##
## [[4]]
## [[4]]$num
## [1] 1 2 3 4 5 6 7 8
##
## [[4]]$cha
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
##
## [[4]]$log
## [1] TRUE FALSE TRUE FALSE TRUE FALSE
# 리스트 e의 2번째 원소를 리스트로 출력합니다.
print(e[2])
## [[1]]
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
# 리스트 e의 2번째 원소를 원래 속성인 벡터로 출력합니다.
print(e[[2]])
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
# 위 벡터의 1~5번째 원소들을 출력합니다.
print(e[[2]][1:5])
## [1] "a" "b" "c" "d" "e"
# 리스트 e의 4번째 원소를 리스트로 출력합니다.
print(e[[4]])
## $num
## [1] 1 2 3 4 5 6 7 8
##
## $cha
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
##
## $log
## [1] TRUE FALSE TRUE FALSE TRUE FALSE
# 리스트 e의 4번째 원소인 리스트에서 다시 2번째 원소를 벡터로 출력합니다.
print(e[[4]][[2]])
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
# 위 벡터의 1~5번째 원소들을 출력합니다.
print(e[[4]][[2]][1:5])
## [1] "a" "b" "c" "d" "e"
# 리스트 e에 새로운 원소를 추가합니다.
e[[5]] <- c("가", "나", "다", "라")
print(e)
## [[1]]
## [1] 1 2 3 4 5 6 7 8
##
## [[2]]
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
##
## [[3]]
## [1] TRUE FALSE TRUE FALSE TRUE FALSE
##
## [[4]]
## [[4]]$num
## [1] 1 2 3 4 5 6 7 8
##
## [[4]]$cha
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
##
## [[4]]$log
## [1] TRUE FALSE TRUE FALSE TRUE FALSE
##
##
## [[5]]
## [1] "가" "나" "다" "라"
# 리스트 e의 4번째 요소를 삭제합니다.
e <- e[-4]
print(e)
## [[1]]
## [1] 1 2 3 4 5 6 7 8
##
## [[2]]
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
##
## [[3]]
## [1] TRUE FALSE TRUE FALSE TRUE FALSE
##
## [[4]]
## [1] "가" "나" "다" "라"
# 리스트 e의 1번째 요소를 변경합니다.
e[[1]] <- 11:18
print(e)
## [[1]]
## [1] 11 12 13 14 15 16 17 18
##
## [[2]]
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
##
## [[3]]
## [1] TRUE FALSE TRUE FALSE TRUE FALSE
##
## [[4]]
## [1] "가" "나" "다" "라"