2011-12-13 19 views
14

mam pewne wątpliwości lata przestępne, jak mogę być pewny, że za pomocą tej formuły jakJak rozliczyć lata przestępne?

add.years= function(x,y){  
if(!isTRUE(all.equal(y,round(y)))) stop("Argument \"y\" must be an integer.\n") 
x <- as.POSIXlt(x) 
x$year <- x$year+y 
as.Date(x) 
} 

weźmie pod konto lat przestępnych, podczas dodawania na przykład 100 lat moim zbiorze obserwacji? Jak mogę to kontrolować?

Mam zestaw danych szeregów czasowych z 50 lat obserwacji:

date obs 
1995-01-01 1.0 
1995-01-02 2.0 
1995-01-03 2.5 
... 
2045-12-30 0.2 
2045-12-31 0.1 

zestawu danych + 100 lat

date obs 
2095-01-01 1.0 
2095-01-02 2.0 
2095-01-03 2.5 
... 
2145-12-30 0.2 
2145-12-31 0.1 

Po podstawowej czeku, zauważyłem, że liczba wierszy jest to samo dla oryginału i 100 lat po zestawie danych. Nie jestem pewien, czy to, co było przed 29. Februray w roku przestępnym, będzie teraz wartością obs na 1 marca w roku wolnym od skoku, itp.

Mogę sprawdzić lata przestępne korzystając z biblioteki chronologicznej funkcja leap.year, jednak chciałbym wiedzieć, czy jest prostszy sposób, aby to zrobić, aby upewnić się, że wiersze z dniami przejściowymi z dnia 29 lutego, które nie istnieją 100 lat po zostaną usunięte, i nowe dni z 29 lutego są dodawane z wartościami NA.

+2

Mieszanie formatów "POSIXlt" i "Date" kończy się tylko w niezrozumiałych błędach i łzach. –

+0

Potwierdzam! Lepiej poświęć trochę czasu na wyczyszczenie mojego kodu. Dzięki! –

Odpowiedz

13

Możesz sprawdzić, czy rok jest rokiem przestępnym z leap_year z lubridate.

years <- 1895:2005 
years[leap_year(years)] 

Ten pakiet będzie również obsługiwać nie generowanie niemożliwe 29 lutego.

ymd("2000-2-29") + years(1) # NA 
ymd("2000-2-29") %m+% years(1) # "2001-02-28" 

Operator %m+% „dodać miesięcy”, jak wspomniano przez @VitoshKa, rzuca sięgają do końca poprzedniego miesiąca, jeśli rzeczywisty dzień nie istnieje.

+0

'Lubridate' nie wydaje się już w stanie sobie z tym poradzić. Dostaję "NA", gdy próbuję dodać rok do dnia przestępnego. – rrs

+1

Zachowanie w lubridate zmieniło się całkiem niedawno. Otrzymasz NA w nieprawidłowych datach. Zobacz dokument [% m +%] (http://finzi.psych.upenn.edu/library/lubridate/html/mplus.html), jeśli chcesz zachowywać się w sposób toczący. Także dokumenty dla "okresu" i "klasy okresu". – VitoshKa

3

rok jest rokiem przestępnym, jeśli:

  • jest podzielna przez 4.
  • Nie, jeśli to jest podzielna przez 100.
  • Ale to, czy jest podzielny przez 400.

Dlatego właśnie rok 2000 był rokiem przestępnym (chociaż jest podzielny przez 100, jest również podzielny przez 400).

Ale ogólnie rzecz biorąc, jeśli masz bibliotekę, która może wykonywać obliczenia daty/czasu, użyj jej. Wykonanie tych obliczeń jest bardzo skomplikowane i łatwe do wykonania, szczególnie w przypadku dat starożytnych (reformy kalendarza) i stref czasowych.

+0

Nadal nie znajduję żadnej funkcji, która pozwoli mi na dokonanie tego typu modyfikacji w zestawie danych, myślę, że muszę go sam stworzyć. –

+0

Nie, nie. Istnieje funkcjonalność w bazie R, a także w pakietach CRAN. –

+0

Toby Marthews-3 stanowi zgrabne oświadczenie 'ifelse' do obsługi lat przestępnych tutaj: http://r.789695.n4.nabble.com/leap-year-and-order-function-td3248104.html –

1

Twoje podejrzenia są rzeczywiście poprawne:

x <- as.POSIXlt("2000-02-29") 
y <- x 
y$year <- y$year+100 
y 
#[1] "2100-03-01" 

Najdziwniejsze jest to, że inne części y pozostają niezmienione, więc nie można z nich korzystać w celu porównania:

y$mday 
#[1] 29 
y$mon 
#[1] 1 

Ale można użyć strftime :

strftime(x,"%d") 
#[1] "29" 
strftime(y,"%d") 
#[1] "01" 

A co powiesz na:

add.years <- function(x,y){ 
    if(!isTRUE(all.equal(y,round(y)))) stop("Argument \"y\" must be an integer.\n") 
    x.out <- as.POSIXlt(x) 
    x.out$year <- x.out$year+y 
    ifelse(strftime(x,"%d")==strftime(x.out,"%d"),as.Date(x.out),NA) 
    } 

Można wtedy podzbiór danych przy użyciu [ i is.na pozbyć 1st skądinąd zdublowane daty marcu. Mimo że te daty wydają się być kolejne, możesz rozważyć rozwiązanie, które używa seq.Date i unikaj upuszczania danych.

+2

2100 nie jest rok przestępny, więc obliczenia w twoim pierwszym przykładzie wydają mi się poprawne. –

Powiązane problemy