본문 바로가기
  • plotly로 바로쓰는 동적시각화 in R & 파이썬
실전에서 바로 쓰는 시계열 데이터 처리와 분석 in R/못다한 이야기

시계열 데이터의 결측치(Missing value) 처리 in R - part 2

by 아참형인간 2022. 9. 9.
xts.knit

이번 포스트에서는 시계열 데이터의 결측치 처리 방법 중 xts 클래스에 따라 살펴보도록 하겠다.

xts와 zoo

xts 클래스와 zoo 클래스는 다른 시계열 클래스와는 달리 특수한 관계에 있다. xts 클래스는 zoo 클래스의 하위 클래스처럼 동작한다. 따라서 zoo 클래스는 부모 클래스, xts 클래스는 자식 클래스로 zoo 클래스에서 정의된 대부분의 기능을 xts클래스로 정의된 데이터에서 사용이 가능하다. 따라서 xtszoo 클래스에서 결측치 처리방법을 알아보겠다.

먼저 필요한 패키지를 로딩하겠다. 그리고 사용하는 데이터는 Part 1에서 사용한 ‘tsAirgap’ 데이터를 xts 클래스 변환하여 사용하도록 하겠다.

데이터 Import

결측치 처리를 위해 사용하는 데이터는 imputeTS 패키지에서 제공하는 tsAirgap 데이터 셋을 사용하도록 하겠다.

if (!require(zoo)) {
  install.packages('zoo')
  library(zoo)
}

if (!require(xts)) {
  install.packages('xts')
  library(xts)
}
index <- lubridate::date_decimal(as.numeric(time(tsAirgap)))

tsAirgap.xts <- xts(tsAirgap, order.by = as.Date(index))

tsAirgap.xts |> head(10)
##            [,1]
## 1949-01-01  112
## 1949-01-31  118
## 1949-03-02  132
## 1949-04-02  129
## 1949-05-02   NA
## 1949-06-02  135
## 1949-07-02  148
## 1949-08-01  148
## 1949-09-01   NA
## 1949-10-01  119
tsAirgap.xts |> plot()

na.locf()

na.locf()는 마지막 관측치를 뒤로 옮겨주는 함수이다.(Last Observation Carried Forward)

tsAirgap.xts |> na.locf() |> head(10)
##            [,1]
## 1949-01-01  112
## 1949-01-31  118
## 1949-03-02  132
## 1949-04-02  129
## 1949-05-02  129
## 1949-06-02  135
## 1949-07-02  148
## 1949-08-01  148
## 1949-09-01  148
## 1949-10-01  119
tsAirgap.xts |> na.locf() |> plot()

위의 결과와 같이 원 데이터에서 NA값이었던 1949-04-02 데이터와 1949-09-01 데이터가 바로 앞의 값으로 채워진 것을 볼 수 있다.

na.approx()

na.approx()는 결측치의 바로 직전 값과 바로 다음 값을 사용하여 시간에 따른 선형 보간법으로 결측치를 채우는 함수이다.

tsAirgap.xts |> na.approx() |> head(10)
##                [,1]
## 1949-01-01 112.0000
## 1949-01-31 118.0000
## 1949-03-02 132.0000
## 1949-04-02 129.0000
## 1949-05-02 131.9508
## 1949-06-02 135.0000
## 1949-07-02 148.0000
## 1949-08-01 148.0000
## 1949-09-01 133.2623
## 1949-10-01 119.0000
tsAirgap.xts |> na.approx() |> plot()

na.fill()

na.fill()는 결측치를 세가지 부분으로 나누어 채우는 함수이다. na.fill()의 매개변수인 ’fill’에 세개의 컴포넌트를 가진 벡터나 리스트를 설정할 수 있는데 첫번째 요소는 맨 왼쪽(시계열의 시작점), 두번째 요소는 시계열 내부 데이터(시계열 시작과 마지막을 제외한), 세번쨰 요소는 맨 오른쪽(시계열의 끝점) 데이터를 지정하여 특정한 값을 채워 넣을 수 있다. 이 요소에서 ’extend’를 명기하면 특정 값을 넣는 것이 아닌 선형 보간을 통한 보정치를 넣어주고 NULL을 명기하면 결측치를 제거해준다.앞에서 실습에 사용한 ’tsAirgap’은 시작점과 마지막점의 데이터가 채워져 있는데 na.fill()의 결과를 보기 위해 NA로 채워넣고 시작하겠다.

tsAirgap.xts.fill <- tsAirgap.xts 

tsAirgap.xts.fill[1] <- NA 

tsAirgap.xts.fill[nrow(tsAirgap.xts.fill)] <- NA  

tsAirgap.xts.fill |> head(10)
##            [,1]
## 1949-01-01   NA
## 1949-01-31  118
## 1949-03-02  132
## 1949-04-02  129
## 1949-05-02   NA
## 1949-06-02  135
## 1949-07-02  148
## 1949-08-01  148
## 1949-09-01   NA
## 1949-10-01  119
tsAirgap.xts.fill |> tail(10)
##            [,1]
## 1960-03-02  419
## 1960-04-01  461
## 1960-05-02   NA
## 1960-06-01  535
## 1960-07-02  622
## 1960-08-01  606
## 1960-09-01  508
## 1960-10-01  461
## 1960-11-01  390
## 1960-12-01   NA
tsAirgap.xts.fill |> plot()

## 결측치 전체를 선형 보간법으로 채움
na.fill(tsAirgap.xts.fill, "extend") |> head(10)
##             [,1]
## 1949-01-01 118.0
## 1949-01-31 118.0
## 1949-03-02 132.0
## 1949-04-02 129.0
## 1949-05-02 132.0
## 1949-06-02 135.0
## 1949-07-02 148.0
## 1949-08-01 148.0
## 1949-09-01 133.5
## 1949-10-01 119.0
na.fill(tsAirgap.xts.fill, "extend") |> tail(10)
##            [,1]
## 1960-03-02  419
## 1960-04-01  461
## 1960-05-02  498
## 1960-06-01  535
## 1960-07-02  622
## 1960-08-01  606
## 1960-09-01  508
## 1960-10-01  461
## 1960-11-01  390
## 1960-12-01  390
na.fill(tsAirgap.xts.fill, "extend") |> plot()

## 첫번째 시계열 값을 선형 보간법으로 중간값은 1000으로 채우는데 마지막 시계열 값에 대한 설정이 없어 첫번쨰 시계열 설정값인 'extend'를 마지막 시계열 설정값으로 사용
na.fill(tsAirgap.xts.fill, c("extend", 1000)) |> head(10)
##            [,1]
## 1949-01-01  118
## 1949-01-31  118
## 1949-03-02  132
## 1949-04-02  129
## 1949-05-02 1000
## 1949-06-02  135
## 1949-07-02  148
## 1949-08-01  148
## 1949-09-01 1000
## 1949-10-01  119
na.fill(tsAirgap.xts.fill, c("extend", 1000)) |> tail(10)
##            [,1]
## 1960-03-02  419
## 1960-04-01  461
## 1960-05-02 1000
## 1960-06-01  535
## 1960-07-02  622
## 1960-08-01  606
## 1960-09-01  508
## 1960-10-01  461
## 1960-11-01  390
## 1960-12-01  390
na.fill(tsAirgap.xts.fill, c("extend", 1000)) |> plot()

## 첫번째 시계열 값을 1, 중간값들은 모두 300, 마지막 값은 500으로 설정
na.fill(tsAirgap.xts.fill, c(1, 300, 500)) |> head(10)
##            [,1]
## 1949-01-01    1
## 1949-01-31  118
## 1949-03-02  132
## 1949-04-02  129
## 1949-05-02  300
## 1949-06-02  135
## 1949-07-02  148
## 1949-08-01  148
## 1949-09-01  300
## 1949-10-01  119
na.fill(tsAirgap.xts.fill, c(1, 300, 500)) |> tail(10)
##            [,1]
## 1960-03-02  419
## 1960-04-01  461
## 1960-05-02  300
## 1960-06-01  535
## 1960-07-02  622
## 1960-08-01  606
## 1960-09-01  508
## 1960-10-01  461
## 1960-11-01  390
## 1960-12-01  500
na.fill(tsAirgap.xts.fill, c(1, 300, 500)) |> plot()

## 첫번째와 마지막 시계열 값은 NA, 중간값은 모두 제거
na.fill(tsAirgap.xts.fill, list(NA, NULL, NA)) |> head(10)
##            [,1]
## 1949-01-01   NA
## 1949-01-31  118
## 1949-03-02  132
## 1949-04-02  129
## 1949-06-02  135
## 1949-07-02  148
## 1949-08-01  148
## 1949-10-01  119
## 1949-11-01  104
## 1949-12-01  118
na.fill(tsAirgap.xts.fill, list(NA, NULL, NA)) |> tail(10)
##            [,1]
## 1960-01-31  391
## 1960-03-02  419
## 1960-04-01  461
## 1960-06-01  535
## 1960-07-02  622
## 1960-08-01  606
## 1960-09-01  508
## 1960-10-01  461
## 1960-11-01  390
## 1960-12-01   NA
na.fill(tsAirgap.xts.fill, list(NA, NULL, NA)) |> plot()

댓글