12 minute read

이 글은 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] "가" "나" "다" "라"

Updated: