Как создать «NA» для отсутствующих данных во временном ряду

#r #time-series #missing-data

#r #временные ряды #отсутствуют данные

Вопрос:

У меня есть несколько файлов данных, которые выглядят следующим образом:

 X code year month day pp  
1 4515 1953     6   1  0  
2 4515 1953     6   2  0  
3 4515 1953     6   3  0  
4 4515 1953     6   4  0  
5 4515 1953     6   5  3.5
  

Иногда отсутствуют данные, но у меня нет NAs, строки просто не существуют. Мне нужно создать NAS, когда отсутствуют данные. Хотя Я мог бы начать с определения того, когда это происходит, путем преобразования его в объект zoo и проверки строгой регулярности (я никогда раньше не использовал zoo), я использовал следующий код:

 z.date<-paste(CET$year, CET$month, CET$day, sep="/")
z <- read.zoo(CET,  order.by= z.date )
reg<-is.regular(z, strict = TRUE)
  

Но ответ всегда верен!

Кто-нибудь может сказать мне, почему не работает? Или, что еще лучше, скажите мне способ создать NAS, когда отсутствуют данные (с пакетом zoo или без него)?

Спасибо

Комментарии:

1. Вы имеете в виду, что ваши данные не содержат строки для некоторых дат? И как это связано с вашими первыми двумя столбцами (X и code)?

Ответ №1:

seq Функция обладает некоторыми интересными функциями, которые вы можете использовать, чтобы легко сгенерировать полную последовательность дат. Например, следующий код может быть использован для генерации последовательности дат, начинающихся 25 апреля:

Редактировать: Эта функция задокументирована в ?seq.Date

 start = as.Date("2011/04/25")
full <- seq(start, by='1 day', length=15)
full

 [1] "2011-04-25" "2011-04-26" "2011-04-27" "2011-04-28" "2011-04-29"
 [6] "2011-04-30" "2011-05-01" "2011-05-02" "2011-05-03" "2011-05-04"
[11] "2011-05-05" "2011-05-06" "2011-05-07" "2011-05-08" "2011-05-09"
  

Теперь используйте тот же принцип для генерации некоторых данных с «отсутствующими» строками, генерируя последовательность для каждого второго дня:

 partial <- data.frame(
    date=seq(start, by='2 day', length=6),
    value=1:6
)
partial

        date value
1 2011-04-25     1
2 2011-04-27     2
3 2011-04-29     3
4 2011-05-01     4
5 2011-05-03     5
6 2011-05-05     6
  

Чтобы ответить на ваш вопрос, можно использовать векторную подписку или match функцию для создания набора данных с помощью NAs:

 with(partial, value[match(full, date)])
 [1]  1 NA  2 NA  3 NA  4 NA  5 NA  6 NA NA NA NA
  

Чтобы объединить этот результат с исходными полными данными:

 data.frame(Date=full, value=with(partial, value[match(full, date)]))
         Date value
1  2011-04-25     1
2  2011-04-26    NA
3  2011-04-27     2
4  2011-04-28    NA
5  2011-04-29     3
6  2011-04-30    NA
7  2011-05-01     4
8  2011-05-02    NA
9  2011-05-03     5
10 2011-05-04    NA
11 2011-05-05     6
12 2011-05-06    NA
13 2011-05-07    NA
14 2011-05-08    NA
15 2011-05-09    NA
  

Комментарии:

1. 1 за классный недокументированный трюк. Опять же: это задокументировано: ?seq. Дата (-:

2. @Nick Спасибо, что показал мне, где найти документы. Я обнаружил эту функцию пять минут назад в списках рассылки R, используя мою любимую поисковую систему, но не смог найти никаких ссылок на это в ?seq.

Ответ №2:

В пакете zoo «обычный» означает, что ряды расположены с одинаковым интервалом, за исключением, возможно, некоторых отсутствующих записей. zooreg Класс в пакете zoo предназначен специально для этого типа рядов. Обратите внимание, что набор всех регулярных рядов включает в себя набор всех равноудаленных рядов, но строго больше.

is.regular Функция проверяет, является ли данный ряд регулярным. То есть, можно ли сделать последовательность равномерно распределенной, если вставить NAs для отсутствующих записей?

Что касается вашего последнего вопроса, это FAQ. Смотрите FAQ # 13 в часто задаваемых вопросах zoo, доступных на странице zoo CRAN или внутри R через:

 vignette("zoo-faq") 
  

Также в FAQ # 13 есть некоторый иллюстративный код.

Ответ №3:

Первое, на что следует обратить внимание, это то, что z.date это символ, а не дата.

Вот как я бы решил вашу проблему, используя xts (подкласс zoo).

 # remove the third obs from sample data
CET <- CET[-3,]
# create an actual Date column in CET
CET$date <- as.Date(with(CET, paste(year, month, day, sep="-")))
# create an xts object using 'date' column
x <- xts(CET[,c("code","pp")], CET$date)
# now merge 'x' with a regular date sequence spanning the start/end of 'x'
X <- merge(x, timeBasedSeq(paste(start(x), end(x), sep="::")))
X
#            code  pp
# 1953-06-01 4515 0.0
# 1953-06-02 4515 0.0
# 1953-06-03   NA  NA
# 1953-06-04 4515 0.0
# 1953-06-05 4515 3.5
  

Комментарии:

1. функции timeBasedSeq повторяют некоторые из создаваемых ими дней! Что вызывает проблемы с zoo, потому что «записи индекса в ‘order.by ’не уникальны». например, timeBasedSeq («19860601/19861231″) создаст …»1986-10-25» «1986-10-26» «1986-10-26» «1986-10-27″… как я могу этого избежать?

Ответ №4:

Мне приходилось сталкиваться с аналогичной проблемой с месячным временным рядом. Я сделал это, напрямую объединив два data.table / data.frame с помощью переменной time. Я хочу сказать, что временные ряды — это тоже своего рода наборы данных. Таким образом, вы также можете манипулировать любым временным рядом как обычным набором данных обычным способом. Вот мое решение:

 library(zoo)    
(full <- data.table(yrAndMo = as.yearmon(seq(as.Date('2008-01-01'), by = '1 month', length = someLength)))) 
# the full time horizon that you want to have
#  yrAndMo
#  1: Jan 2008
#  2: Feb 2008
#  3: Mar 2008
#  4: Apr 2008
#  5: May 2008
# ---         
# 98: Feb 2016
# 99: Mar 2016
# 100: Apr 2016
# 101: May 2016
# 102: Jun 2016

exampleDat # the actually data you want to append to the full time horizon
# yrAndMo someValue
# 1 Mar 2010      7500
# 2 Jun 2010      1115
# 3 Mar 2011      2726
# 4 Apr 2011      1865
# 5 Nov 2011      1695
# 6 Dec 2012     10000
# 7 Mar 2016      1000

library(plyr)
join(full, exampleDat, by = 'yrAndMo', type = "left")
#   yrAndMo someValue
#   1: Jan 2008        NA
#   2: Feb 2008        NA
#   3: Mar 2008        NA
#   4: Apr 2008        NA
#   5: May 2008        NA
#  ---                   
#  98: Feb 2016        NA
#  99: Mar 2016      1000
# 100: Apr 2016        NA
# 101: May 2016        NA
# 102: Jun 2016        NA
  

после этого вы можете легко изменить класс набора данных обратно на любой тип временных рядов, который вы хотите иметь. Я предпочел read.zoo .