你能使dplyr :: mutate和dplyr :: lag默认=它自己的输入值吗?

The*_*iat 3 r lag dplyr mutate

这类似于这个dplyr滞后帖,这个dplyr变异延迟发布,但是这些都没有问这个关于默认为输入值的问题.我正在使用dplyr来改变一个新字段,该字段是另一个字段的滞后偏移量(我已转换为POSIXct).目标是,对于给定的ip,我想知道一些关于它在我的列表中显示的所有时间之间的增量的汇总统计数据.我也有大约1200万行.

数据看起来像这样(在变异之前)

ip             hour         snap
192.168.1.2    2017070700    0
192.168.1.2    2017070700   15
192.168.1.4    2017070700    0
192.168.1.4    2017070701   45
192.168.1.4    2017070702   30
192.168.1.7    2017070700   15
Run Code Online (Sandbox Code Playgroud)

'hour'是一个整数,但应该是一个时间戳.

'snap'是4个'快照'值之一,代表15分钟的增量.

这是data.frame创建代码:

test <- data.frame(ip=c("192.168.1.2","192.168.1.2","192.168.1.4","192.168.1.4","192.168.1.4","192.168.1.7"), hour=c(2017070700,2017070700,2017070700,2017070701,2017070702,2017070700), snap=c(0,15,0,45,30,15))
Run Code Online (Sandbox Code Playgroud)

每个ip有数百甚至数千个时间戳.下面的代码使用dplyr来

  • a)用前导0填充0',
  • b)将两个整数'date'字段连成一个字段,
  • c)将合并的整数'date'字段转换为POSIX日期,
  • d)通过ip组,
  • e)将一个滞后于旧时间戳的新列变为1,如果该值为NA,则返回原始值(这就是"没有工作的位置"),以及
  • f)改变一个新列,它取当前时间和前一个时间的差值(通过ip).

这些步骤参考每行末尾的注释.

timedelta <- test %>% 
  mutate(snap = formatC(snap, width=2, flag=0)) %>%                      # a) 
  mutate(fulldateint = paste(hour, snap, sep="")) %>%                    # b) 
  mutate(fulldate = as.POSIXct(strptime(fulldateint, "%Y%m%d%H%M"))) %>% # c) 
  group_by(ip) %>%                                                       # d) 
  mutate(shifted = dplyr::lag(fulldate, default=fulldate)) %>%           # e) 
  mutate(diff = fulldate-shifted)                                        # f) 
Run Code Online (Sandbox Code Playgroud)

变异后,数据应如下所示:

           ip       hour  snap  fulldateint            fulldate             shifted      diff
       <fctr>      <dbl> <chr>        <chr>              <dttm>              <dttm>    <time>
1 192.168.1.2 2017070700    00 201707070000 2017-07-07 00:00:00 2017-07-07 00:00:00    0 secs
2 192.168.1.2 2017070700    15 201707070015 2017-07-07 00:15:00 2017-07-07 00:00:00  900 secs
3 192.168.1.4 2017070700    00 201707070000 2017-07-07 00:00:00 2017-07-07 00:00:00    0 secs
4 192.168.1.4 2017070701    45 201707070145 2017-07-07 01:45:00 2017-07-07 00:00:00 6300 secs
5 192.168.1.4 2017070702    30 201707070230 2017-07-07 02:30:00 2017-07-07 01:45:00 2700 secs
6 192.168.1.7 2017070700    15 201707070015 2017-07-07 00:15:00 2017-07-07 00:15:00    0 secs
Run Code Online (Sandbox Code Playgroud)

如果我可以使滞后默认为其原始值,那么当'delta-T'没有先前的值(这是期望的结果)时,它将始终为0.

但是,dplyr::lag(fulldate, default=fulldate)抛出错误

Error in mutate_impl(.data, dots) : 
Column `shifted` must be length 2 (the group size) or one, not 3
Run Code Online (Sandbox Code Playgroud)

如果我使用fulldate 1它确实有效,但后来我失去了group_by(ip)结果,这是必要的.是否有可能在dplyr中使滞后引用自己的输入?

注意:我真的更喜欢使用dplyr而不是data.table的答案,如果可能的话,因为我一直使用dplyr作为我们的主要数据调整库,但是因为我想建议Wickham先生他接受这个如果它在现有的dplyr库中确实没有解决方案正在考虑中.

Fra*_*ank 6

在OP的代码中......

...
d) group_by(ip) %>%
e) mutate(shifted = dplyr::lag(fulldate, default=fulldate)) %>%
...
Run Code Online (Sandbox Code Playgroud)

default=参数应该有一个的长度.替换OP的代码default = first(fulldate)应该适用于这种情况(因为第一个元素不会有滞后,所以我们需要应用默认值).

相关案例:

  • 同样,有了"领先",我们也想要dplyr::lead(x, default=last(x)).
  • 随着滞后或一个以上的步骤(铅n大于1),default=不能做到这一点,我们可能会需要切换到if_elsecase_when或相似.(我不确定当前的整齐成语.)