2011-12-13 83 views
14

Tôi có một số nghi ngờ về tính năm nhuận, làm thế nào tôi có thể chắc chắn rằng bằng cách sử dụng một công thức như thế nàyLàm thế nào để tính toán cho năm nhuận?

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) 
} 

nó sẽ mất vào năm tài khoản bước nhảy vọt, khi thêm ví dụ 100 năm để tập dữ liệu quan sát của tôi? Làm thế nào tôi có thể kiểm soát điều này?

Tôi có một chuỗi thời gian tập dữ liệu với 50 năm quan sát:

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 

bộ dữ liệu + 100 năm

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 

Sau khi kiểm tra cơ bản, tôi đã nhận thấy rằng số hàng là tương tự cho cả bản gốc và 100 năm sau tập dữ liệu. Tôi không chắc chắn nếu những gì đã được trước khi Februray thứ 29 trong một năm nhuận sẽ là giá trị ám ảnh cho ngày 1 tháng 3 trong một năm không nhuận, v.v.

Tôi có thể kiểm tra năm nhuận sử dụng từ thư viện chron chức năng leap.year, tuy nhiên tôi muốn biết nếu có một cách đơn giản hơn để làm điều này, để đảm bảo rằng các hàng có ngày vượt qua ngày 29 tháng 2 không tồn tại 100 năm sau khi bị xóa và ngày mới của ngày 29 tháng 2 được thêm vào với các giá trị NA.

+2

Việc trộn các định dạng 'POSIXlt' và' Date' sẽ chỉ kết thúc trong các lỗi và nước mắt mơ hồ. –

+0

Tôi xác nhận! Tốt hơn dành chút thời gian để dọn sạch mã của tôi. Cảm ơn! –

Trả lời

13

Bạn có thể kiểm tra xem một năm có phải là năm nhuận hay không với leap_year từ lubridate.

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

Gói này cũng sẽ xử lý không tạo ra 29 tháng 2 không thể.

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

Các "thêm tháng" hành %m+%, như đã đề cập bởi @VitoshKa, cuộn ngày trở lại vào cuối tháng trước nếu ngày thực tế không tồn tại.

+0

'lubridate' dường như không thể xử lý việc này nữa. Tôi nhận được 'NA' khi tôi cố gắng thêm một năm vào một ngày nhuận. – rrs

+1

Hành vi trong lubridate đã được thay đổi khá lâu trước đây. Bạn sẽ nhận được NA vào ngày không hợp lệ. Xem tài liệu về [% m +%] (http://finzi.psych.upenn.edu/library/lubridate/html/mplus.html) nếu bạn muốn có hành vi lăn. Ngoài ra, tài liệu cho 'period' và' Period-Class'. – VitoshKa

3

Một năm là năm nhuận nếu:

  • là chia hết cho 4.
  • Không nếu nó chia hết cho 100.
  • Nhưng nếu nó là chia hết cho 400.

Đó là lý do tại sao năm 2000 là năm nhuận (mặc dù nó chia hết cho 100, nhưng cũng chia hết cho 400).

Nhưng nói chung, nếu bạn có thư viện có thể tính toán ngày/giờ thì hãy sử dụng tính năng này. Nó rất phức tạp để thực hiện những phép tính này và dễ làm sai, đặc biệt là với những ngày cổ xưa (cải cách lịch) và múi giờ có liên quan.

+0

Tôi vẫn không tìm thấy bất kỳ chức năng nào cho phép tôi thực hiện loại sửa đổi này thành tập dữ liệu, tôi đoán tôi phải tự mình tạo một tập dữ liệu. –

+0

Không, bạn không có. Hiện có chức năng trong cơ sở R, cũng như trong các gói CRAN. –

+0

Toby Marthews-3 cung cấp một tuyên bố 'ifelse' gọn gàng để xử lý những năm nhuận ở đây: http://r.789695.n4.nabble.com/leap-year-and-order-function-td3248104.html –

1

nghi ngờ của bạn có thực sự chính xác:

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

Điều lạ là các bộ phận khác của y vẫn không thay đổi nên bạn không thể dùng những thứ này so sánh:

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

Nhưng bạn có thể sử dụng strftime :

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

Vậy làm thế nào về:

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) 
    } 

Sau đó, bạn có thể chia nhỏ dữ liệu của mình bằng cách sử dụng [is.na để loại bỏ các ngày trùng lặp khác vào ngày 1 tháng 3. Mặc dù những ngày này dường như liên tiếp, bạn có thể muốn xem xét một giải pháp sử dụng seq.Date và tránh xóa dữ liệu.

+2

2100 không phải là một năm nhuận, vì vậy việc tính toán trong ví dụ đầu tiên của bạn có vẻ đúng với tôi. –

Các vấn đề liên quan