4.1 수학함수

R은 광범위한 수학 함수를 내장하고 있고 다음 열거한 함수 목록은 그 일부임

  • exp(): 지수(e)를 밑으로 하는 지수 함수
  • log(): 자연 로그 함수
  • log10(): 10을 밑으로 하는 로그
  • sqrt(): 제곱근
  • abs(): 절대값
  • sin(), cos(), tan() … : 삼각함수
  • min(), max(): 벡터 내 최솟값과 최댓값 반환
  • which.min(), which.max(): 벡터 내 최댓값과 최솟값에 대한 인덱스 반환
  • sum(), prod(): 벡터 원소들의 합과 곱 결과 반환
  • cumsum(), cumprod(): 백터 원소들의 누적합과 누적곱
  • round(), floor(), ceiling(): 수치형 값의 반올림, 내림, 올림
  • factorial(): 팩토리얼 함수 \(n!\)
  • choose(): 조합 함수 (\(_n C_r = \frac{n!}{r!(n-r)!}\))
  • rev(): 역순으로 배열
  • rank(): 백터 원소 값들의 순위 반환
  • sweep(): 각 원소에서 요약통계량(예: 평균)으로부터 편차 계산 시 유용

확장예제1: 확률계산

  • \(P_i\): \(n\) 개의 독립적인 사건이 있고 \(i\) 번째 사건이 발생할 확률
  • \(n = 3\) 일 때, 각 사건의 이름을 각각 A, B, C 라고 할 때 이 중 사건 하나가 발생할 확률
P(사건 하나가 발생할 확률) = 
P(A가 일어나고 B와 C가 일어나지 않을 확률) + 
  P(A가 일어나지 않고 B가 일어나고 C가 일어나지 않을 확률) + 
  P(A, B가 일어나지 않고 C만 일어날 확률)

  • 여기서 P(A가 일어나고 B와 C가 일어나지 않을 확률) = \(P_A(1-P_B)(1-P_C)\) \(\rightarrow\) 나머지도 마찬가지임
  • 일반화 하면

\[ \sum_{i=1}^{n} P_i(1-P_1)(1-P_2)\cdots (1-P_{i-1})(1-P_{i+1})\cdots (1-P_{n}) \]

  • 수학함수로 구현: prod() 함수 활용
# 벡터 p에서 p_i 계산 함수
p <- c(0.2, 0.4, 0.3)
notp <- 1 - p
p[1] * prod(notp[-1]) +
p[2] * prod(notp[-2]) +
p[3] * prod(notp[-3])
[1] 0.452
p <- runif(10, 0, 1)
notp <- 1 - p
# 일반화 하려면 어떻게 해야 할까? -> 반복문 활용
tot <- 0
for (i in 1:length(p)) {
  tot <- tot + p[i] * prod(notp[-i])
}

확장예제2: 누적합, 누적곱

# cumsum, cumprod 함수 사용 예시
x <- c(2, 4, 1, 3, 7, 8)
cumsum(x); cumprod(x)
[1]  2  6  7 10 17 25
[1]    2    8    8   24  168 1344

확장예제3: 최솟값, 최댓값

# which.min, which.max 사용 예시
set.seed(100)
x <- sample(1:100, 100)
idx_min <- which.min(x)
x[idx_min]
[1] 1
idx_max <- which.max(x)
x[idx_max]
[1] 100
# min(), max(), pmin(), pmax() 비교
set.seed(5)
x <- runif(5, 2, 4)
y <- runif(5, 2, 4)
z <- cbind(x, y)

min(z); max(z) # z의 전체 값 중 최솟값과 최댓값 반환
[1] 2.2093
[1] 3.913
pmin(z); pmax(z) # 아무 값을 반환하지 않음
            x        y
[1,] 2.400429 3.402115
[2,] 3.370437 3.055920
[3,] 3.833752 3.615870
[4,] 2.568799 3.913000
[5,] 2.209300 2.220906
            x        y
[1,] 2.400429 3.402115
[2,] 3.370437 3.055920
[3,] 3.833752 3.615870
[4,] 2.568799 3.913000
[5,] 2.209300 2.220906
# 두 열을 비교해 각 행에서 최솟값, 최댓값을 반환
pmin(z[, 1], z[, 2]) 
[1] 2.400429 3.055920 3.615870 2.568799 2.209300
pmax(z[, 1], z[, 2])
[1] 3.402115 3.370437 3.833752 3.913000 2.220906

확장예제5: sweep() 함수 활용

X <- matrix(1:12, 3, 4)
m <- apply(X, 2, mean)
M <- matrix(m, ncol = 4, nrow = 3, byrow = TRUE)
X - M
     [,1] [,2] [,3] [,4]
[1,]   -1   -1   -1   -1
[2,]    0    0    0    0
[3,]    1    1    1    1
# sweep 함수 활용
sweep(X, 2, colMeans(X))
     [,1] [,2] [,3] [,4]
[1,]   -1   -1   -1   -1
[2,]    0    0    0    0
[3,]    1    1    1    1

확장예제6: 미분/적분

  • 문자의 미분 및 수치 적분 가능
# 도함수 구하기
## D() 함수 사용
dx <- D(expression(exp(x^2)), "x") # exp(x^2)을 x에 대해서 1차 미분한 도함수
set.seed(3)
x <- runif(3, 1, 2)
eval(dx) # 위 입력한 x에 대한 도함수 값 출력
[1]  9.141245 94.842390 18.856751
## deriv() 함수 사용
grad <- D(expression(x*sin(x)), "x")
# 도함수를 R의 function으로 바로 반환 가능
dx2 <- deriv(expression(x*sin(x)), "x", function.arg = TRUE) 
dx2(x)
[1] 1.074580 1.757109 1.361092
attr(,"gradient")
             x
[1,] 1.3778035
[2,] 0.5482219
[3,] 1.2386966
# 수치 적분
## integrate() 함수 사용
## 주어진 함수의 적분식을 구한 후, 입력 구간에 대한 적분값 계산
integrate(f = function(x) x^2, lower = 0, upper = 1)
0.3333333 with absolute error < 3.7e-15