首页 文章

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

提问于
浏览
3

这类似于this dplyr lag postthis dplyr mutate lag post,但这些都没有提出关于默认为输入值的问题 . 我正在使用dplyr来改变_325927已经转换为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

'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))

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

  • a)用前导0填充0',

  • b)将两个整数'date'字段连成一个字段,

  • c)将合并的整数'date'字段转换为POSIX日期,

  • d)按组划分,

  • 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)

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

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

如果我可以使滞后默认为其原始值,那么当'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

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

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

3 回答

  • 5

    我认为_325946的解决方案非常有效 . 这是完整的例子:

    library(dplyr, warn.conflicts = F)
    
    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))
    
    
    test %>%
      mutate(snap = formatC(snap, width = 2, flag = 0)) %>%
      mutate(fulldateint = paste(hour, snap, sep = "")) %>%
      mutate(fulldate = as.POSIXct(strptime(fulldateint, "%Y%m%d%H%M"))) %>%
      group_by(ip) %>%
      mutate(shifted = lag(fulldate, default = first(fulldate))) %>%
      mutate(diff = fulldate - shifted) %>% 
      ungroup() %>% 
      select(ip, fulldate, shifted, diff)
    
    #> # A tibble: 6 x 4
    #>            ip            fulldate             shifted      diff
    #>        <fctr>              <dttm>              <dttm>    <time>
    #> 1 192.168.1.2 2017-07-07 00:00:00 2017-07-07 00:00:00    0 secs
    #> 2 192.168.1.2 2017-07-07 00:15:00 2017-07-07 00:00:00  900 secs
    #> 3 192.168.1.4 2017-07-07 00:00:00 2017-07-07 00:00:00    0 secs
    #> 4 192.168.1.4 2017-07-07 01:45:00 2017-07-07 00:00:00 6300 secs
    #> 5 192.168.1.4 2017-07-07 02:30:00 2017-07-07 01:45:00 2700 secs
    #> 6 192.168.1.7 2017-07-07 00:15:00 2017-07-07 00:15:00    0 secs
    
  • 0

    怎么样

    ifelse(is.na(lag(value)), value, lag(value))
    
  • 3

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

    ......
    d)group_by(ip)%>%
    e)mutate(shifted = dplyr :: lag(fulldate,default = fulldate))%>%
    ...

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

    相关案例:

    • 同样,对于"lead",我们需要 dplyr::lead(x, default=last(x)) .

    • 如果滞后或超过一步( n 大于1),则 default= 无法执行此操作,我们可能需要切换到 if_elsecase_when 或类似步骤 . (我不确定目前整齐的成语 . )

相关问题