如何使用lapply代替for循环?

时间:2018-11-20 16:53:14

标签: r

我正在尝试计算一个被认为是晚上的时间间隔中的小时数(此处从16:00开始计算)。下面是一个示例。

                start                 end  evening
1 2018-01-01 10:47:05 2018-01-01 16:36:03 0.600924
2 2018-01-02 04:05:56 2018-01-02 14:24:59 0.000000
3 2018-01-02 13:37:41 2018-01-03 00:47:31 5.000000
4 2018-01-02 22:53:31 2018-01-03 04:43:59 0.000000
5 2018-01-03 17:04:20 2018-01-03 22:27:39 3.927569

我创建了一个函数f_overlap(),用于计算每行的傍晚小时数。在for循环中运行它看起来像这样:

library(lubridate)

...

for (row in 1:nrow(df)) {
  df$evening[row] <- f_overlap(eveningStart,
                               eveningEnd,
                               interval(df[row,'start'], df[row,'end']))
}

我无法使用lapply()而不是for循环,而且我在那儿读到的教程以及在那儿读到的问题都没有到目前为止没有任何帮助。因此,有人可以在这里帮助我,向我展示如何使用lapply()获得相同的结果吗?

1 个答案:

答案 0 :(得分:0)

sapply()应该很合适。

evening <- sapply(1:nrow(df1), f_overlap)
> cbind(df1, evening=evening)
                start                 end   evening
1 2018-01-01 10:47:05 2018-01-01 16:36:03 0.6008333
2 2018-01-02 04:05:56 2018-01-02 14:24:59 0.0000000
3 2018-01-02 13:37:41 2018-01-03 00:47:31 5.0000000
4 2018-01-02 22:53:31 2018-01-03 04:43:59 0.0000000
5 2018-01-03 17:04:20 2018-01-03 22:27:39 3.9277778

如果您依赖lapply(),则必须unlist()rbind()输出:

do.call(rbind, lapply(1:nrow(df1), f_overlap))  # rbind, or
unlist(lapply(1:nrow(df1), f_overlap))  # unlist

您也可以在上面的cbind()中使用这两种选择。

我试图重新构造您的f_overlap()函数的作用,这些值至少非常相似。

f_overlap <- function(x) {
  i0 <- as.POSIXct(paste(as.character(as.Date(df1[x,]$start)), "16:00"))
  t0 <- df1[x, ]$start
  t1 <- df1[x, ]$end
  i1 <- as.POSIXct(paste(as.character(as.Date(df1[x,]$start)), "21:00"))
  if (t0 < i0 & t1 < i0) return(0)
  else if (t0 < i0 & t1 > i1) return(5)
  else if (t0 > i1 & t1 > i1) return (0)
  else if (t0 > i0 & t1 < i1) 
    return(difftime(t1, t0, units="hours"))
  else if (t0 < i0 & t1 < i1) 
    return(difftime(t1, i0, units="hours"))
  else if (t0 > i0 & t1 > i1) 
    return(difftime(i1, t0, units="hours"))
}
相关问题