这似乎应该更容易,我相信有人可以帮助我。我正在尝试使用lubridate包中的floor_date()将日期的data.frame更改为每个日期到其各自月份的第一个日期,但是其中一些日期是NA。我宁愿不用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
感谢您的帮助!
答案 0 :(得分: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>
答案 1 :(得分: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))
)
答案 2 :(得分: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"))
答案 3 :(得分: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
。
答案 4 :(得分:1)
floor_date()中的NA错误在今天发送到CRAN的lubridate 1.1.0中得到修复。日期的S3更新方法中的NA错误仍然存在(在开发版本中已修复)。与此同时,
floor_date(as.POSIXlt(test$b), unit = "month")
会起作用。