Как создать "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
Иногда отсутствуют данные, но у меня нет NA, строки просто не существуют. Мне нужно создавать NA, когда данные отсутствуют. Хотя я мог бы начать с определения того, когда это происходит, преобразовав его в объект зоопарка и проверить на строгую регулярность (я никогда раньше не использовал зоопарк), я использовал следующий код:
z.date<-paste(CET$year, CET$month, CET$day, sep="/")
z <- read.zoo(CET, order.by= z.date )
reg<-is.regular(z, strict = TRUE)
Но ответ всегда верен!
Может кто-нибудь сказать мне, почему не работает? Или даже лучше, скажите мне, как создать NA, когда данные отсутствуют (с пакетом zoo или без него)?
Спасибо
4 ответа
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
Функция для создания набора данных с NA:
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
В пакете зоопарка "обычный" означает, что ряды расположены одинаково, за исключением, возможно, некоторых пропущенных записей. zooreg
Класс в пакете зоопарка специально для этого типа сериалов. Обратите внимание, что множество всех регулярных рядов включает в себя множество всех одинаково разнесенных рядов, но строго больше.
is.regular
Функция проверяет, является ли данная серия регулярной. То есть можно ли сделать серию одинаково разнесенной, если вставить недостающие записи?
Что касается вашего последнего вопроса, это часто задаваемые вопросы. См. FAQ № 13 в разделе часто задаваемых вопросов о зоопарке, доступном на странице зоопарка 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
,