Использование apply для преобразования дат в R и обработки дат NA - PullRequest
3 голосов
/ 06 марта 2012

Кажется, это должно быть намного проще, и я уверен, что кто-то может мне помочь. Я пытаюсь изменить каждую дату на первую в соответствующем месяце с даты data.frame, используя floor_date () в пакете lubridate, однако некоторые из этих дат являются NA. Я бы не стал заменять фиктивные даты для НС.

Я попробовал следующее:

library(lubridate)
a<-c(as.Date("2011-05-04"), as.Date("2011-06-12"))
b<-c(as.Date("2012-03-01"), NA)
test <- data.frame(a,b)

apply(test, 1, function(y) sapply(y, function(x) if(!is.na(x)) floor_date(x, "month") else na.pass(x)))
apply(test, 1, function(y) ifelse(!is.na(y)), floor_date(y, "month"), na.pass(y))

Первый звонок возвращается:

Error in object[[name, exact = TRUE]] : subscript out of bounds

Второй вызов возвращает:

Error in update.default(x, mdays = 1, hours = 0, minutes = 0, seconds = 0) : 
need an object with call component

Спасибо за любую помощь!

Ответы [ 5 ]

7 голосов
/ 06 марта 2012

Я не знаю о lubridate, но вы могли бы сделать это легко с отличными средствами обработки данных, предоставляемыми базой R.

Вот небольшая вспомогательная функция, которая должна выполнять необходимые вычисления без жалоб:

firstOfMonth <- function(dates) {
    as.Date(strftime(dates, format="%Y-%m-01"))
}

firstOfMonth(a)
# [1] "2011-05-01" "2011-06-01"
firstOfMonth(b)
# [1] "2012-03-01" NA   

data.frame(lapply(test, firstOfMonth))
#            a          b
# 1 2011-05-01 2012-03-01
# 2 2011-06-01       <NA>
2 голосов
/ 06 марта 2012

Вы пробовали пакет зоопарка?

library(zoo)
a<-c(as.Date("2011-05-04"), as.Date("2011-06-12"))
b<-c(as.Date("2012-03-01"), NA)
test <- data.frame(
        "a" = as.Date(as.yearmon(a)),
        "b" = as.Date(as.yearmon(b))
)
1 голос
/ 06 марта 2012

Ошибка NA в floor_date () исправлена ​​в lubridate 1.1.0, который был отправлен сегодня в CRAN. Ошибка NA в методе обновления S3 для дат сохраняется (исправлена ​​в версии для разработчиков). В то же время,

floor_date(as.POSIXlt(test$b), unit = "month")

будет работать.

1 голос
/ 06 марта 2012

Если вы хотите сделать это в одной строке, как вы пытались, это будет работать:

data.frame(lapply(test,function (y) (as.Date(sapply(y,function(x) if (is.na(x)) NA else floor_date(x,'month'))))))

Настоящая проблема здесь - сама функция lubridate, которая должна позволить вам пройтипараметр update.Date, указывающий игнорировать NA.Решение strftime, приведенное выше, определенно является самым чистым.

Кроме того, как уже упоминалось в комментариях, причина, по которой ваше решение не сработало, заключалась в том, что вы использовали apply вместо lapply.

1 голос
/ 06 марта 2012

Как насчет этого?

my_floor_date <- function(x,...) {idx <- !is.na(x); x[idx] <- floor_date(x[idx], ...); x}
transform(test, a=my_floor_date(a, "month"), b=my_floor_date(b, "month"))
...