R lubridate - 使用apply和minute时出错

时间:2014-06-22 19:41:20

标签: r lubridate

我有一个与period包中的lubridate个对象一起使用的函数。具体来说,我使用minute()函数时遇到错误,同时使用分钟内部apply-ie:apply(data, 2, minute)

我编写的函数是将mean, sd, etc转换为数字(秒数)后使用句点对象的包装器。这是代码:

conv_ms <- function(x, func= "mean", na.rm=TRUE, ...) {
  # extract min/sec, convert to numeric
  m <- minute(x)
  s <- second(x)
  mns <- m * 60 + s
  # apply wrapper
  if (func == "mean") {
    x2 <- mean(mns, na.rm= na.rm)
  } else if (func == "sd") {
    x2 <- sd(mns, na.rm= na.rm)
  } else if (func == "median") {
    x2 <- median(mns, na.rm= na.rm) 
  } else if (func == "quantile") {
    x2 <- quantile(mns, na.rm= na.rm, ...)
  } else if (func == "min") {
    x2 <- min(mns, na.rm= na.rm)
  } else if (func == "max") {
    x2 <- max(mns, na.rm= na.rm)
  }
  m2 <- trunc(x2 / 60)
  s2 <- round((x2 - trunc(x2 / 60)) * 60, 0)
  return(ms(paste(as.character(m2), as.character(s2), sep=":")))
}

执行。当我执行该函数时,使用minute()收到错误。但是minuteapply框架之外正常运行。

# run above function -- error message and traceback
conv_ms(men_g[, c(10:11)], na.rm=T)
Error in as.POSIXlt.default(x, tz = tz(x)) : 
  do not know how to convert 'x' to class “POSIXlt” 
5 stop(gettextf("do not know how to convert '%s' to class %s", 
    deparse(substitute(x)), dQuote("POSIXlt")), domain = NA) 
4 as.POSIXlt.default(x, tz = tz(x)) 
3 as.POSIXlt(x, tz = tz(x)) 
2 minute.default(x) 
1 conv_ms(men_g[, c(10:11)], na.rm = T) 

# isolate the error -- show error message
# appears to not work within apply
apply(men_g[, c(10:11)], 2, minute)
Error in as.POSIXlt.numeric(x, tz = tz(x)) : 'origin' must be supplied

# but minute works on an isolated vector
minute(men_g[, 10])
 [1] 20 20 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 20 21 21 21 20 21 21 20 21 21 21 21 21
[35] 21 21 21 21 21 21 21 22 22

数据 - 已编辑以使用dput

dput(men_g[,10:11])
structure(list(ev6_raw = structure(c(29, 53, 27, 14, 6, 34, 51, 
6, 18, 15, 5, 4, 7, 34, 11, 51, 58, 19, 39, 8, 30, 56, 14, 37, 
9, 24, 46, 28, 51, 39, 25, 51, 40, 50, 45, 36, 52, 18, 46, 40, 
36, 16, 42), year = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0), month = c(0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), day = c(0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), hour = c(0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
), minute = c(20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 
21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 21, 21, 21, 20, 21, 21, 
20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22), class = structure("Period", package = "lubridate")), 
    ev7_raw = structure(c(44, 52, 38, 3, 55, 46, 7, 54, 6, 5, 
    12, 22, 0, 56, 23, 56, 45, 6, 24, 1, 5, 10, 24, 10, 27, 31, 
    33, 57, 19, 43, 4, 4, 11, 10, 53, 13, 10, 22, 21, 6, 58, 
    52, 51), year = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), month = c(0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), day = c(0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0), hour = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), minute = c(1, 1, 1, 
    2, 1, 1, 2, 1, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 2, 2, 2, 3, 
    2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 
    1, 2), class = structure("Period", package = "lubridate"))), .Names = c("ev6_raw", 
"ev7_raw"), class = "data.frame", row.names = c(1L, 2L, 3L, 4L, 
5L, 6L, 7L, 8L, 9L, 11L, 12L, 13L, 14L, 16L, 17L, 18L, 19L, 20L, 
21L, 22L, 23L, 24L, 25L, 26L, 30L, 31L, 33L, 34L, 35L, 39L, 41L, 
42L, 43L, 44L, 53L, 54L, 67L, 68L, 70L, 72L, 82L, 83L, 165L))

1 个答案:

答案 0 :(得分:-1)

当您看到错误消息时,请考虑一下它所说的内容,而不是只是举起手来说“#34;它不起作用&#34;。它还有助于正确拼写课程(&#39;期间&#39;),以便您知道在使用methodsgetMethods时将应用哪些功能。

> methods(minute)
[1] minute.default* minute.Period* 

   Non-visible functions are asterisked
> help(pack='lubridate')
showMethods(classes="Period")   # extensive output not included

&#34;期间&#34;上面的对象显然是列出具有一堆保存信息的属性的对象。 POSIXlt对象存在问题的原因之一是它们不能很好地被apply - 函数传递,因为它将其项强制转换为原子向量。与POSIXlt对象一样,Period-objects应通过保持附加到其属性列表来携带其值。从Period-object中删除属性时,将删除有关分钟,天,月和年的所有信息。

我得到你可能早先搞砸的感觉,因为Period-classed对象假设是带有插槽的S4对象,你有一个普通的S3类列表,其中包含数据属性&#34;

men_g[[1]]
 [1] 29 53 27 14  6 34 51  6 18 15  5  4  7 34 11 51 58 19 39  8 30 56 14 37  9 24 46 28 51 39 25 51
[33] 40 50 45 36 52 18 46 40 36 16 42
attr(,"year")
 [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
attr(,"month")
 [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
attr(,"day")
 [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
attr(,"hour")
 [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
attr(,"minute")
 [1] 20 20 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 20 21 21 21 20 21 21 20 21 21 21
[33] 21 21 21 21 21 21 21 21 21 22 22
attr(,"class")
[1] "Period"
attr(,"class")attr(,"package")
[1] "lubridate"

在str-microscope下,Period对象应该是什么样子:

> span <- new_interval(as.POSIXct("2009-01-01"), as.POSIXct("2010-02-02 01:01:01")) #interval
> # 2009-01-01 CST--2010-02-02 01:01:01 CST
> str(as.period(span))
Formal class 'Period' [package "lubridate"] with 6 slots
  ..@ .Data : num 1
  ..@ year  : num 1
  ..@ month : num 1
  ..@ day   : num 1
  ..@ hour  : num 1
  ..@ minute: num 1