"R을 이용한 데이터 처리 & 분석 실무 - 서민구 지음" 정리 자료 #1
- https://thebook.io/006723/
- 첫번째 : goo.gl/FJjOlq
- 두번째 : goo.gl/Wdb90g
- 세번째 : goo.gl/80VGcn
- 네번째 : goo.gl/lblUsR
3. 01. 왜 R인가
• A Language and Environment for Statistical Computing and Graphics
• Bell Lab 통계 분석 언어인 S의 방언(Dialect)
• The R Environment
• R은 Language이자 다양한 Package의 집합
4. 02. R 설치하기
• Windows
• Official Site (http://www.r-project.org) 의 설치 파일 사용
• Linux 설치時 고려사항
• BLAS(Basic Linear Algebra System), LAPACK(Linear Algebra Packages) 의 구현체 변경
• IDE (통합개발환경)
• RStudio – http://www.rstudio.com
• Package Installation
>install.packages("randomForest") #패키지 다운로드 및 설치
>library("randomForest") #패키지를 로드하여 사용준비
6. • Naming Convention
• Alphanumeric, _(Underscore), .(Period) 사용가능, - (Hyphen)은 사용불가
• R 1.9.0 이전에 _를 사용하지 못했던 이유로 .을 대신 사용 -> 객체 멤버 접근처럼 보임
• 올바른 변수명
• 올바르지 못한 변수명
• Assignment
• <-, <<- 또는 = 연산자 사용
• <-와 <<-는 Scope에 따른 차이 발생
• <-와 =는 논쟁적인 주제로 =의 표현력 제한으로 <- 사용 권장
01. 변수
2a 숫자로 시작
.2 . (dot)에 이어 숫자 사용
a-b - (hyphen) 사용
a a1 .x
7. • R 함수들은 Default Values를 지정할 수 있는 Named Arguments를 가짐
• 인자들은 위치에 의해서나(by position) , 이름에 의해서(by name) Matching이 된다.
1. Check for exact match for a named argument
2. Check for a partial match
3. Check for a positional match
02. 함수 호출시 인자 지정
foo <- function(a, b, c=1, d=2) {
print(c(a, b, c, d))
}
foo(3, 4)
foo(3, 4, 1)
foo(3, 4, 1, 2)
foo(3, 4, 5)
foo(a=3, b=4, d=5)
foo(d=1, 3, 4)
8. • Scalar (0차원) Vector(1차원) Matrix(2차원) Array(n차원)
• 숫자, NA – Not Available (결측치), NULL – Undefined (미정값)
• 문자열
• char type이 존재하지 않고 대신 문자열로 표현, quote(‘’), double qutote(“”) 모두 사용 가능
• 진리값
• TRUE, FALSE (reserved keyword) vs. T, F (전역변수)
• &(AND), |(OR), ~(NOT) 연산자 element-wise operator
• &&, || 단일 Boolean 결과값 리턴, short-circuit 지원
• Factor – 범주형 데이터 표현
• Levels – 범주형 데이터가 표현하는 값의 목록
• 명목형(Nominal)과 순서형(Ordinal)으로 구분
03. Scalar
9. sex <- factor("m", c("m", "f"))
str(sex)
## Factor w/ 2 levels "m","f": 1
nlevels(sex)
## [1] 2
levels(sex)
## [1] "m" "f"
levels(sex)[1] # 1-based index, not zero-based
## [1] "m"
levels(sex)[2]
## [1] "f"
factor(c("m", "m", "f"), c("m", "f"))
factor(c("m", "m", "f"))
## [1] m m f
## Levels: f m
# ordered factor
o <- ordered("a", c("a", "b", "c"))
o <- factor("a", c("a", "b", "c"), ordered=TRUE)
10. • 1차원 배열의 개념, 동일 Scalar Type의 값들만 저장
• 슬라이스(slice) 기능 제공
• 배열의 일부를 잘라내어 배열처럼 사용, 연속적이지 않아도 가능
• Duplicate Indexes, Out-of-Order Indexes, Range Index(:, colon operator)
• 각 cell에 이름을 부여할 수 있음 – Index뿐만 아니라 Name을 통해서도 Cell에 접근 가능
• Vector 생성
• Combine 함수 c()를 사용하여 생성, names()를 사용하여 이름을 부여
• 연속된 숫자로 구성된 벡터 생성 – Sequence 함수 seq(from, to, by), seq_along(), from:end 사용
• 반복된 값을 저장한 벡터 – Repeat 함수 rep(x, times, each) 사용
04. Vector
11. # vector combine and naming example
> (x <- c(1,2,3,4,5))
[1] 1 2 3 4 5
> x <- c(1,2,3,4,5)
> (x <- c(1,2,3,4,5))
[1] 1 2 3 4 5
> (x <- c("1", 2, "3")) # 동일 Type으로 변환(Casting)
# 표현력이 큰 데이터 Type으로 변환이 원칙
[1] "1" "2" "3"
> c(1,2,3)
[1] 1 2 3
> c(1,2,3,c(1,2,3)) # 중첩(nested) 허용하지 않음
[1] 1 2 3 1 2 3
> x <- c(1, 3, 4)
> names(x) <- c("kim", "seo", "park")
> x
kim seo park
1 3 4
13. • Vector 접근
• 색인(Index)를 사용하는 방법과 이름(Name)을 사용하는 방법
• 특정 요소 제외(-), 동시에 여러셀에 접근 하는 방법 (slice example 참고)
• Vector Length
• length(x) – 객체의 길이 반환
• NROW(x) – 객체의 행 갯수
문법 의미
x[n] vector x의 n번째 요소 반환, n은 index 혹은 name
x[-n] vector x에서 n번째 요소를 제외한 나머지 요소들 반환, n은 index
x[idx_vector] idx_vector에 지정된 요소들 반환, index vector 혹은 name vector
x[start:end] vector x의 start index부터 end index까지의 요소들 반환
14. > x <- c("a", "b", "c")
> x[1]
[1] "a"
> x[-1]
[1] "b" "c"
> x[c(1, 3)]
[1] "a" "c"
> x[c(1, 1)]
[1] "a" "a"
> x[c(-1, -3)]
[1] "b"
> names(x) <- c("kim", "seo", "park")
> x["seo"]
seo
"b"
> x[c("kim", "park")]
kim park
"a" "c"
> length(x)
[1] 3
> NROW(x)
[1] 3
18. • ‘(key, value)’ 형태의 데이터를 담는 연관 배열(Associative Array)
• Hash Table, Dictionary
• 서로 다른 Data Type의 값 저장 가능
• List 생성
• list(key1=value, key2=value, …)
05. List
> (x <- list(name="foo", height=70))
$name
[1] "foo"
$height
[1] 70
> (x <- list(name="foo", height=c(70,80,90)))
$name
[1] "foo"
$height
[1] 70 80 90
list( a=list(val=c(1,2,3)),
b=list(val=c(1,2,3,4)))
$a
$a$val
[1] 1 2 3
$b
$b$val
[1] 1 2 3 4
19. • List 접근
> x <- list(name="foo", height=c(1, 3, 5))
> x$name
[1] "foo"
> x$height
[1] 1 3 5
> x[[1]]
[1] "foo"
> x[[2]]
[1] 1 3 5
> x[1]
$name
[1] "foo"
> x[c(1,2)]
$name
[1] "foo"
$height
[1] 1 3 5
> x[[c(1,2)]]
Error in x[[c(1, 2)]] : subscript out of
bounds
> x[[2]]
[1] 1 3 5
문법 의미
x$k list x에서 key 값 k
x[n] list x에서 n번째 데이터의 sub list
x[[n]] list x에서 n번째 데이터의 value
20. • 행(Row)과 열(Column)의 수가 지정된 구조
• 2차원 배열, 한가지 유형의 스칼라만 저장
• Matrix 생성
• matrix(data, nrow, ncol, byrow=FALSE, dimnames=NULL)
• dimnames(x) # 객체의 각 차원 이름 가져온다.
• dimnames(x) <- value # 객체의 차원에 이름을 설정한다.
• rownames(x) # 행렬의 행 이름을 가져온다.
• rownames(x) <- value # 행렬의 행 이름을 설정한다.
• colnames(x) # 행렬의 열 이름을 가져온다.
• colnames(x) <- value # 행렬의 열 이름을 설정한다.
06. Matrix
22. • Matrix 접근
문법 의미
A[ridx, cidx] 행렬 A의 ridx행, cidx열에 저장된 값. 생략하면 전체 행 또는 열을 의미
> x[1,1]
[1] 1
> x[1:2,]
c1 c2 c3
r1 1 4 7
r2 2 5 8
> x[-3,]
c1 c2 c3
r1 1 4 7
r2 2 5 8
> x[c(1,3), c(1,3)]
c1 c3
r1 1 7
r3 3 9
> x["r1",]
c1 c2 c3
1 4 7
23. • Matrix 연산
연산자 의미
A + x x는 scalar 값, 행렬 A의 모든 요소에 x를 더한다. -, *, / 연산자 동일
A + B 행렬 A와 행렬 B의 합 (element-wise 연산), 행렬간 차는 – 연산자
A %*% B 행렬 A와 행렬 B의 곱
t(x) 행렬 또는 데이터 프레임의 전치행렬을 구한다.
solve(a, b) a %*% x = b를 만족하는 x를 구함. b 미정시 a의 역행렬
nrow(x) x의 행의 수
ncol(x) x의 열의 수
dim(x) 객체 x의 차원 수
dim(x) <- value 객체 x의 차원 수 지정
26. • 처리할 데이터를 Excel Spread Sheet 형태로 정리
• 각 열(Column)에는 관측값의 이름 저장, 각 행(Row)에는 매 관측시 얻어진 값들이 저장
• Data Frame 생성
• data.frame( …, stringsAsFactors=default.stringsAsFactors())
• d$colName – 데이터프레임 d에서 컬럼 이름이 colName인 데이터를 접근
• d$colName <- y – 데이터프레임 d에서 컬럼 이름이 conName인 컬럼에 데이터 y를 저장
08. Data Frame
> (d <- data.frame(x=c(1:5), y=c(seq(2,10,2)),
z=c('M', 'F', 'M', 'F', 'M')))
x y z
1 1 2 M
2 2 4 F
3 3 6 M
4 4 8 F
5 5 10 M
> str(d)
'data.frame': 5 obs. of 3 variables:
$ x: int 1 2 3 4 5
$ y: num 2 4 6 8 10
$ z: Factor w/ 2 levels "F","M": 2 1 2 1 2
> d$x
[1] 1 2 3 4 5
> (d$w <- c("A", "B", "C", "D", "E"))
x y z w
1 1 2 M A
2 2 4 F B
3 3 6 M C
4 4 8 F D
5 5 10 M E
27. • Data Frame 접근
문법 의미
d$colname 데이터프레임 d에서 컬럼 이름이 colName인 데이터를 접근
D[m, n, drop=TRUE] 데이터프레임 d의 m행 n열에 저장된 데이터
> d$x
[1] 1 2 3 4 5
> d[, c("x")] # vector 반환
[1] 1 2 3 4 5
> d[, c("x"), drop=FALSE] # dataframe 반환
x
1 1
2 2
3 3
4 4
5 5
> d[c(1,3), 2]
[1] 2 6
> d[-1, -2]
x z w
2 2 F B
3 3 M C
4 4 F D
5 5 M E
> d[,!names(d) %in% c("x")]
y z w
1 2 M A
2 4 F B
3 6 M C
4 8 F D
5 10 M E
28. • Utility Function
• Type 판별
• Type 변환
함수 의미
head(x, n=6L) 객체의 처음 부분을 반환한다.
tail(x, n=6L) 객체의 뒷 부분을 반환한다.
view(x, title) 데이터 뷰어를 호출한다.
함수 의미
class(x) 객체 x의 클래스
str(x) 객체 x의 내부구조
is.factor(x) Factor type여부, is.numeric(), is.character(), is.matrix(), is.array(),
is.data.frame() 모두 동일
함수 의미
as.factor(x) Factor type으로 변환, as.numeric(), as.character(), as.matrix(),
as.array(), as.data.frame() 모두 동일
30. • 데이터를 다루는 방법 – Vectorized Computation (Array Programming)
• 결측치를 다루는 방법
• NA(결측치), NULL(미정값)
• NULL AND TRUE -> NULL, NULL AND FALSE -> NULL로 계산
• 객체의 불변성 (immutable)
01. R의 특징
31. • 조건문
02. Flow Control (흐름제어, 조건문과 반복문)
if (cond) {
#cond가 참일때 실행할 문장
}
else {
#cond가 거짓일때 실행할 문장
}
> x <- 1:5
> ifelse(x %% 2 == 0, "even", "odd")
[1] "odd" "even" "odd" "even" "odd"
32. • 반복문
for ( i in data ) {
# i를 사용한 문장
}
while (cond) {
# 조건이 참일 때 수행할 문장
}
repeat {
# 반복해서 수행할 물장, 타 언어의 do-while에 해당
}
# break : 반복문을 종료한다.
# next : 현재 수행중인 반복문 블록의 수행을 중단하고 다음 반복을 시작한다.타 언어의
continue
33. • 수치 연산
03. Operation(연산)
연산자와 함수 의미
+, -, *, / 사칙연산
n %% m 나머지 연산 (modulus)
n %/% m n을 m으로 나눈 몫
n^m n의 m승
exp(n) e의 n승
log(x, base=exp(1)) logbase(x). base 미지정시 e
log2(x), log10(x) log2(x), log10(x)
sin(x), cos(x), tan(x) 삼각함수
34. • 벡터 연산
> x <- 1:5
> x + x
[1] 2 4 6 8 10
> x == x
[1] TRUE TRUE TRUE TRUE TRUE
> x == c(1, 2, 3, 5, 5)
[1] TRUE TRUE TRUE FALSE TRUE
> c(T, T, T) & c(T, F, T)
[1] TRUE FALSE TRUE
> sum(x)
[1] 15
> mean(x)
[1] 3
> median(x)
[1] 3
> ifelse(x %% 2 == 0, "even", "odd")
[1] "odd" "even" "odd" "even" "odd"
>
## 벡터연산을 통해 Data Frame에서 원하는 정
보를 가져오기
## 기본원리–데이터 프레임에 진리값을 지정해
특정 행을 가져올 수 있는 점을 이용
> (d <- data.frame(x=1:5, y=c('a', 'b', 'c',
'd', 'e')))
x y
1 1 a
2 2 b
3 3 c
4 4 d
5 5 e
> d[c(TRUE, FALSE, TRUE, FALSE, TRUE),]
x y
1 1 a
3 3 c
5 5 e
>
35. • NA 처리
• 데이터에 NA가 포함되어 있는 경우 연산결과가 NA
• R의 많은 함수가 na.rm 을 인자로 받아 NA값을 어떻게 처리할 지 지정
• na.rm = TRUE 일 경우, NA를 제외한 나머지 값들로 연산 수행
> NA & TRUE
[1] NA
> NA + 1
[1] NA
> sum(c(1:3, NA))
[1] NA
> sum(c(1:3, NA), na.rm=TRUE)
[1] 6
함수 의미
na.fail(object, …) NA를 포함하면 fail
na.omit(object, …) NA 제외
na.exclude(object, …) omit과 기본적으로 동일
na.pass(object, …) NA가 포함되어 있어도 pass
36. • 기본 정의
04. 함수의 정의
function_name <- function(인자, 인자, ...) {
함수 본문
return (반환 값) # 반환값이 없다면 생략
}
# 피보나치 함수 예제
fibo <- function(n) {
if (n == 1 || n == 2) {
return (1)
}
return (fibo(n - 1) + fibo(n - 2))
}
# 가변 길이 인자
f <- function(...) {
args <- list(...)
for ( a in args ) {
print(a)
}
}
37. • 가변 길이 인자
• 중첩 함수 (nested function)
• 함수 안에 또 다른 함수를 정의하여 사용
• 함수 내부에서 반복되는 코드를 함수化
• 내부 함수가 외부 함수에 정의된 변수를 접근할 수 있어 Closure로 사용 가능
# 가변 길이 인자
f <- function(...) {
args <- list(...)
for ( a in args ) {
print(a)
}
}
39. • 변수명이 어디에서 사용 가능한지를 정하는 규칙
• 변수가 정의된 Block 내부에서만 변수를 접근할 수 있는 규칙
• Console에서 선언된 변수는 전역변수로 모든 곳에서 접근 가능
• 함수 내부에서 전역 변수와 같은 이름의 지역 변수를 사용하면, 함수 내부의 지역
변수가 우선
• 내부 블록에서 외부 블록의 변수에 접근하고자 할 경우 <<- 대입연산자 사용
05. Scope
40. • R에서는 Pass by Value 방식으로 함수에 인자를 전달
• Copy on Write 기법을 통해서 메모리 사용 효율화
06. Pass by Value (값에 의한 전달)
07. 객체의 불변성
• R 객체는 불변(immutable)으로 초기화 이후 수정 불가능
• 연산에 의해서 기존 객체가 변경되지 않고, 연산 결과가 반영된 새로운 객체 생성
• 기존 변수명(variable name)은 새로 생성된 객체를 참조
> tracemem(a)
[1] "<0x000000000c488428>"
> a$b <- 1:3
tracemem[0x000000000c488428 -> 0x000000000c3bbdb0]:
> a$c <- seq(0, 10, 2)
> tracemem(a)
[1] "<0x000000002c3d3c28>"
41. • Information Hiding – 데이터에 대한 외부 접근을 차단하여 내부 구현을 감춤
• Public Access via Interfaces – 사전에 정의된 함수로만 내부 데이터 조작
• Queue Example - Enqueue() / Dequeue() / Size()
08. Module Pattern
q <- c()
q_size <- 0
enqueue <- function(data) {
q <<- c(q, data)
q_size <<- q_size + 1
}
dequeue <- function() {
first <- q[1]
q <<- q[-1]
q_size <<- q_size - 1
return(first)
}
size <- function() {
return(q_size)
}
> enqueue(1)
> enqueue(3)
> enqueue(5)
> print(size())
[1] 3
> print(dequeue())
[1] 1
> print(dequeue())
[1] 3
> print(dequeue())
[1] 5
> print(size())
[1] 0
> enqueue(1)
> q <- c(q, 5)
> print(size())
[1] 1
> dequeue()
[1] 1
> dequeue()
[1] 5
> size()
[1] -1
>
무결성 깨짐