2012-03-05 3 views
3

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

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

+1

Большая проблема со всем этим заключается в том, что 'apply' собирается принуждать к матрице и всем атрибутам (включая то, что делает R« Date »дата будет потеряна. Вам нужно будет использовать' lapply' on столбцы, а не работая над строками. –

+0

Вы просто хотите преобразовать каждую дату в первый месяц? Если это так, нет смысла делать это, работая по строкам по одному, что и есть «apply (test) , 1, ....) '. .. Вы должны сделать что-то вроде' data.frame (lapply (test, ...)) '. Это займет каждый из столбцов' test' и выполнит вычисления на них каждый в свою очередь, а затем преобразовать полученный список столбцов обратно в data.frame. –

ответ

7

Я не знаю, о 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> 
+0

doh! Я знал, что делаю слишком сложно! Большое вам спасибо. Также заметили, что в этом случае лучше работать, чем применять. векторов вместо объектов класса Date в этом экзамене PLE. – tcash21

+0

Да.Он также выглядит так: 'floor_date()' lubridate 'просто не предназначен для обработки' NA ', поэтому вам будет лучше использовать мой код или что-то в этом роде. (Попробуйте 'floor_date (b)' с вашим вектором 'b', чтобы понять, что я имею в виду.) –

1

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

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")) 
2

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

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

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

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

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

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^