如何对R中的日期组件进行算术运算

时间:2015-02-03 07:42:32

标签: r date

我试图计算日期组件的功能(年,月,日)。我正在将数据读入数据框,将字符串解析为日期,然后,我希望,对日期的组件进行一些算术运算。

这是我的数据文件:

timestamp,value
"2014-01-23 12:30:00",123
"2015-11-30 15:45:00",456
"2016-07-29 09:15:00",789

这是我的R会话:(我在Ubuntu 14.04上使用R 3.0.2)

> x <- read.csv ("foo.csv", row.names=NULL, header=T)
> x
            timestamp value
1 2014-01-23 12:30:00   123
2 2015-11-30 15:45:00   456
3 2016-07-29 09:15:00   789
> x1 <- as.vector (x[, 1])
> x1
[1] "2014-01-23 12:30:00" "2015-11-30 15:45:00" "2016-07-29 09:15:00"
> x1.t <- strptime (x1, "%Y-%m-%d %H:%M:%S")
> x1.t
[1] "2014-01-23 12:30:00" "2015-11-30 15:45:00" "2016-07-29 09:15:00"
> x1.t.combo <- sapply (x1.t, function (t) { (t$year - 114)*12 + (t$mon + 1) })
Error in t$year : $ operator is invalid for atomic vectors

$应用于x1.t的元素似乎按预期工作,例如(x1.t[1]$year - 114)*12 + (x1.t[1]$mon + 1)会产生1。导致错误讯息的原因是什么?

我发现(x1.t$year - 114)*12 + (x1.t$mon + 1)按预期产生了1 23 31,所以我认为用sapply找出业务并不是真的有必要,但我仍然我想知道,为了理解发生了什么。

2 个答案:

答案 0 :(得分:2)

您遇到的问题是POSIXlt本身是一个具有多个元素的类型,因此* apply命令将函数应用于它的每个元素。您可以按unlist(x1.t)

查看元素

所以你必须&#34;四处走动&#34;它。这是一个简单的方法,你不必先转换它:

> x <- c("2014-01-23 12:30:00", "2015-11-30 15:45:00")
> x
[1] "2014-01-23 12:30:00" "2015-11-30 15:45:00"
> y <- sapply (x, function (t) { t <- as.POSIXlt(t); (t$year - 114)*12 + (t$mon + 1) })
> y
2014-01-23 12:30:00 2015-11-30 15:45:00 
                  1                  23 

但是如果你真的想先转换它,那么你必须先将它转换为数字或字符,然后再次转换回函数内部。像这样:

> x <- c(strptime("2014-01-23 12:30:00", "%Y-%m-%d %H:%M:%S"), strptime("2015-11-30 15:45:00", "%Y-%m-%d %H:%M:%S"))
> x
[1] "2014-01-23 12:30:00 EET" "2015-11-30 15:45:00 EET"
> y <- sapply (as.numeric(x), function (t) { t <- as.POSIXlt(t, origin = "1970-01-01"); (t$year - 114)*12 + (t$mon + 1) })
> y
[1]  1 23

答案 1 :(得分:2)

sapplylapply都会产生相同的错误,因为x1.t是一个列表,并且它们会逐个传递列表中的元素。第一个是3元素(原子,非递归)秒矢量

> x1.t[[1]]   # same as x1.t[['sec']]
[1] 0 0 0

....而且它(和所有其他组件)没有名字传递。因此,即使是第5个或第6个列表的年份元素在到达该匿名函数的主体时仍然没有“年份”的名称。

dput(x1.t)
structure(list(sec = c(0, 0, 0), min = c(30L, 45L, 15L), hour = c(12L, 
15L, 9L), mday = c(23L, 30L, 29L), mon = c(0L, 10L, 6L), year = 114:116, 
    wday = c(4L, 1L, 5L), yday = c(22L, 333L, 210L), isdst = c(0L, 
    0L, 1L), zone = c("PST", "PST", "PDT"), gmtoff = c(NA_integer_, 
    NA_integer_, NA_integer_)), .Names = c("sec", "min", "hour", 
"mday", "mon", "year", "wday", "yday", "isdst", "zone", "gmtoff"
), class = c("POSIXlt", "POSIXt"))

这类似于人们认为data.frame中的第一个元素是第一行或者data.frame的长度是个案数量(当它实际上是列数时)的错误。)