재현가능한 과학적 분석을 위한 R

데이터 부분집합

학습 목표

  • 벡터, 요인, 행렬, 리스트, 데이터프레임 부분집합을 뽑아낼 수 있다.
  • 개별, 다수 요소를 다음 기준으로 뽑아낼 수 있다:
    • 색인
    • 명칭
    • 비교 연산을 사용
  • 다양한 자료구조로부터 요소를 건너뛰거나 제거할 수 있다.

R에는 강력한 부분집합 연산자를 다수 구비되어 있다. 이를 완전히 익히게 되면 어떤 유형의 데이터셋에 대해서도 복잡한 연산을 수월하게 수행할 수 있게 된다.

어떤 유형의 객체에서 부분집합을 뽑아낼 수 있는 방식은 6가지가 있다. 다른 자료구조에 대한 부분집합을 뽑아내는 연산자는 3가지가 있다.

R의 핵심으로 가장 많은 일은 하는 것부터 시작해본다: 원자 벡터(atomic vector)

x <- c(5.4, 6.2, 7.1, 4.8, 7.5)
names(x) <- c('a', 'b', 'c', 'd', 'e')
x
  a   b   c   d   e 
5.4 6.2 7.1 4.8 7.5 

이제 작업할 준비가 마루타 벡터를 생성했다. 해당 벡터 내용물을 손에 넣는 방식은 무엇인가?

색인을 사용한 요소 접근

벡터 요소를 추출하는데, 대응되는 색인을 부여하는데, 1부터 시작된다:

x[1]
  a 
5.4 
x[4]
  d 
4.8 

꺾쇠 괄호 연산자는 다른 어떤 함수와 비슷한다. 원자 벡터(그리과 행렬)에 대해, “n번째 요소를 뽑아낸다”라는 의미다.

한번에 다수 요소를 뽑아낼 수도 있다:

x[c(1, 3)]
  a   c 
5.4 7.1 

혹은, 벡터 슬라이스로 뽑아낼 수도 있다:

x[1:4]
  a   b   c   d 
5.4 6.2 7.1 4.8 

: 연산자는 왼쪽 요소부터 우측 요소까지 연속된 숫자를 생성한다. 예를 들어, x[1:4]x[c(1,2,3,4)]와 동등하다:

x[c(1,1,3)]
  a   a   c 
5.4 5.4 7.1 

벡터를 벗어난 숫자를 뽑아내려고 하면, R은 결측값을 반환한다:

x[6]
<NA> 
  NA 

길이 1을 갖는 벡터로 NA가 담겨있고, 명칭도 NA다.

0번째 요소를 뽑아내려고 하면, 공벡터가 반환된다:

x[0]
named numeric(0)

요소 건너뛰고 제거하기

벡터 색인으로 음수를 사용하면, R은 명세된 숫자를 제외한 모든 요소를 반환한다:

x[-2]
  a   c   d   e 
5.4 7.1 4.8 7.5 

다수 요소를 건너뛸 수도 있다:

x[c(-1, -5)]  # 혹은 x[-c(1,5)]
  b   c   d 
6.2 7.1 4.8 

벡터에서 요소를 제거하려면, 결과를 다시 벡터에 대입할 필요가 있다:

x <- x[-4]
x
  a   b   c   e 
5.4 6.2 7.1 7.5 

도전 과제 1

다음과 같이 코드가 주어졌다:

x <- c(5.4, 6.2, 7.1, 4.8, 7.5)
names(x) <- c('a', 'b', 'c', 'd', 'e')
print(x)
  a   b   c   d   e 
5.4 6.2 7.1 4.8 7.5 
  1. 다음 출력결과를 산출하는 적어도 서로 다른 명령어 3개 제시한다:
  b   c   d 
6.2 7.1 4.8 
  1. 작업결과를 옆 사람과 비교한다. 서로 다른 전략을 취했나요?

명칭으로 부분집합 뽑아내기

색인 대신에 명칭을 사용해서, 요소를 뽑아낼 수 있다:

x[c("a", "c")]
  a   c 
5.4 7.1 

명칭을 사용한 것이 객체에 대한 부분집합을 뽑아내는 훨씬 더 신뢰성 있는 방식이다: 다양한 요소 위치는 부분집합을 뽑아내는 연산자를 연결해서 적용할 때 종종 변경되지만, 명칭은 항상 동일하게 남게 마련이다!

불행하게도, 그다지 수월하게 요소를 건너뛰거나 제거할 수는 없다.

요소 하나를 건너뛰거나 제거하려면:

x[-which(names(x) == "a")]
  b   c   d   e 
6.2 7.1 4.8 7.5 

which 함수는 함수 인자의 모든 TRUE 요소에 대한 색인을 반환한다. 함수에 전달되기 전에 표현식이 평가됨을 기억한다. 내부를 파고들어, 어떤 일이 진행되는지 명확히 알아보자.

다음이 가장 먼저 진행된다:

names(x) == "a"
[1]  TRUE FALSE FALSE FALSE FALSE

조건 연산자는 x 벡터에 대한 모든 명칭에 적용된다. 첫번째 명칭만 “a” 라서, 해당 요소만 참(TRUE)이 된다.

그리고 나면, which가 이를 색인으로 변환한다:

which(names(x) == "a")
[1] 1

첫번째 요소만 참(TRUE)이라서, which는 1을 반환한다. 이제 색인을 갖게 되서, 건너뛰는 연산이 동작한다. 왜냐하면 음수 색인이기 때문이다!

명칭을 갖는 다수 색인을 건너뛰는 것도 유사하다. 하지만, 다른 비교 연산자를 사용한다:

x[-which(names(x) %in% c("a", "c"))]
  b   d   e 
6.2 4.8 7.5 

%in% 비교연산자는 좌측 인자(이번 경우에, x 명칭)에 대한 각 요소를 훑는다. 그리고 나서, “해당 요소가 두번째 인자에 나타나는가?”라고 질의한다.

도전과제 2

다음 코드를 실행해서 x 벡터를 정의한다.

x <- c(5.4, 6.2, 7.1, 4.8, 7.5)
names(x) <- c('a', 'b', 'c', 'd', 'e')
print(x)
  a   b   c   d   e 
5.4 6.2 7.1 4.8 7.5 

x 벡터가 주어지면, 다음 명령어는 어떤 작업을 수행할 것으로 예상되는가?

x[-which(names(x) == "g")]

상기 명령어를 시도해보고, 실행결과를 살펴본다. 여러분의 예상과 일치하는가? 왜 이런 결과가 나왔을까? (Tip: 여러분이 직접 작성한 것처럼 한땀한땀 명령어 각각을 테스트한다 - 매우 유용한 디버깅 전략이다.)

다음 중 어떤 것이 사실인가:

    1. which에 전달되는 TRUE값이 없다면, 공벡터가 반환된다.
    1. which에 전달되는 TRUE값이 없다면, 오류 메시지가 나타난다.
    1. integer()는 공벡터다.
    1. 공벡터를 부정하면 “모든” 벡터를 만들어낸다.
    1. x[]x[integer()]와 동일한 결과를 산출한다.
x <- 1:3
x
[1] 1 2 3
names(x) <- c('a', 'a', 'a')  
x
a a a 
1 2 3 
x['a']  # 첫번째 값만 반환한다.
a 
1 
x[which(names(x) == 'a')]  # 세가지 값 모두 반환한다.
a a a 
1 2 3 

그러면, 이전처럼 == 연산자는 왜 사용할 수 없을까? 매우 좋은 질문이다.

비교에 해당되는 항목만 살펴보자:

names(x) == c('a', 'c')
Warning in names(x) == c("a", "c"): 두 객체의 길이가 서로 배수관계에 있지
않습니다
[1]  TRUE FALSE  TRUE

분명히, “c”는 x 요소명칭 중에 존재한다. 그런데, 왜 동작을 하지 않을까? ==%in% 과는 다소 다른방식으로 동작한다. ==은 좌측 인자 요소 각각을 대응되는 우측 요소 각각과 비교한다.

== 연산자를 모사한 것이 다음에 나와 있다:

c("a", "b", "c", "e")  # x 명칭
   |    |    |    |    # ==으로 요소들을 비교한다.
c("a", "c")

한 벡터가 다른 벡터보다 작은 경우, 해당 벡터는 재사용된다:

c("a", "b", "c", "e")  # x 명칭
   |    |    |    |    # ==으로 요소들을 비교한다.
c("a", "c", "a", "c")

이런 경우, R이 단순히 c("a", "c")을 두번 반복한다. 더 긴 벡터가 더 짧은 벡터의 배수가 아닌 경우, R은 경고 메시지도 출력한다:

names(x) == c('a', 'c', 'e')
[1]  TRUE FALSE FALSE

==%in% 차이점을 숙지하는 것이 중요한데, 이유는 탐지가 어렵고 미묘한 버그가 스며들 수 있기 때문이다!

논리 연산자를 통한 부분집합 뽑아내기

더 단순하게는 논리 연산자로 부분집합을 뽑아낼 수도 있다:

x[c(TRUE, TRUE, FALSE, FALSE)]
a a 
1 2 

이번 경우, 논리 벡터는 부분집합을 뽑아내는 벡터 길이만큼 재사용됨에 주목한다!

x[c(TRUE, FALSE)]
a a 
1 3 

비교 연산자는 논리벡터로 평가되기 때문에, 간결하게 벡터 부분집합을 뽑아내는데 사용할 수도 있다:

x[x > 7]
named integer(0)

도전과제 3

다음 코드가 주어졌다:

x <- c(5.4, 6.2, 7.1, 4.8, 7.5)
names(x) <- c('a', 'b', 'c', 'd', 'e')
print(x)
  a   b   c   d   e 
5.4 6.2 7.1 4.8 7.5 

x 벡터에서 4보다 크고 7보다 적은 값을 부분집합으로 뽑아내는 명령어를 작성한다.

특수값 처리하기

어느 지점에 다다르면, R 함수에 처리할 수 없는 결측값, 무한값, 정의되지 않는 값을 갖는 데이터와 마주하게 된다.

이런 유형의 데이터를 필터링하는데 사용되는 특수 함수가 있다:

  • is.na는 벡터, 행렬, 데이터프레임에 포함된 NA 위치를 반환한다.
  • 마찬가지로, is.nanis.infinite 함수도 NaNInf 값에 대한 동일한 작업을 수행한다.
  • is.finite 함수는 NA, NaN, Inf 값을 포함하지 않는 벡터, 행렬, 데이터프레임에 대한 모든 위치정보를 반환한다.
  • na.omit는 벡터에서 모든 결측값을 필터링해서 제외시키다.

요인 부분집합으로 뽑아내기

지금까지 벡터 부분집합을 뽑아내는 다양한 방식을 탐색했다. 다른 자료구조에 대한 부분집합은 어떻게 뽑아낼 수 있을까?

요인 부분집합 뽑아내기는 벡터 부분집합 뽑아내기와 동일한 방식으로 동작한다.

f <- factor(c("a", "a", "b", "c", "c", "d"))
f[f == "a"]
[1] a a
Levels: a b c d
f[f %in% c("b", "c")]
[1] b c c
Levels: a b c d
f[1:3]
[1] a a b
Levels: a b c d

중요한 주의점 하나는 건너뛰는 요소가 설사 해당 범주가 요인으로 존재하지 않더라도, 수준(level)을 제거하지 않는다는 점이다:

f[-3]
[1] a a c c d
Levels: a b c d

행렬 부분집합 뽑아내기

행렬의 경우도 [ 함수를 사용해서 부분집합을 뽑아낸다. 이번 경우에는 인자를 두개 사용한다: 첫번째 인자는 행에 적용되고, 두번째 인자는 칼럼에 적용된다:

set.seed(1)
m <- matrix(rnorm(6*4), ncol=4, nrow=6)
m[3:4, c(3,1)]
            [,1]       [,2]
[1,]  1.12493092 -0.8356286
[2,] -0.04493361  1.5952808

첫번째 혹은 두번째 인자를 공백으로 남겨놓을 수도 있는데, 모든 행 혹은 칼럼을 각각 불러올 경우 사용한다:

m[, c(3,4)]
            [,1]        [,2]
[1,] -0.62124058  0.82122120
[2,] -2.21469989  0.59390132
[3,]  1.12493092  0.91897737
[4,] -0.04493361  0.78213630
[5,] -0.01619026  0.07456498
[6,]  0.94383621 -1.98935170

행 혹은 칼럼 하나만 접근하고자 하면, R이 자동으로 결과값을 벡터로 전환시킨다:

m[3,]
[1] -0.8356286  0.5757814  1.1249309  0.9189774

결과값을 행렬로 그대로 유지하고자 한다면, 세번째 인자를 명세할 필요가 있다; drop = FALSE:

m[3, , drop=FALSE]
           [,1]      [,2]     [,3]      [,4]
[1,] -0.8356286 0.5757814 1.124931 0.9189774

벡터와 달리, 행렬 외부 행과 칼럼을 접근하고자 하면, R이 오류를 던진다:

m[, c(3,6)]
Error in m[, c(3, 6)]: 첨자의 허용 범위를 벗어났습니다

행렬을 까면 정말 자료형이 벡터라서, 단지 인자 하나로만 부분집합을 추출할 수도 있다:

m[5]
[1] 0.3295078

보통 유용하지는 않다. 하지만, 행렬이 열우선형식(column-major format)으로 기본디폴트 설정으로 되어있음에 주목한다. 즉, 벡터 요소가 칼럼방향으로 배열된다는 것을 의미한다:

matrix(1:6, nrow=2, ncol=3)
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

행렬을 행우선으로 쭉 펼치고자 한다면, byrow=TRUE를 사용한다:

matrix(1:6, nrow=2, ncol=3, byrow=TRUE)
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6

행과 칼럼 색인 대신에 행명칭(rownames)과 열명칭(column names)을 사용해서 배열 부분집합을 뽑아낼 수 있다.

도전과제 4

다음과 같은 코드가 주어졌다:

m <- matrix(1:18, nrow=3, ncol=6)
print(m)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    4    7   10   13   16
[2,]    2    5    8   11   14   17
[3,]    3    6    9   12   15   18
  1. 다음 중 어떤 명령어가 값 11과 14를 추출하는 하는가?

A. m[2,4,2,5]

B. m[2:5]

C. m[4:5,2]

D. m[2,c(4,5)]

리스트 부분집합 뽑아내기

이제 몇가지 새로운 부분집합을 뽑아내는 연산자를 소개한다. 리스트 부분집합을 뽑아내는데 사용되는 함수가 세가지 있다; 원자벡터와 행렬에서 살펴본 [, 그리고 [[, $이 있다.

[을 사용하면, 항상 리스트만 반환한다. 리스트 부분집합을 뽑아내고자 하지만, 요소는 뽑아내고 싶지 않다면, 아마도 [ 연산자를 사용할 것이다.

xlist <- list(a = "Software Carpentry", b = 1:10, data = head(iris))
xlist[1]
$a
[1] "Software Carpentry"

상기 명령어는 요소 하나만 갖는 리스트를 반환한다.

[ 연산자를 사용해서 원자벡터에 적용한 그대로 리스트 요소를 부분집합으로 뽑아낼 수 있다. 하지만, 리스트가 재귀적으로 되어 있지 않다면, 비교 연산자는 동작하지 않는다. 이유는 비교 연산자가 데이터 구조 내부 개별 요소가 아닌, 리스트 각 요소에 내재한 자료구조로 되어있기 때문이다.

xlist[1:2]
$a
[1] "Software Carpentry"

$b
 [1]  1  2  3  4  5  6  7  8  9 10

리스트 개별 요소를 추출하려면, 이중 꺾쇠 함수를 사용한다: [[.

xlist[[1]]
[1] "Software Carpentry"

이제 결과값이 리스트가 아닌 벡터에 주목한다.

한번에 요소 하나이상을 추출할 수는 없다:

xlist[[1:2]]
Error in xlist[[1:2]]: 첨자의 허용 범위를 벗어났습니다

요소를 건너뛰는 것도 사용할 수 없다:

xlist[[-1]]
Error in xlist[[-1]]: 한 개 이상의 구성요소 선택을 시도합니다

하지만, 명칭을 사용해서 요소에 대한 부분집합으로 뽑아내거나, 요소를 추출할 때 사용할 수 있다:

xlist[["a"]]
[1] "Software Carpentry"

$ 함수는 명칭으로 요소를 뽑아내는데 사용되는 초간편 방법이다:

xlist$data
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

도전 과제 5

다음 리스트가 주어졌다:

xlist <- list(a = "Software Carpentry", b = 1:10, data = head(iris))

리스트와 벡터 부분집합을 추출하는 지식을 활용해서, xlist에서 숫자 2를 추출한다. 힌트: 숫자 2는 리스트 “b” 항목 내부에 담겨있다.

도전 과제 6

선형 모형이 다음과 같이 주어졌다:

mod <- aov(pop ~ lifeExp, data=gapminder)

잔차 자유도를 추출하라. 힌트: attributes() 함수가 도움을 줄 것이다.

데이터프레임

데이터프레임을 까면 내부는 리스트로 구성된 것을 기억한다. 그래서 유사한 규칙이 적용된다. 하지만, 데이터프레임도 2차원 객체다:

[함수에 인자를 하나만 넣으면 리스트와 동일하게 동작한다. 즉, 각 리스트 요소는 칼럼에 대응된다. 작업결과 나오는 객체는 데이터프레임이다:

head(gapminder[3])
       pop
1  8425333
2  9240934
3 10267083
4 11537966
5 13079460
6 14880372

유사하게, [[ 함수는 칼럼 한개만 추출하는데 동작된다:

head(gapminder[["lifeExp"]])
[1] 28.801 30.332 31.997 34.020 36.088 38.438

명칭으로 칼럼을 추출하는데 사용되는 편리한 단축어가 $이다:

head(gapminder$year)
[1] 1952 1957 1962 1967 1972 1977

인자가 두개 있는 경우, [ 함수는 행렬에 대해서와 마찬가지로 동작한다:

gapminder[1:3,]
      country year      pop continent lifeExp gdpPercap
1 Afghanistan 1952  8425333      Asia  28.801  779.4453
2 Afghanistan 1957  9240934      Asia  30.332  820.8530
3 Afghanistan 1962 10267083      Asia  31.997  853.1007

행 하나만 부분집합으로 뽑아내면, 결과는 데이터프레임이 되는데 이유는 각 요소가 혼합된 자료형으로 구성되었기 때문이다:

gapminder[3,]
      country year      pop continent lifeExp gdpPercap
3 Afghanistan 1962 10267083      Asia  31.997  853.1007

하지만, 단일 칼럼에 대해서 결과는 벡터다. drop = FALSE를 세번째 인자로 넣으면 바꿀 수 있다.

도전과제 7

데이터프레임 부분집합을 뽑아내는 오류가 다음에 나와 있는데 이를 버그없이 수정하라:

  1. 1957년에 수집된 관측점을 뽑아내라.
gapminder[gapminder$year = 1957,]
  1. 1에서 4를 제외한 모든 칼럼을 뽑아내라.
gapminder[,-1:4]
  1. 기대수명이 80세 이상 되는 행을 추출하라.
gapminder[gapminder$lifeExp > 80]
  1. 첫번째 행과 4번째 5번째 칼럼(lifeExp, gdpPercap)을 뽑아내라. .
gapminder[1, 4, 5]
  1. 고급: 2002년과 2007년에 대한 정보를 담고 있는 행을 추출하라.
gapminder[gapminder$year == 2002 | 2007,]

도전과제 8

  1. gapminder[1:20] 명령어는 왜 오류를 반환하는가? gapminder[1:20,]와 어떻게 다른가?

  2. gapminder_small이라는 데이터프레임을 생성하는데 1에서 9까지 행과 19에서 23까지 행만 포함한다. 이 작업을 하나 혹은 두 단계로 작성한다.

도전과제 해답

도전과제 1에 대한 해답

다음과 같은 코드가 주어졌다:

x <- c(5.4, 6.2, 7.1, 4.8, 7.5)
names(x) <- c('a', 'b', 'c', 'd', 'e')
print(x)
  a   b   c   d   e 
5.4 6.2 7.1 4.8 7.5 
  1. 다음 출력결과를 산출하는 적어도 서로 다른 명령어 3개를 제시한다:
  b   c   d 
6.2 7.1 4.8 
x[2:4] 
x[-c(1,5)]
x[c("b", "c", "d")]
x[c(2,3,4)]

도전과제 2에 대한 해답

다음 코드를 실행해서 x 벡터를 정의한다.

x <- c(5.4, 6.2, 7.1, 4.8, 7.5)
names(x) <- c('a', 'b', 'c', 'd', 'e')
print(x)
  a   b   c   d   e 
5.4 6.2 7.1 4.8 7.5 

x 벡터가 주어지면, 다음 명령어는 어떤 작업을 수행할 것으로 예상되는가?

x[-which(names(x) == "g")]

상기 명령어를 시도해보고, 실행결과를 살펴본다. 여러분의 예상과 일치하는가? 왜 이런 결과가 나왔을까? (Tip: 여러분이 직접 작성한 것처럼 한땀한땀 명령어 각각을 테스트한다 - 매우 유용한 디버깅 전략이다.)

다음 중 어떤 것이 사실인가:

    1. which에 전달되는 TRUE값이 없다면, 공벡터가 반환된다.
    1. which에 전달되는 TRUE값이 없다면, 오류 메시지가 나타난다.
    1. integer()는 공벡터다.
    1. 공벡터를 부정하면 “모든” 벡터를 만들어낸다.
    1. x[]x[integer()]와 동일한 결과를 산출한다.

정답: A 와 C 가 맞다.

which 명령어는 입력값에 대한 모든 TRUE 값에 대한 색인을 반환한다. names(x) == "g"은 어떤 TRUE값도 반환하지 않는다. which 명령어에 전달되는 어떤 TRUE 값도 없기 때문에, 공벡터를 반환했다. 음수 부호로 벡터를 부정한다고 의미가 변경되지는 않는다. x 벡터에서 값을 가져오는데 공벡터를 사용했기 때문에, 빈 숫자벡터를 만들어 낸다. 결과는 named numeric 공벡터다. 이유는 x 벡터 자료형이 “named numeric”인데, 명칭을 값에 대입했기 때문이다(str(x)을 시도해 보라).

도전과제 4에 대한 해답

다음과 같은 코드가 주어졌다:

m <- matrix(1:18, nrow=3, ncol=6)
print(m)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    4    7   10   13   16
[2,]    2    5    8   11   14   17
[3,]    3    6    9   12   15   18
  1. 다음 중 어떤 명령어가 값 11과 14를 추출하는 하는가?

A. m[2,4,2,5]

B. m[2:5]

C. m[4:5,2]

D. m[2,c(4,5)]

정답: D

도전과제 5에 대한 해답

다음 리스트가 주어졌다:

xlist <- list(a = "Software Carpentry", b = 1:10, data = head(iris))

리스트와 벡터 부분집합을 추출하는 지식을 활용해서, xlist에서 숫자 2를 추출한다. 힌트: 숫자 2는 리스트 “b” 항목 내부에 담겨있다.

xlist$b[2]
xlist[[2]][2]
xlist[["b"]][2]

도전과제 6에 대한 해답

선형 모형이 다음과 같이 주어졌다:

mod <- aov(pop ~ lifeExp, data=gapminder)

잔차 자유도를 추출하라. 힌트: attributes() 함수가 도움을 줄 것이다.

attributes(mod) ## `df.residual` is one of the names of `mod`
mod$df.residual

도전과제 7에 대한 해답

데이터프레임 부분집합을 뽑아내는 오류가 다음에 나와 있는데 이를 버그없이 수정하라:

  1. 1957년에 수집된 관측점을 뽑아내라.
# gapminder[gapminder$year = 1957,]
gapminder[gapminder$year == 1957,]
  1. 1에서 4를 제외한 모든 칼럼을 뽑아내라.
# gapminder[,-1:4]
gapminder[,-c(1:4)]
  1. 기대수명이 80세 이상 되는 행을 추출하라.
# gapminder[gapminder$lifeExp > 80]
gapminder[gapminder$lifeExp > 80,]
  1. 첫번째 행과 4번째 5번째 칼럼(lifeExp, gdpPercap)을 뽑아내라. .
# gapminder[1, 4, 5]
gapminder[1, c(4, 5)]
  1. 고급: 2002년과 2007년에 대한 정보를 담고 있는 행을 추출하라.
# gapminder[gapminder$year == 2002 | 2007,]
gapminder[gapminder$year == 2002 | gapminder$year == 2007,]
gapminder[gapminder$year %in% c(2002, 2007),]

도전과제 8에 대한 해답

  1. gapminder[1:20] 명령어는 왜 오류를 반환하는가? gapminder[1:20,]와 어떻게 다른가?

정답: gapminder는 데이터프레임이다. 그래서 차원 2개로 부분집합을 뽑아낼 필요가 있다. gapminder[1:20, ]는 첫번째부터 20번째 모든 행과 모든 칼럼을 부분집합으로 뽑아낸다.

  1. gapminder_small이라는 데이터프레임을 생성하는데 1에서 9까지 행과 19에서 23까지 행만 포함한다. 이 작업을 하나 혹은 두 단계로 작성한다.
gapminder_small <- gapminder[c(1:9, 19:23),]