Chapter 4 R program basic
4.1 기초 연산
단순 계산기로 사용할 수 있다. 예를 들어 1+2 의 값이라던가, log2(10) 등을 계산할 수 있다. Rsutdio 의 스크립트 창이나 콘솔 창에 아래의 항목을 작성해 볼 수 있다.
3+4;4-3;4/3;3*4
log2(10)
abs(-4)
sqrt(4)
기초 함수는 아래와 같다.
Operator | Description |
---|---|
+ | addition |
- | subtraction |
* | multiplication |
/ | division |
^ or ** | exponentiation |
x %% y | modulus (x mod y) 5%%2 is 1 |
x %/% y | integer division 5%/%2 is 2 |
Operator | Description |
---|---|
< | less than |
<= | less than or equal to |
> | greater than |
>= | greater than or equal to |
== | exactly equal to |
!= | not equal to |
!x | Not x |
x | y |
x & y | x AND y |
isTRUE(x) | test if X is TRUE |
Operator | Description |
---|---|
Logarithms and exponentials | log2(x), log10(x), exp(x) |
Trigonometric functions | cos(x), sin(x), tan(x), acos(x), asin(x), atan(x) |
Others | abs(x): absolute value; sqrt(x): square root. |
기초 함수 중에 몇몇은 그림을 그려보아야 이해가 쉽다.
= rnorm(n=100, mean = 10, sd = 5) # 평균이 10이고 표준편차가 5인 100개의 랜덤 변수를 pm10 이라고 가정하자
pm10 = rep(1:100) # 1일부터 100까지의 시간이 있다고 해보자
dateplot(x=date, y=pm10, type = "l") # "l" line 형식으로 그려보았다.
= sin(date) # 오존은 시간에 따라 햇빛이 있을 때 높게 올라간다. sine 함수를 따른다고 가정해 보자
oz plot(x=date, y = oz, type = "l") #
= oz**2 # -값을 갖는 것은 좀 이상하다. 제곱을 통해 변경해 보자
oz2 plot(x=date, y = oz2, type = "l") #
= abs(oz) # 접곱보다 절대 값이 어떨까?
ozabs plot(x=date, y = ozabs, type = "l") #
= pm10 + date # 시간에 따라 pm10 농도가 올라간다고 가정해 보자
pmtrend plot(x=date, y = pmtrend, type="l")
= log(pmtrend) # 로그 값을 넣어보자. 특별한 의미는 없이 함수에 대한 실습이다.
pmtrend.log plot(x=date, y = pmtrend.log, type="l") #
과제
아래 mimic이라는 -10부터 10까지 점차 증가하는 숫자가 있다. 아래 그림처러 그려진다. abline(h=0)
은 horizontal line을 추가해서 0 아래 와 위를 구분해 본것이다.
= -10:10
mimic plot(mimic);abline(h=0) #
아래에 함수(function
)에 적당한 함수를 넣어서 아래의 그림 처럼 나타내 보자!
= "function"(mimic)
mimic2 plot(mimic2); abline(h=0, col='red')
두번 째
여기에 sin 함수를 넣고 최소 값이 0이 되도록 + 1을 해서 그림을 그려보자
4.2 조건부 연산
if-else
라는 조건에 따라 연산을 수행시킨다. 예를 들어 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 의 백터에서 5보다 작으면 A 크면 B를 적용시켜주다.
<- 1
numsif (nums <5) {
= 'A'
chars else{
} = 'B'
chars
} chars
## [1] "A"
<- 6
nums if (nums <5) {
= 'A'
chars else{
} = 'B'
chars
} chars
## [1] "B"
몇가지 예제를 더 살펴보자.
<-round(rnorm(10)*10)
a a
## [1] 3 -14 12 -9 0 -7 16 18 -6 -6
<- ifelse(a>0, '양수', '음수')
tab tab
## [1] "양수" "음수" "양수" "음수" "음수" "음수" "양수" "양수" "음수" "음수"
data.frame(a, tab)
## a tab
## 1 3 양수
## 2 -14 음수
## 3 12 양수
## 4 -9 음수
## 5 0 음수
## 6 -7 음수
## 7 16 양수
## 8 18 양수
## 9 -6 음수
## 10 -6 음수
데이터 클리닝에서 자주 사용하는 두개의 조건문 any()
와 all()
이 있다. any()
는 하나라도 TRUE
값이 있으면 TRUE
를 변환해주고, all()
은 모두 TRUE
여야 TRUE
를 돌려준다.
<- c(1, 2, NA)
new.var is.na(new.var)
## [1] FALSE FALSE TRUE
any(is.na(new.var))
## [1] TRUE
all(is.na(new.var))
## [1] FALSE
index 를 이용하면 조건 문에서 IF (또는 Where)의 개념을 사용할 수 있다. iris
데이터에서 Sepal.Length
가 가장 큰 값은 찾고, Sepal.Length
최고 값을 갖은 Species
의 종류를 찾고자한다. 어떻게 하면될까?
head(iris)
## 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
table(iris$Species)
##
## setosa versicolor virginica
## 50 50 50
max(iris$Sepal.Length)
## [1] 7.9
<- which.max(iris$Sepal.Length)
max.length $Species[max.length] iris
## [1] virginica
## Levels: setosa versicolor virginica
과제
index 를 이용하면 조건 문에서 IF (또는 Where)의 개념을 사용할 수 있다.
iris
데이터에서 Sepal.Length
가 가장 작은 찾고, Sepal.Length
최소 값을 갖은 Species
의 종류를 찾고자한다. 최소 값과 종류를 쓰시오
4.3 함수 만들기
저자가 R을 이용하는 이유중 하나가 함수를 손쉽게 만들고 그 결과를 활용하기가 쉽다는 것이다. 자동문, 반복문, 데이터 클리능, 데이터 시각화 등에서 자주 사용하는 기본 원리이다.
숫자 2개를 넣으면 덧 샘을 해주는 함수를 만들어 보자
= function(x, y ){
addtive.function + y
x }
addtive.function(100, 2)
## [1] 102
퀴즈
숫자 2개를 넣으면 두 수의 차이를 보여주는 함수를 만들어 보자 abs
사용. #-#
에 계산식을 넣어 함수를 완성해 보세요.
= function(x, y ){
abs.function#--#
}
평균을 구해주는 함수 avg를 만들어 보자. length
는 길이를 말해주니, 몇개의 변수값이 있는 지 알 수 있다.
<- 1:50
my_vector<- function(x){
avg sum(x)/length(x)
}avg(my_vector)
## [1] 25.5
좀더 확장해서 변수 갯수, 평균, 최고, 최저 값을 나타내는 함수를 만들어 보자.
<- function(x){
tabs data.frame( '평균' = mean(x),
'변수갯수' = length(x),
'최고값' = max(x),
'최저값' = min(x)
)
}
tabs(my_vector)
## 평균 변수갯수 최고값 최저값
## 1 25.5 50 50 1
그럼 이를 이용해서, 다음을 해석해 보자
<- function(x, arithmetic = TRUE){
avg <- length(x)
n ifelse(arithmetic, sum(x)/n, prod(x)^(1/n))
}
4.4 반복문, vectorization, functionals
4.4.1 for loop
1a, 2a, 3a, 4a, 5a, 6a, 7a, 8a, 9a, 10a 을 만들어보자, 어떻게 하면될까?
c('1a', '2a', '10a') # 이렇게 해보는 것도 좋지만
## [1] "1a" "2a" "10a"
반목문을 사용하면, 아래와 같다.
for (i in 1:10){
print(paste0(i, 'a'))
}
## [1] "1a"
## [1] "2a"
## [1] "3a"
## [1] "4a"
## [1] "5a"
## [1] "6a"
## [1] "7a"
## [1] "8a"
## [1] "9a"
## [1] "10a"
물론 대부분 이렇게 사용하지만, 반복문을 사용하여 확장할 수 있다.
paste0(1:10, "a")
## [1] "1a" "2a" "3a" "4a" "5a" "6a" "7a" "8a" "9a" "10a"
1:n
까지의 숫자 합을 만들어보자, 그리고 이를 1부터 100일때 까지 만들고 그림을 그려보자
<- function(n){ sum(1:n)}
compute compute(10)
## [1] 55
<-c()
test for (n in 1:100){
<- compute(n)
test[n]
}
plot(1:100, test)
4.4.2 vectorization 과 apply 구문
사실 ifelse 를 잘 사용하지 않는다. 이는 속도의 문제와도 관련된다. 실제 ifesel 로 10분이 걸리는 연산이 1분으로 줄수도 있다. 이때 사용하게 되는 것이 백터화와 apply 구문이다. 이미 past0(1:10,“a”) 같은 구문이 편할 수 있다는 것을 느꼈을 것이다. 이번에는 구구단 2단과 3단을 서로 곱해보자. 어떻게 하면 좋을까 for와 if를 생각하기 보다 아래를 고려해 보자. 아래가 백터화이다.
<- c(1:9*2)
n2 <- c(1:9*3)
n3 *n3 n2
## [1] 6 24 54 96 150 216 294 384 486
2단에 3단이 아닌 다른 단을 곱하는 함수를 사용해 보자
<-function(n2){
new.functionc(1:9*2) * c(1:9*n2)
}
new.function( 4)
## [1] 8 32 72 128 200 288 392 512 648
그럼 3단 대신에 1, 2, 3, 4, 5, 6, 7, 8, 9 단을 모두 해보자
sapply(1:9, new.function)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
## [1,] 2 4 6 8 10 12 14 16 18
## [2,] 8 16 24 32 40 48 56 64 72
## [3,] 18 36 54 72 90 108 126 144 162
## [4,] 32 64 96 128 160 192 224 256 288
## [5,] 50 100 150 200 250 300 350 400 450
## [6,] 72 144 216 288 360 432 504 576 648
## [7,] 98 196 294 392 490 588 686 784 882
## [8,] 128 256 384 512 640 768 896 1024 1152
## [9,] 162 324 486 648 810 972 1134 1296 1458
상기 행렬을 만들기위해 ifelse를 사용하거나 for 문을 사용하면 좀더 머리가 복잡해 질 수 있다. apply 구문은 확실히 머리가 가벼워진다. tidyverse 부분을 할 때 apply, lapply, tapply, mapply, vaply, replicate
등을 다루게 될 것이다.
4.4.3 home work and summary function
iris
라는 내장 함수를 사용해서 몇가지 실습을 해보자
iris 데이터의 첫번째 10개의 행을 관찰해 보자
head(iris )
## 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
iris 데이터의 마지막 10개의 행을 관찰해 보자
tail(iris)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 145 6.7 3.3 5.7 2.5 virginica
## 146 6.7 3.0 5.2 2.3 virginica
## 147 6.3 2.5 5.0 1.9 virginica
## 148 6.5 3.0 5.2 2.0 virginica
## 149 6.2 3.4 5.4 2.3 virginica
## 150 5.9 3.0 5.1 1.8 virginica
과제 iris 데이터에서 각 변수(sepal.length, sepal.width, petal.length, petal.width) 별 최소, 평균, 중간값, 최대값을 구하시오
각 최소, 평균과 가까운 값(소수점 한자리 까지 같은 것), 중간값, 최대값을 갖는 species 를 구하시오.