The art of R programming

2.5.2 확장 예제: 이산적 시계열값 예측하기

preda <- function(x, k)
{
  n <- length(x)
  k2 <- k/2 
  
  pred <- vector(length = n - k)
  
  for (i in 1:(n-k))
  {
    if(sum(x[i:(i+(k-1))]) >= k2) pred[i] <- 1
      else pred[i] <- 0
  }
  
  return(mean(abs(pred-x[(k+1):n])))
}

벡터 누적합 구하기

y <- c(5, 2, -3, 8)
cumsum(y) #벡터의 누적합을 구한다. 나중에 sas책 2장 업데이트에서 활용할 것
## [1]  5  7  4 12
sum(y)
## [1] 12

벡터 입력 >> 행렬 출력

z12 <- function(z) return(c(z, z^2))

x<-1:8

z12(1:8)
##  [1]  1  2  3  4  5  6  7  8  1  4  9 16 25 36 49 64
matrix(z12(x), ncol=2)
##      [,1] [,2]
## [1,]    1    1
## [2,]    2    4
## [3,]    3    9
## [4,]    4   16
## [5,]    5   25
## [6,]    6   36
## [7,]    7   49
## [8,]    8   64
sapply(1:8, z12)
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,]    1    2    3    4    5    6    7    8
## [2,]    1    4    9   16   25   36   49   64

NULL은 매번 원소를 추가해가며 벡터를 생성할 때 사용

1:10에서 짝수로 된 벡터를 생성, NULL은 어떤 형식도 취하지 않는 특별한 객체

NA의 경우 형식이 있다. 다시 말해, 숫자가 들어가야 하나 빈 칸, 문자가 들어가야 하나 빈 칸.

x <- c(5, NA, 12)

mode(x[1])
## [1] "numeric"
mode(x[2])
## [1] "numeric"
x <- c("abd", "def", NA)

mode(x[2])
## [1] "character"
mode(x[3])
## [1] "character"
z<-NULL
z
## NULL
z<-c()
z
## NULL
for (i in 1:10)
{
  if(i%%2 ==0) z <-c(z, i)
}

z
## [1]  2  4  6  8 10

필터링

R의 사칙연산과 부등호는 “모두” 벡터 연산이자 함수

아래 예제에서 중요한 점은 벡터 y를 필터링하기 위해 다른 벡터 z를 인덱스로 사용

z <- c(5, 2, -3, 8)
w <- z[z*z > 8]
w
## [1]  5 -3  8
z*z > 8
## [1]  TRUE FALSE  TRUE  TRUE
z[c(TRUE, FALSE, TRUE, TRUE)]
## [1]  5 -3  8
j <- z*z > 8
j
## [1]  TRUE FALSE  TRUE  TRUE
y <- c(1, 2, 30, 5)

y[j]
## [1]  1 30  5

벡터 x중 3보다 큰 원소를 0으로 치환

x <- c(1, 3, 8, 2, 20)
x
## [1]  1  3  8  2 20
x>3
## [1] FALSE FALSE  TRUE FALSE  TRUE
x[x>3] <- 0

x
## [1] 1 3 0 2 0

만약 subset을 쓴다면 NA를 필터할 수 있다.

x <- c(6, 1:3, NA, 12)
x
## [1]  6  1  2  3 NA 12
x[x>5]
## [1]  6 NA 12
subset(x, x>5)
## [1]  6 12

선택 함수 which()

해당 조건을 만족하는 원소들의 위치만을 찾는다.

z <- c(5, 2, -3, 8)
which(z*z > 8)
## [1] 1 3 4

which를 유용하게 사용하는 법: 어떤 상태가 처음 발생하는 위치 찾기.

first1 <- function(x)
{
  for(i in 1:length(x))
  {
    if(x[i] == 1) break
  }
  i
}


kk <- c(5:1,2:5)

first1(kk)
## [1] 5
which(kk==1)
## [1] 5
first1a <- function(x)
{
  which(kk==1)[1]
}

first1a(kk)
## [1] 5

확장 예제: 연관성 측정

매 시간 별 기온과 기압을 측정해 모은 시계열 벡터 x와 y가 있다. 시간에 따라 x와 y가 증가하고 감소하는 것에 대한 상관관계 정의

즉 y[i+1] - y[i] 가 x[i+1] - x[i]와 같은 현상을 보이는 i의 비율을 보는 것

findud <- function(v)
{
  vud <- v[-1] - v[-length(v)]
  return(ifelse(vud>0, 1, -1))
}

udcorr <- function(x, y)
{
  ud <- lapply(list(x, y), findud)
  mean(ud[[1]] == ud[[2]])
}

x <- c(5, 12, 13, 3, 6, 0, 1, 15, 16, 8, 88)
y <- c( 4, 2, 3, 23, 6, 10, 11, 12, 6, 3, 2)

findud(x)
##  [1]  1  1 -1  1 -1  1  1  1 -1  1
findud(y)
##  [1] -1  1  1 -1  1  1  1 -1 -1 -1
udcorr(x, y)
## [1] 0.4

이걸 줄여보자. sign()은 양수 1, 음수 -1, 0은 0 return

udcorr <- function(x, y) mean(sign(diff(x))==sign(diff(y)))

udcorr(x, y)
## [1] 0.4

벡터 동일성 테스트

x <- 1:3
y <- c(1, 3, 4)

x==y
## [1]  TRUE FALSE FALSE
all(x==y)
## [1] FALSE
identical(x, y)
## [1] FALSE

함정. indentical 은 변수 타입까지 신경쓰지 않는다.

x <- 1:2
y <- c(1, 2)

x
## [1] 1 2
y
## [1] 1 2
identical(x, y)
## [1] FALSE
typeof(x)
## [1] "integer"
typeof(y)
## [1] "double"
mode(x)
## [1] "numeric"
mode(y)
## [1] "numeric"

벡터 원소의 이름

x <- c(1, 2, 4)

names(x) <- c("a", "b", "ab")

x
##  a  b ab 
##  1  2  4
## 원소의 이름을 가지고 찾을 때

x["b"]
## b 
## 2
## 삭제하고 싶을 때

names(x) <- NULL

x
## [1] 1 2 4