21 . R과 RStudio 소개

21.1 동기 모티브

과학은 다단계 과정이다: 실험을 설계하고 데이터를 수집하게 되면, 실제로 재미난 일이 시작된다. 이번 학습을 통해서 R과 RStudio를 사용해서 이런 과정을 시작하는 방법을 학습할 것이다. 원데이터(raw data)로 시작해서 탐색적 데이터 분석을 수행하고 분석결과를 시각화하는 방법을 학습할 것이다. 세월에 따른 국가별 인구 정보를 담고 있는 gapminder.org로부터 나온 데이터셋을 가지고 학습을 진행한다. 원데이터를 R로 불러올 수 있나요? 세네갈에 대한 인구를 시각화할 수 있나요? 아시아 대륙 국가에 대해 평균 소득을 계산할 수 있나요? 학습 말미에는 1분도 되지 않는 시간내에 모든 국가에 대해 인구수를 시각화할 수 있게 된다.

21.2 워크샵 시작 전에

노트북 컴퓨터에 최신 R과 RStudio가 설치되었는지 확인한다. 이것이 중요한데 이유는 설치된 R 버전이 최신이 아닌 경우 워크샵에 사용되는 팩키지가 제대로 설치되지 않거나 전혀 설치되지 않기 때문이다.

최신 R 버전 다운로드 RStudio 다운로드 및 설치

21.3 RStudio 소개

소프트웨어 카펜트리 R교육에 오신 것을 환영합니다.

이번 R 수업시간을 통해서, R 언어 기본기 뿐만 아니라 저녁이 있는 삶(make your life easier)을 가능토록 과학 프로젝트에 코드를 구조화하는 모범 활용사례도 교육한다.

도구로 RStudio 를 사용한다: 자유로이 사용가능하고, 무료이며, 오픈 소스 R과 통합된 개발 환경을 제공한다. RStudio는 편집기가 내장되어 있고, (서버 포함) 모든 플랫폼에서 동작하고, 버젼 제어 및 프로젝트 관리 같은 많은 앞선 기능을 제공한다.

기본 배치

RStudio를 처음 열게 되면, 창 3개가 반갑게 여러분을 맞이한다:

  • 인터랙티브 R 콘솔 : 좌측 전체
  • 작업공간(Workspace)/이력 (History) : 우측상단 탭
  • 파일(File)/그래프(Plot)/팩키지(Package)/도움말(Help): 우측하단 탭

RStudio 배치화면

R 스크립트 같은 파일을 열게 되면, 편집창이 좌측 상단에 열린다.

.R 파일을 연 RStudio 배치화면

21.4 RStudio 내부 작업흐름

RStudio 내부에서 작업하는 방식이 크게 두가지 있다.

  1. 인터랙티브 R 콘솔에서 테스트하고 가지고 놀다가, 나중에 실행할 .R 파일에 복사해서 붙여넣는다.
    • 초기 시작하고 작은 테스트를 할 때 잘 작동한다.
    • 신속하게 노동 집약적인 개발이 된다.
  2. .R 파일에서 작업을 시작하고, RStudio 명령어/단축키를 사용해서 현재 라인, 선택된 라인 혹은 변경된 라인을 인터랙티브 R 콘솔에 밀어넣어 실행한다.
    • 시작하는 매우 훌륭한 방식이다; 작성된 모든 코드가 나중에 저장된다.
    • RStudio 내부 혹은 R source() 함수를 사용해서 생성한 파일을 실행할 수 있다.

꿀팁: 코드 일부 실행하기

편집기 창에서 코드를 실행하는데 있어 상당한 유연성을 RStudio가 제공한다. 버튼, 메뉴, 키보드 단축키, 세가지 방식이 있다. 현재 라인을 실행하려면,

  1. 편집기창 상단 Run 버튼을 클릭한다.
  2. “Code” 메뉴에서 “Run Lines” 를 선택한다.
  3. 리눅스 혹은 윈도우에서 Ctrl+엔터(Ctrl+Return), 맥 OS X에서 Command+엔터(+Return) 단축키를 누른다. (단축키는 버튼 위에 마우스를 올리면 볼 수 있다).

코드 블록을 실행하려면, 코드 블록을 선택하고 나서, Run 버튼을 누른다. 방금전에 실행한 코드 블록 내부 일부 코드를 변경했다면, 다시 코드 블록을 선택하고, Run 버튼을 누를 필요가 없다. 바로 옆에 있는 버튼(Re-run the previous region)을 누르면 된다. 이 버튼은 방금전에 변경한 내용을 포함해서 이전 코드 블록을 실행시킨다.

21.5 R 소개

R에서 상당한 시간을 R 인터랙티브 콘솔에서 사용한다. 이곳이 여러분이 작성한 모든 코드를 실행하는 곳으로 R 스크립트 파일에 추가하기 전에, 아이디어를 시험하는 유용한 환경이다. RStudio 콘솔은 R 명령-라인 환경에서 입력하는 곳과 동일하다.

R 인터랙티브 세션에서 보게 되는 첫번째 사항은 정보가 쭉 나오고 나서, “>” 가 나타나고 커서가 깜빡인다. 여러가지 면에서, 쉘 수업시간에 학습한 쉘 환경과 유사하다: REPL 루프(읽고, 평가하고, 출력하는 루프) 기본 아이디어 위에서 동작한다. 명령어를 입력하면, R이 명령어를 실행하고 나서, 결과를 반환한다.

21.6 계산기로 R 사용하기

R로 할 수 있는 가장 간단한 것이 산수다:

1 + 100
## [1] 101

R이 “[1]” 다음에 정답을 출력한다. 지금 당장 “[1]”에 대해 걱정하지 말자. 나중에 설명이 나와 있다. 지금은 일단 출력결과를 지칭한다고 생각한다.

배쉬(bash) 처럼, 불완전한 명령어를 타이핑하면, R은 사용자가 명령어를 완성할 때까지 대기한다:

> 1 +
+

1+ 다음에 엔터를 치게되면, R 세션이 “>” 대신에 “+” 을 보여준다. 이것이 의미하는 바는 명령어가 완성될 때까지 대기한다는 것이다. 명령어를 취소하고자 한다면, 단순히 “Esc” 키를 치게 되면, 다시 “>” 프롬프트로 되돌아 간다.

꿀팁: 명령문 취소

RStudio가 아니고 R 명령-라인을 사용하고 있다면, 명령문을 취소하는데 ESC 대신에 Ctrl+C(Ctrl+C) 사용이 필요하다. 또한, 이런 사실은 맥 사용자에도 동일하게 적용된다!

명령어 취소는 불완성된 명령어를 종료시키는데 그다지 유용하지는 않다: 명령어 취소 기능을 실행되고 있는 코드를 멈추는데도 사용할 수 있다. (예를 들어, 예상한 것보다 훨씬 더 오래 시간이 소요되는 경우) 혹은 현재 작성하고 있는 코드를 제거할 때도 사용한다.

계산기로 R을 사용할 때, 연산 순위는 초중등학교에서 배운 것과 동일하다.

가장 우선순위가 높은 것부터 낮은 순서는 다음과 같다:

  • 괄호: (, )
  • 멱승: ^ or **
  • 나눗셈: /
  • 곱셈: *
  • 덧셈: +
  • 뺄셈: -
3 + 5 * 2
## [1] 13

괄호를 사용해서 연산작업을 한데 묶는데, 이유는 의도한 바를 명확히 하거나, 기본설정과 차이가 날 때 평가순서를 강제하기 위해서다.

(3 + 5) * 2
## [1] 16

꼭 필요하지 않을 때 괄호가 사용되면 읽기 힘들어 지기도 하지만, 의도를 명확히 한다. 나중에 여러분이 작성한 코드를 다른 사람이 읽게 됨을 기억하라.

(3 + (5 * (2 ^ 2))) # hard to read
3 + 5 * 2 ^ 2       # clear, if you remember the rules
3 + 5 * (2 ^ 2)     # if you forget some rules, this might help

상기 코드 각 라인 뒤에 텍스트를 “주석”이라고 부른다. 해쉬(혹은 번호기호)기호 # 다음에 오는 모든 것은 코드가 실행될 때 R에서 무시된다.

매우 작거나 큰 숫자는 과학 표기법을 따른다:

2/10000
## [1] 2e-04

상기 표기법은 10^XX 곱한 것을 축약한 것이다. 따라서, 2e-42 * 10^(-4)을 축약한 것이다.

숫자를 과학 표기법으로 작성할 수도 있다:

5e3  # Note the lack of minus here
## [1] 5000

21.7 수학 함수

R에는 수많은 내장 수학함수가 존재한다. 함수를 호출하려면, 함수명을 단순히 타이핑하고, 괄호를 열고 닫으면 된다. 괄호안에 타이핑하는 것을 함수 인자라고 부른다:

sin(1)  # 삼각함수
## [1] 0.841
log(1)  # 자연로그
## [1] 0
log10(10) # 지수가 10인 로그
## [1] 1
exp(0.5) # e^(1/2)
## [1] 1.65

R에 나온 함수 모두를 기억해야 된다는 걱정은 하지마라. 구글이나 네이버, 다음에서 검색하면 된다. 함수명 앞 글자를 기억하고 있다면 RStudio에서 탭 자동완성 기능을 사용한다.

탭 자동완성이 R 자체 엔진보다 RStudio가 우월성을 갖는 분야로, 자동완성 기능이 함수, 함수 인자, 함수가 전달받을 수 있는 값을 더 쉽게 찾을 수 있게 한다.

명령문 앞에 ?을 타이핑하고 엔터를 치면 해당 명령어에 대한 도움말 페이지가 열린다. 명령어에 대한 기술과 동작방식에 대한 정보를 제공할 뿐만 아니라, 도움말 페이지 하단으로 스크롤해서 쭉 내리면 해당 명령어 사용법을 시연하는 코드 예제가 나와 있다. 나중에 예제를 통해서 살펴볼 것이다.

21.8 다양한 객체 비교하기

R에서 비교 작업도 수행할 수 있다:

1 == 1  # 같음 ("is equal to"로 읽음)
## [1] TRUE
1 != 2  # 같지 않음 ("is not equal to"로 읽음)
## [1] TRUE
1 <  2  # 보다 작음
## [1] TRUE
1 <= 1  # 작거나 같음
## [1] TRUE
1 > 0  # 보다 큼
## [1] TRUE
1 >= -9 # 같거나 큼
## [1] TRUE

꿀팁: 숫자 비교

숫자 비교할 때 주의 사항: 정수가 아닌 경우, 절대로 == 비교를 사용하지 않는다. 정수는 구체적으로 자연수만 표현할 수 있는 자료형이다.

컴퓨터는 일정 정확도를 갖는 소수만 표현할 수 있다. 그래서, R로 출력할 때 같아 보이는 두 숫자는 사실 겉으로 드러나지 않는 표현이 다를 수 있다.

따라서, 작은 오차범위(컴퓨터 허용오차, Machine Numberic Tolerance)만큼 차이가 난다 대신에, all.equal 함수를 사용한다.

자세한 사항은 http://floating-point-gui.de/ 웹사이트 참조.

21.9 변수와 대입

할당 연산자(Assignment Operator), <-를 사용해서 변수에 값을 저장할 수 있다. 예를 들어:

x <- 1/40

변수에 할당하면, 값을 출력하지 않음에 유의한다. 대신에, 나중에 사용하려고 변수라는 곳에 저장한다. x 변수에는 0.025가 담겨있다:

x
## [1] 0.025

좀더 구체적으로, 저장된 값은 부동소수점 수라고 불리는 해당 분수를 소수 근사한 것이다.

RStudio 우측 상단 창에서 Environment 탭을 클릭하면, 변수x와 값이 저장된 것을 확인할 수 있다. 변수 x는 숫자가 예상되는 어떤 연산작업에도 숫자자리에 사용될 수 있다:

log(x)
## [1] -3.69

변수가 다시 할당될 수도 있음에 주목한다:

x <- 100

x 변수에 0.025 값이 담겼지만, 현재는 담긴 값이 100 이 된다.

변수에 대입되는 값에는 대입되는 변수도 포함될 수 있다:

x <- x + 1 # 우측 상단 탭에서 RStudio가 x에 대한 정보가 어떻게 바뀌는지 주목한다.

할당하는 우측편은 어떤 적법한 R 표현식도 될 수 있다. 우측편은 대입이 일어나기 전에 완전한 평가가 이루어 진다.

변수명에는 문자, 숫자, 밑줄, 구두점이 포함될 수 있다. 변수명이 숫자로 시작되거나, 공백이 있으면 안된다. 사람마다 긴 변수명에 대해 다른 관례를 사용한다. 다음에 관례가 나와있다.

  • 단어.사이.구두점
  • 단어_사이_밑줄
  • 낙타대문자 : camelCaseToSeparateWords

어떤 관례를 사용하든 여러분 취향이지만, 일관성을 유지하라.

변수에 대입할 때, 할당 = 연산자 사용도 가능하다:

x = 1/40

하지만, R 사용자 사이 그다지 많이 활용되지 않는다. 가장 중요한 것은 사용하는 연산자에 일관성 유지하라. = 보다 <-을 사용하는 것이 덜 혼동스러운 경우가 있고, 커뮤니티에서 가장 흔히 사용되는 기호다. 그래서 추천하는 것은 <- 이다.

21.10 도전과제 1

다음 중 적법한 R 변수명은 어느것인가?

min_height
max.height
_age
.mass
MaxLength
min-length
2widths
celsius2kelvin

도전과제 1 해답

다음 사례는 R 변수로 사용될 수 있다:

min_height
max.height
MaxLength
celsius2kelvin

다음은 숨은 변수를 생성한다:

.mass

다음은 변수를 생성하는데 사용할 수 없다:

_age
min-length
2widths

21.11 벡터화(Vectorization)

인지해야 되는 마지막 사항은 R은 벡터화되었다는 사실이다. 변수와 함수는 값으로 벡터를 갖을 수 있다는 의미다. 예를 들어,

1:5
## [1] 1 2 3 4 5
2^(1:5)
## [1]  2  4  8 16 32
x <- 1:5
2^x
## [1]  2  4  8 16 32

놀랍도록 강력한 기능이다; 이점에 대해, 다음 수업에서 좀더 깊이 다룰 예정이다.

21.12 환경 설정

R 세션과 상호작용할 때 사용되는 몇가지 유용한 명령어가 있다.

ls 명령어는 전역환경(작업하고 있는 R 세션)에 저장된 모든 변수와 함수 목록을 출력한다:

ls()
## [1] "con" "x"

꿀팀: 숨긴 객체

유닉스 쉘처럼, ls는 기본디폴트 설정으로 “.”으로 시작되는 함수와 변수를 숨긴다. 모든 객체 목록을 보려면, ls(all.names=TRUE) 타이핑하면 된다.

여기서 ls 명령어에 어떤 인자도 전달하지 않았음에 주목한다. 하지만, R에 함수를 호출하려면 괄호는 여전히 전달해야 된다.

ls만 그 자체로 타이핑하면, R은 해당 함수에 대한 소스코드만 출력한다!

ls
## function (name, pos = -1L, envir = as.environment(pos), all.names = FALSE, 
##     pattern, sorted = TRUE) 
## {
##     if (!missing(name)) {
##         pos <- tryCatch(name, error = function(e) e)
##         if (inherits(pos, "error")) {
##             name <- substitute(name)
##             if (!is.character(name)) 
##                 name <- deparse(name)
##             warning(gettextf("%s converted to character string", 
##                 sQuote(name)), domain = NA)
##             pos <- name
##         }
##     }
##     all.names <- .Internal(ls(envir, all.names, sorted))
##     if (!missing(pattern)) {
##         if ((ll <- length(grep("[", pattern, fixed = TRUE))) && 
##             ll != length(grep("]", pattern, fixed = TRUE))) {
##             if (pattern == "[") {
##                 pattern <- "\\["
##                 warning("replaced regular expression pattern '[' by  '\\\\['")
##             }
##             else if (length(grep("[^\\\\]\\[<-", pattern))) {
##                 pattern <- sub("\\[<-", "\\\\\\[<-", pattern)
##                 warning("replaced '[<-' by '\\\\[<-' in regular expression pattern")
##             }
##         }
##         grep(pattern, all.names, value = TRUE)
##     }
##     else all.names
## }
## <bytecode: 0x00000274c290f458>
## <environment: namespace:base>

rm 명령어를 사용해서 더이상 사용할 필요가 없는 객체를 삭제한다:

rm(x)

작업 환경에 너무 많은 객체가 있고, 전부 삭제하고자 한다면, rm 함수에 ls 결과를 전달하면 된다:

rm(list = ls())

상기 예제에서, 명령어 두개를 조합했다. 연산 우선순위처럼, 가장안쪽 괄호 내부에 있는 것이 먼저 평가되고, 쭉 이어서 평가된다.

상기 예제에서, ls 결과가 rm 삭제 명령어 list 인자로 사용되도록 지정했다. 값을 이름으로 인자에 할당할 때, = 연산자를 사용해야만 한다!

대신에 <-가 사용되면, 의도하지 못한 역효과가 발생되거나, 오류 메시지만 얻게 된다:

rm(list <- ls())
## Error in rm(list <- ls()): ... must contain names or character strings

꿀팁: 경고 vs. 오류

R이 예상하지 못한 무언가 수행할 때 주위를 기울이다! R이 연산작업을 더이상 진행할 수 없을 때 상기와 같이 오류를 던진다.

다른 한편으로 경고는 일반적으로 함수는 실행된다. 하지만, 함수는 아마도 예상한 것처럼 동작하지 않을 것이다.

두가지 경우 몯, R이 출력해서 전해주는 메시지가 문제 해결에 대한 단서를 줄 것이다.

21.13 R 팩키지

팩키지를 작성하거나, 누군가 작성한 팩키지를 얻어 R에 함수추가도 가능하다. 현 저작시점에, CRAN(comprehensive R archive network)에는 13,000개 이상 팩키지가 있다. R과 RStudio 모두 팩키지 관리 기능이 있다:

  • installed.packages() 타이핑하면, 어떤 팩키지가 설치되어 있는지 확인할 수 있다.
  • install.packages("packagename") 타이핑하면, 팩키지를 설치할 수 있다. 여기서 packagename은 팩키지명칭이 된다.
  • update.packages() 타이핑하면, 설치된 팩키지를 갱신할 수 있다.
  • remove.packages("packagename") 타이핑하면, 팩키지를 제거한다.
  • library(packagename) 명령어로 팩키지를 사용할 수 있게 한다.

21.14 도전과제 2

다음 프로그램에 나온 각 문장을 실행하게 되면, 각 변수 값에는 무슨 값이 담겨있을까요?

mass <- 47.5
age <- 122
mass <- mass * 2.3
age <- age - 20

도전과제 2에 대한 해답

mass <- 47.5

실행하게 되면 mass 변수에 47.5 값이 배정된다.

age <- 122

age 변수에 122 값이 배정된다.

mass <- mass * 2.3

상기 문장은 2.3을 47.5 에 곱하여 mass 변수에 109.25 값이 배정된다.

age <- age - 20

기존 변수 age 122 값에 20을 빼서 변수 age에는 102 값이 할당된다.

21.15 도전과제 3

이전 도전과제 코드를 실행하고 난 후, mass와 age를 비교하는 코드를 작성한다. mass와 age 중 어는 것이 더 큰가?

도전과제 3에 대한 해답

상기 질문에 답하는 방식은 다음과 같이 > 을 사용하는 것이다:

mass > age
## [1] TRUE

109.25 가 102 보다 큰 경우 TRUE를 반환한다.

21.16 도전과제 4

mass와 age 변수를 지워서 작업환경을 청소하자.

도전과제 4에 대한 해답

rm 명령어를 사용해서 청소 작업을 수행한다.

rm(age, mass)

21.17 도전과제 5

ggplot2, plyr, gapminder 팩키지를 설치하라.

도전과제 5에 대한 해답

install.packages() 명령어를 사용해서 팩키지를 설치한다.

install.packages("ggplot2")
install.packages("plyr")
install.packages("gapminder")