dplyr 延迟将向量而不是单个值传递给调用的函数

dplyr lag passing vector instead of single value to invoked function

我有这样一个数据框:

> df
  threadId          threadTime
1        1 2014-07-08 18:28:29
2        1 2014-07-08 18:46:09
3        2 2014-07-10 10:14:42
4        2 2014-07-10 10:30:49
5        3 2014-07-10 11:19:27
6        3 2014-07-10 11:45:23
> str(df)
'data.frame':   6 obs. of  2 variables:
 $ threadId  : num  1 1 2 2 3 3
 $ threadTime: POSIXct, format: "2014-07-08 18:28:29" "2014-07-08 18:46:09" ...

我正在使用一个简单的函数调用(这个函数做什么并不重要):

someFunc <- function(t1, t2) { cat(t1); cat('\n'); return(1)}

当我如下调用函数来改变数据框上的新列时,我看到调用该函数时使用了 threadTime 值的向量,而不是独立的滞后行和当前行的值。我错过了什么?

df %>% group_by(threadId) %>% mutate(blah = someFunc(lag(threadTime), threadTime))

我原以为 t1 是滞后行中的时间,t2 是当前行中的时间。当然,该组的第一行将有 NA 作为滞后值,我很好,可以在我的函数中检查它。

'three groups in the df' 函数调用的输出仅针对 t1 参数如下。使用 'lag(threadTime)' 和 'threadTime'.

的串联值调用该函数
t1 = NA 1404858509
t1 = NA 1405001682
t1 = NA 1405005567

更新

事实证明,我的功能 does/needs 完全重要。更新问题。我想计算滞后行时间值之间的工作日和小时数。所以,我使用的函数如下(onDays 是工作日,扣除周末+假期,onHours 是工作时间):

workingHours <- function(t1, t2) {
  elapsedTime <- seq.POSIXt(from = t1, to = t2, by = 'hour')
  elapsedTime <- elapsedTime[as.Date(elapsedTime) %in% onDays &
                               as.numeric(format(elapsedTime, '%H')) %in%
                               onHours]
  return(length(elapsedTime))
}

在这种情况下,seq.POSIXt 不会为 'from' 和 'to' 采用向量,因此我不能使用向量化的 lag() 值。有没有比 'looping' 或使用某种 apply() 调用更好的替代方法,它可能只是比循环略有改进?

评论太长了,所以我发帖作为回答...

您的一般 lag() 语法应该有效。我会检查您是否没有发生屏蔽问题,其他几个软件包提供了 lag 与 dplyr 不同的功能。您可以始终明确并调用 dplyr::lag 来确定。

这里有一些关于内置数据的代码,可以证明您的基本想法应该可行:

mtcars %>% 
  arrange(cyl, mpg) %>%
  group_by(cyl) %>%
  mutate(mpgmpg = paste(lag(mpg), mpg, sep = "!"))

# Source: local data frame [32 x 12]
# Groups: cyl
#
#     mpg cyl  disp  hp drat    wt  qsec vs am gear carb    mpgmpg
# 1  21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2   NA!21.4
# 2  21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1 21.4!21.5
# 3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 21.5!22.8
# 4  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2 22.8!22.8
# 5  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2 22.8!24.4
# 6  26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2   24.4!26

同样,使用您的函数的修改版本:

someFunc <- function(t1, t2) { cat(t1); cat("\n"); cat(t2); cat('\n\n'); return(1)}

这是我所期望的,也是我得到的:

mtcars %>% arrange(cyl, mpg) %>% group_by(cyl) %>%
  mutate(mpgmpg = someFunc(lag(mpg), mpg))
# NA 21.4 21.5 22.8 22.8 24.4 26 27.3 30.4 30.4 32.4
# 21.4 21.5 22.8 22.8 24.4 26 27.3 30.4 30.4 32.4 33.9

# NA 17.8 18.1 19.2 19.7 21 21
# 17.8 18.1 19.2 19.7 21 21 21.4

# NA 10.4 10.4 13.3 14.3 14.7 15 15.2 15.2 15.5 15.8 16.4 17.3 18.7
# 10.4 10.4 13.3 14.3 14.7 15 15.2 15.2 15.5 15.8 16.4 17.3 18.7 19.2
# ...

这是因为lag被向量化了,someFunc被向量化了,这是好事!它似乎符合您的描述:

I was expecting t1 to be time in the lagged row, and t2 to be the time in the current row

您可以看到滞后值(顶行)如何与当前值(底行)配对。

如果这不是您想要的,请编辑您的问题以显示期望的行为,最好是在内置数据集或 dput()或模拟数据。