-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy path02-R-basic.Rmd
218 lines (149 loc) · 16.5 KB
/
02-R-basic.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# R 에센셜
## R과 R Studio 설치
먼저 R과 R Studio가 필요하다. R은 프로그래밍 언어 자체고, R Studio는 여러분들의 R 프로그래밍을 조금 더 쉽게 도와줄 친구라고 생각해보자. R Studio나 VS Code와 같이 코딩을 도와주는 친구들을 IDE라고 하는데, 이는 "통합 개발 환경" (Integrated Development Environment)의 약어로 소프트웨어 개발을 위한 툴 또는 프로그램을 이야기한다. 이를 통해 개발자는 소스 코드를 작성, 편집, 디버깅, 테스트 및 배포하는 데 많은 도움을 받을 수 있다. 일단 묻지도 따지지도 말고 일단 Posit [홈페이지](https://posit.co/download/rstudio-desktop/)에 접속하자. 사용하는 OS에 맞춰 R 버전은 4.0이상, R Studio는 대충 최신 버전으로 설치하면 된다.
## Hello World!
R Studio를 실행해보자. 프로그래밍이 처음인 사람이라면 아주 낯선 화면을 마주하게 될 것이다. 묻지도 따지지도 말고 일단 Console이라고 적인 박스에서 꿈뻑거리고 있는 그곳에 아래와 같이 입력하고 경쾌히 엔터키를 눌러보자.
```{r}
print("Hello World!")
```
축하한다! **당신은 세상 모든 프로그래머들의 국룰과 함께 역사적인 첫발을 내딛었다.** 부디 새로운 세상(World)에 들어온 이 순간을 잘 기억하시라. R Studio의 인터페이스는 단순하다. Console에 뭔가를 쓰고 입력하기만 하면 된다. 우리는 이것을 '명령'이라고 부른다. 컴퓨터는 '명령'한대로 뭔가를 하기 시작할 것이다. 그리고 그 여튼 뭔가 보여준다. 제대로 실행되던지 아니면 오류 메시지를 보여주던지. 만약 미완성된 명령을 입력하면 프롬프트에 `+`가 표시되는데, 이는 나머지 부분을 더 입력하기를 기다리고 있다는 의미다. 명령을 마저 입력하거나 Esc를 눌러 취소하면 된다.
## 예쁜 테마는 일할 맛 나게 해주지
다음으로 해야 할 일은 테마를 바꾸는 것이다. `Options > Appearance`에서는 R Studio의 테마, 폰트, 폰트사이즈 모두 마음대로 바꿀 수 있다. 이건 마치 공부하기 전 책상정리부터 하는 학생의 마음같은 것이다. 내가 공부할 수 있는 가장 기분좋은 상태를 만들어 보자. 마치 국방부 서버를 침투하는 대단한 해커가 된 것 같은 기분을 내보는 것이 도움이 된다.
## 당신의 고민은 이미 누군가의 고민이었다
### 에러 메시지를 대하는 자세
최고급 개발자조차 에러 메시지는 피할 수 없다. **에러 메시지를 무서워하지 말자.** 잘 읽어보면 그 안에 답이 있다. 필자의 경우 에러 메시지를 맞닥뜨리는 이유의 80%는 '오탈자' 때문이다. 그래도 모르겠다면 구글에 에러 메시지를 복붙해 해보자. 당신의 고민은 이미 누군가의 고민이었다. 'How to ~'와 '~ in R'을 적절히 섞어서 검색하다 보면 누군가의 해결방법을 찾을 수 있을 것이다. 물론 고수의 입장에서 본다면 복붙한 코드는 근본적인 해결이 아닌 미봉책에 그치는 경우도 많겠지만 지금 단계에서 그것은 중요하지 않다. 일단 과정 가운데 꾸준히 배우다 보면 결국 근본적인 해결책도 만나게 될 것이다.
**영어 문서를 무서워하지 말자.** 대부분의 고급 정보는 영어로 제공되곤 한다. 영어를 두려워하는 우리를 위해 구글 번역기, DeepL, 네이버 파파고가 존재하지 않는가? 구글 번역기의 크롬 익스텐션이 보다 빠른 번역을 도와줄 것이다. 외국인이나 한국인이나 맞닥드리는 문제는 근본적으로 크게 다르지 않다. 다만 한국어보다 영어를 쓰는 사람이 많기 때문에 영어로된 질문과 답변에 대한 문서가 훨씬 많을 뿐이다.
## 계산기로 사용해보기
R은 계산기로 사용할 수 있다. `1 + 1`를 입력하고 엔터키를 눌러보자.
```{r}
1 + 1
```
R은 사칙연산을 포함한 다양한 연산을 할 수 있다. 원하는 숫자들을 더하고(`+`) 빼고(`-`) 곱하고(`*`) 나눠보자(`/`). R은 아주 작은수 부터 큰수까지 순식간에 계산해준다.
```{r}
2 + 2
2 - 2
2 * 2
2 / 2
```
## 이름을 붙여주자(객체할당)
> 내가 그의 이름을 불러주기 전에는 그는 다만 하나의 몸짓에 지나지 않았다.
> 내가 그의 이름을 불러 주었을 때, 그는 나에게로 와서 꽃이 되었다. -- 꽃(김춘수)
앞에서 배운 것처럼 R에게 명령을 내려보았다. 하지만 이것들은 아직 컴퓨터 어디에도 저장되지 않았다. 이미 다 지나간 일이라 다시 사용할 수 없으므로 만약 이것들을 계속해서 사용하고 싶다면 어딘가에 어떠한 형태로든 저장해 놓아야 한다. 이제 객체(object)가 필요할 시간이다.
```{r}
two <- 2
five <- 5
```
이제 컴퓨터의 메모리 어딘가에 객체가 저장되었다. 객체는 `<-`를 사용해서 할당할 수 있다(대신 `=`를 사용할 수도 있지만 사용하지 않기로 하자). 할당된 객체들에 대한 정보는 R Studio의 Environment 탭에서 찾아볼 수 있다.
```{r}
two + 8
five * 100
two / five
```
이미 만들어진 객체 이름이라도 덮어 쓸 수 있다. 같은 객체 이름을 두번 사용하지 않도록 조심하자.
```{r}
a <- 100
a
a <- 9999
a
```
객체명을 할당할 때는 반드시 아래 규칙을 지켜야 한다. 만약 이 규칙을 지키지 않고 아래와 같이 하면 에러가 발생할 것이다.
1. 문자로 시작해야 한다(= 숫자로 시작할 수 없다).
2. 문자, 숫자, _, . 만 포함해야 한다.
```{r echo=TRUE, error=TRUE}
123 <- 10
animal!! <- "cow"
```
또한 R은 대소문자를 구분한다. `Year`과 `year`은 다르다.
```{r echo=TRUE, error=TRUE}
Year <- 365
year
```
> There are only two hard things in Computer Science: cache invalidation and naming things.
> --Phil Karlton
객체 할당에서 가장 어려운 것은 객체의 이름을 정하는 것이다. 객체명을 정하는 방법과 기준은 개발자 간에 다소 주관적일 수 있으나 일반적인 가이드라인은 다음과 같다. 조금 더 자세한 내용이 알고 싶다면 [tidyverse style guide](https://style.tidyverse.org/syntax.html)를 참조하자.
1. 명확하고 의미 전달력이 있는 이름 사용: 변수명은 해당 변수의 의도나 기능을 명확하게 전달해야 한다. 다른 사람이 코드를 읽거나 유지보수할 때 이해하기 쉬워야 하기 때문에 의미 있는 단어나 약어를 사용하고, 변수가 나타내는 데이터의 성격이나 용도를 잘 나타내도록 한다. 일반적으로 변수 이름은 명사가, 함수 이름은 동사가 좋다(함수가 무엇인지 아직 몰라도 된다).
2. 카멜 케이스 또는 스네이크 케이스 사용: 변수명을 작성하는 데에는 주로 카멜 케이스(camel case) 또는 스네이크 케이스(snake case)를 사용한다. 카멜 케이스는 첫 번째 단어를 제외한 각 단어의 첫 글자를 대문자로 작성하고, 단어들을 연결하여 작성하는 방식으로 예를 들면 "myVariableName"과 같다. 스네이크 케이스는 모든 단어를 소문자로 작성하고, 단어들을 밑줄로 연결하는 방식으로 예를 들면 "my_variable_name"과 같다. 어떤 케이스를 사용하든지 일관성을 유지하는 것이 중요하다(필자는 스네이크 케이스를 선호한다).
3. 너무 짧은 변수명 피하기: 충분히 명확하지만 지나치게 짧게 작성하는 것은 가독성을 저해할 수 있다. 변수의 용도와 의미를 잘 반영하면서도 충분히 길이가 있는 이름을 선택하는 것이 좋다. R Studio를 포함한 대부분의 IDE들에서는 할당된 객체에 대한 자동완성 기능을 제공한다.
4. 일관성 유지: 프로젝트 전체에서 일관된 변수명 규칙을 사용하는 것이 좋다. 같은 종류의 변수는 같은 규칙에 따라 명명되어야 하며, 다른 개발자들과의 협업 시에도 일관성을 유지할 수 있다.
5. 발음하기 쉬운 변수명 쓰기: 혼자 일하지 않는 경우도 많다. `Worcestershire`같은 변수명을 쓰다간 동료에게 맞는 불상사가 생길 수도 있다.
그리고 생각보다 **한글** 변수명도 잘 읽는다. 물론 한영전환이 불편할 수도 있고 만약 외국인들과 일한다면 소통의 어려움이 있겠지만, 개인적인 프로젝트라면 보다 풍부한 변수명을 쓸 수도 있다. 무엇보다 특정 도메인에 특화된 프로그래밍을 할 때, 한글 변수명을 사용하면 도메인 용어와의 일치도를 높일 수 있다. 한국어 자연어 처리와 같이 한글을 다루는 분야에서 변수명과 관련 용어들 간의 일관성을 유지하기 쉽다.
```{r}
아름다운우리한글 <- 99.9
아름다운우리한글
```
## 컴퓨터에게 "1"은 1이 아니야(문자와 숫자)
R은 사람이 콕 찝어 알려주기 전까지는 숫자(number)와 문자(character)를 온전히 구분하지 못한다. 아래 두 사칙연산 결과를 비교해 보자.
```{r error=TRUE, echo=TRUE}
5 + 5
"5" + "5"
```
`5 + 5`는 정확하게 계산값을 뱉어내지만 `"5" + "5"`는 `non-numeric argument`라 계산할 수 없다는 에러 메시지를 뱉는다. 이는 R에서 `5`는 `"5"`와 다르기 때문이다. 숫자는 더하거나 뺄 수 있지만, 문자는 불가능하다(우리가 철수에서 영희를 빼지 못하는 것처럼). **R은 쌍따옴표(`"`)로 감싸진 것들은 문자라고 인식**하기 때문에 `5 + "5"`는 계산이 불가능하다. 반드시 숫자는 숫자를 다루는 방식으로, 문자는 문자를 다루는 방식으로 다뤄져야 한다. 자료의 속성을 가장 쉽게 확인해보는 방법은 `str()` 함수를 사용하는 것이다
```{r error=TRUE, echo=TRUE}
str(5)
str("5")
```
`num`은 numeric (숫자)을 의미하고 `chr`은 character (문자)를 의미한다. 명심하자. 우리는 `오 더하기 오`와 `5 + 5`를 보며 같은 결과를 도출하지만 R은 개떡같이 말해도 찰떡같이 알아먹을 줄 모른다. ~~chatGPT는 알아 먹던데..~~
## 함수와 패키지
### 함수란?
R에서 함수란 입력값을 받아서 출력값을 내놓는 작은 도구이다. 함수는 `function()` 함수를 사용하여 정의할 수 있다. 아래는 `add()`라는 함수를 정의하는 예제이다. `add()` 함수는 두 개의 숫자를 입력받아 더한 값을 출력한다.
```{r}
add <- function(x, y) {
x + y
}
add(x = 5, y = 5)
```
함수는 이런 단순한 계산에서 부터 시작해서 시각화, 딥러닝까지 다양한 목적으로 사용될 수 있다. R은 기본적으로 내장하고 있는 함수들이 있으며, 손쉽게 꺼내 쓸수 있다. `mean()` 함수는 입력값의 평균을 계산해주는 함수이다. 아래는 `mean()` 함수를 사용하는 예제이다.
```{r}
mean(x = 1:10)
```
`1:10`은 1부터 10까지의 숫자를 의미한다. `mean()` 함수는 이 숫자들의 평균을 계산하여 출력한다. `mean()` 함수는 `x`라는 입력값을 받는다. `x`는 `1:10`이라는 숫자 벡터이다. `mean()` 함수는 `x`에 해당하는 숫자들의 평균을 계산하여 출력한다. `mean()` 함수는 `x`라는 입력값을 받는다. `x`는 `1:10`이라는 숫자 벡터이다. `mean()` 함수는 `x`에 해당하는 숫자들의 평균을 계산하여 출력한다.
### 함수들의 꾸러미, 패키지
함수가 단일 작업을 수행하는 작은 도구 하나라면, 패키지는 그 도구들이 모여 있는 큰 도구상자다. 각 패키지는 특정 기능을 수행하기 위해 필요한 함수와 데이터를 제공하며, 사용자는 패키지를 설치하고 로드하여 해당 기능을 사용할 수 있다. 패키지는 R의 기본 기능을 확장하고, 다양한 도메인에 특화된 기능을 제공하여 데이터 분석, 시각화, 모델링 등 다양한 작업을 수행할 수 있도록 도와준다.
### 주요 패키지 설치
#### CRAN을 통한 설치
R은 오픈소스로 많은 사람들이 만들고 공개한 패키지를 손쉽게 사용할 수 있다. 패키지를 설치하는 가장 쉬운 방법은 `install.package()` 함수를 사용하는 것인데, 이는 [CRAN](http://cran.r-project.org/)(The Comprehensive R Archive Network)이라는 저장소에 올라가 있는 R 패키지를 다운로드 받는다. 현재 CRAN에서 다운로드 가능한 패키지는 아래와 같다.
```{r echo=FALSE, eval=TRUE, message=FALSE}
library(dplyr)
library(reactable)
reactable(available.packages(contriburl = contrib.url("https://cran.r-project.org/")) %>%
as_tibble() %>% select(Package, Version, Depends, License), searchable = TRUE,
columns = list(Depends = colDef(minWidth = 140))
)
```
아래는 `tidyverse`라는 패키지를 설치하는 예제이다.
```{r eval=FALSE}
install.packages("tidyverse")
```
#### Github을 통한 설치
[Github](https://github.com)은 소프트웨어 개발자들이 소스코드를 공유하는 플랫폼이다. Github에는 CRAN에 올라가지 않은 패키지들도 많이 올라와 있다. 이 패키지들은`remotes`패키지의 `install_github()` 함수를 사용하여 설치할 수 있다. 다만 Github에 업로드 되어 있는 패키지들은 CRAN에 비해 peer-review가 되어 있지 않아 테스트가 덜 되어 있을 수 있으므로 주의가 필요하다. 아래는 `datatoys`라는 패키지를 설치하는 예제이다.
```{r eval=FALSE}
install.packages("remotes") # if required
remotes::install_github("statgarten/datatoys")
```
#### 패키지 불러오기
불러온 패키지는 R 세션이 재시작 될 때마다(R을 실행하고 종료할 때 마다) 초기화 된다. 한마디로, 새로운 세션이 시작될 때 마다 `library()` 함수를 다시 실행해 줘야 한다.
```{r}
library(dplyr)
```
만약 `library()` 함수를 사용하지 않고 특정 패키지에 있는 데이터셋이나 함수를 한번만 불러오고 싶다면 `::`를 사용할 수 있다.
`petNames`라는 데이터셋은 패키지 로딩 없이는 꺼낼 수 없지만(에러 메시지를 출력한다),
```{r error=TRUE, echo=TRUE}
head(petNames)
```
`::`를 아래와 같이 사용하면 패키지 로딩 없이 필요한 데이터셋이나 함수만 쏙 빼올 수도 있다.
```{r error=TRUE, echo=TRUE}
head(datatoys::petNames)
```
#### 의존성 문제
R을 사용하다보면 여러가지 패키지들을 함께 사용할 경우가 대부분이고, 사용하는 패키지가 많아질 수록 한 패키지가 다른 패키지의 함수를 빌려다 쓰는 의존성(Dependency)이 증가하게 된다. 그러다보면 의존된 패키지가 누락되거나 업데이트 되었을 때 해당 함수가 정상적으로 동작하지 않을 수도 있다. 예를 들어, "ggplot2" 패키지는 "dplyr" 패키지의 함수를 사용하여 데이터를 전처리하기도 한다. 따라서 "ggplot2" 패키지를 사용하려면 "dplyr" 패키지가 먼저 설치되어 있어야 한다.
따라서 패키지를 업데이트할 때는 의존하는 다른 패키지와의 호환성을 고려해야 한다. 이러한 문제를 해결하기 위해 R에서는 패키지 의존성을 자동으로 관리해주는 도구인 패키지 관리자를 제공한다. 패키지 관리자는 의존하는 패키지를 자동으로 설치하거나 업데이트하고, 패키지 간의 충돌을 최소화하여 코드의 정상 작동을 보장한다. 문제가 생길 수 있다고 인식하고 있되, 너무 걱정하지는 말자.
## 파이프 연산자
### 파이프 연산자란?
파이프 연산자는 함수를 연결하여 사용할 때 유용하게 사용할 수 있는 연산자다. **파이프 연산자는 `%>%`로 표현하며, 왼쪽에 있는 값을 오른쪽에 있는 함수의 첫 번째 인자로 전달**한다. 파이프 연산자를 사용하면 함수를 연결하여 사용할 때 코드의 가독성을 높일 수 있다. 앞으로의 모든 분석에서 파이프 연산자를 함께 사용할 것이다. 따라서 본 개념을 정확하게 익히고 가도록 하자.
```{r error=TRUE, echo=TRUE}
library(dplyr)
library(datatoys)
head(petNames)
petNames %>% head()
```
위 `head(petNames)`와 `petNames %>% head()`는 동일한 결과를 출력한다. `head`함수의 첫 번째 인자로 `petNames`를 전달하는 대신, `petNames`를 `%>%`의 왼쪽에 두어 `head` 함수의 첫 번째 인자로 전달한 것이다. 이처럼 파이프 연산자는 함수를 연결하여 사용할 때 유용하게 사용할 수 있다.