Jak utworzyć "NA" dla brakujących danych w szeregu czasowym

Mam kilka plików danych, które wyglądają tak:

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

Czasami brakuje danych, ale nie mam NAs, wiersze po prostu nie istnieją. Muszę utworzyć NAs, gdy brakuje danych. Chociaż mogłem zacząć od zidentyfikowania, kiedy to nastąpi, konwertując go do obiektu zoo i sprawdzając ścisłą regularność( nigdy wcześniej nie korzystałem z zoo), użyłem następującego kodu: {]}

z.date<-paste(CET$year, CET$month, CET$day, sep="/")
z <- read.zoo(CET,  order.by= z.date )
reg<-is.regular(z, strict = TRUE)
Ale odpowiedź jest zawsze prawdziwa! Czy ktoś może mi powiedzieć, dlaczego nie działa? Lub nawet lepiej, powiedz mi, jak utworzyć NAs, gdy brakuje danych (z pakietem zoo lub bez niego)?

Dzięki

Author: Joshua Ulrich, 2011-05-19

4 answers

Funkcja seq posiada kilka ciekawych funkcji, które można wykorzystać do łatwego wygenerowania pełnej sekwencji dat. Na przykład, poniższy kod może być użyty do wygenerowania sekwencji dat rozpoczynających się 25 kwietnia:

Edit: Ta funkcja jest udokumentowana w ?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"

Teraz użyj tej samej zasady, aby wygenerować niektóre dane z "brakującymi" wierszami, generując sekwencję dla każdego drugiego dnia:

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

Aby odpowiedzieć na twoje pytanie, można użyć Vector subscripting lub funkcja match do tworzenia zestawu danych za pomocą serwera NAs:

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

Aby połączyć ten wynik z oryginalnymi pełnymi danymi:

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
 21
Author: Andrie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-22 15:44:13

W pakiecie zoo "regular" oznacza, że seria jest równo rozłożona z wyjątkiem niektórych brakujących wpisów. Klasa zooreg w pakiecie zoo jest specjalnie dla tego typu serii. Należy pamiętać, że zestaw wszystkich serii regularnych zawiera zestaw wszystkich jednakowo rozmieszczonych serii, ale jest ściśle większy.

Funkcja is.regular sprawdza, czy dany szereg jest regularny. Oznacza to, że seria może być równo rozłożona, jeśli ktoś włoży NAs do brakującego wpisy?

Jeśli chodzi o twoje ostatnie pytanie, to FAQ. Zobacz FAQ #13 w FAQ zoo dostępnym ze strony zoo CRAN lub z wewnątrz R poprzez:

vignette("zoo-faq") 

Również w FAQ #13 jest jakiś kod ilustracyjny.

 4
Author: G. Grothendieck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-21 12:28:40

Pierwszą rzeczą, którą należy zauważyć jest to, że z.date jest znak, a nie DATA.

Oto jak rozwiązałbym twój problem używając xts (podklasa 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
 3
Author: Joshua Ulrich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-19 13:05:51

Miałem do czynienia z podobnym problemem z miesięcznym szeregiem czasowym. Zrobiłem to z bezpośrednim połączeniem dwóch data.table/data.frame przez zmienną czasu. Chodzi mi o to, że szeregi czasowe są również rodzajem zbiorów danych. Możesz więc również manipulować dowolnymi seriami czasowymi jako regularnym zestawem danych w regularny sposób. Oto moje rozwiązanie:

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

Po tym można łatwo zmienić klasę zbioru danych z powrotem do dowolnego typu szeregów czasowych, które chcesz mieć. Wolałem read.zoo.

 0
Author: Yang Bai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-13 18:31:32