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

у меня есть несколько файлов данных, которые выглядят так:

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 или без него)?

спасибо

4 ответов


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

Edit: эта функция задокументирована в ?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"

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

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

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

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

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

vignette("zoo-faq") 

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


первое, что нужно отметить, это 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

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

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.