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

R과 RStudio 소개

학습 목표

  • RStudio IDE 개발환경에 나온 다양한 창에 친숙해진다.
  • RStudio IDE 개발환경에 활용되는 버튼, 단축키, 선택옵션과 친숙해진다.
  • 변수를 이해하고, 변수에 값을 할당하는 방법을 이해한다.
  • 인터랙티브 R 세션에 작업공간을 관리할 수 있다.
  • 수학 연산과 비교연산 작업을 수행할 수 있다.
  • 함수를 호출할 수 있다.
  • 팩키지 관리에 대한 소개

RStudio 소개

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

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

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

기본 배치

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

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

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

RStudio 내부 작업흐름

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

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

R 소개

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

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

계산기로 R 사용하기

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

1 + 100
[1] 101

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

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

> 1 +
+

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

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

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

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

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

(3 + 5) * 2
[1] 16

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

(3 + (5 * (2 ^ 2))) # 읽기 어렵다.
3 + 5 * 2 ^ 2       # 만약 수학 연산 우선순위 규칙을 기억한다면, 명확한다.
3 + 5 * (2 ^ 2)     # 우선순위 규칙을 잊어버린 경우, 도움이 된다.

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

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

2/10000
[1] 2e-04

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

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

5e3  # 양수는 음의 부호가 생략됨에 주의
[1] 5000

수학 함수

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

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

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

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

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

다양한 객체 비교하기

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

변수와 대입

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

x <- 1/40

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

x
[1] 0.025

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

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

log(x)
[1] -3.688879

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

x <- 100

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

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

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

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

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

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

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

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

x = 1/40

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

벡터화(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

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

환경 설정

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

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

ls()
[1] "hook_error" "hook_in"    "hook_out"   "x"         

여기서 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: 0x7fc99da60190>
<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

R 팩키지

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

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

도전과제 1

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

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

도전과제 2

도전과제 1 코드를 실행하고 massage를 비교하는 명령어를 작성한다. massage 보다 큰가요?

도전과제 3

massage 변수를 삭제해서 작업환경을 정리하세요.

도전과제 4

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