代码之家  ›  专栏  ›  技术社区  ›  Thomas Speidel

如果在dplyr管道中有日期

  •  -2
  • Thomas Speidel  · 技术社区  · 6 年前

    假设我有这些数据:

    df <- structure(list(end = structure(c(2932896, 2932896, 17434, 2932896, 
    2932896, 2932896), class = "Date"), start = structure(c(15397, 
    16847, 14249, 13801, 12101, 13360), class = "Date")), class = "data.frame", row.names = c(NA, 
    -6L))
    
    > df
             end      start
    1 9999-12-31 2012-02-27
    2 9999-12-31 2016-02-16
    3 2017-09-25 2009-01-05
    4 9999-12-31 2007-10-15
    5 9999-12-31 2003-02-18
    6 9999-12-31 2006-07-31
    

    我想创建第三个变量, dur ,以某个语句为条件:

    library(dplyr)
    library(lubridate)
    
    df %>%
      mutate(dur = if_else(end == "9999-12-31",
                           as.duration(today() - max("2012-01-01", start)),
                           as.duration(max(start, "2012-01-01") - end)
                           )
             )
    

    Error in mutate_impl(.data, dots) : 
      Evaluation error: non-numeric argument to binary operator.
    

    我知道一些建议 DT ifelse 有约会,但我想呆在房间里。


    更新1

    这里是专栏 表示预期输出:

    | end           | start         | dur                       | code                                              |
    |------------   |------------   |-------------------------- |-------------------------------------------------- |
    | 9999-12-31    | 2012-02-27    | 207100800s (~6.56 years)  | as.duration(today()-ymd("2012-02-27"))            |
    | 9999-12-31    | 2016-02-16    | 81820800s (~2.59 years)   | as.duration(today()-ymd("2016-02-16"))            |
    | 2017-09-25    | 2009-01-05    | 180921600s (~5.73 years)  | as.duration(ymd("2017-09-25")-ymd("2012-01-01"))  |
    | 9999-12-31    | 2007-10-15    | 212025600s (~6.72 years)  | as.duration(today()-ymd("2012-01-01"))            |
    | 9999-12-31    | 2003-02-18    | 212025600s (~6.72 years)  | as.duration(today()-ymd("2012-01-01"))            |
    | 9999-12-31    | 2006-07-31    | 212025600s (~6.72 years)  | as.duration(today()-ymd("2012-01-01"))            |
    

    更新2

    df %>%
      mutate(dur = if_else(end == ymd("9999-12-31"),
                           as.duration(today() - max(ymd("2012-01-01"), start)),
                           as.duration(max(start, ymd("2012-01-01")) - end)
                           )
             )
    

    生产:

             end      start                     dur
    1 9999-12-31 2012-02-27 81820800s (~2.59 years)
    2 9999-12-31 2016-02-16 81820800s (~2.59 years)
    3 2017-09-25 2009-01-05 50716800s (~1.61 years)
    4 9999-12-31 2007-10-15 81820800s (~2.59 years)
    5 9999-12-31 2003-02-18 81820800s (~2.59 years)
    6 9999-12-31 2006-07-31 81820800s (~2.59 years)
    


    更新3(已解决!)

    感谢 @jdobres pmax 而不是 max . 我想不出原因,但文件上说: pmax和pmin还将使用适当的比较方法来处理分类的S3或S4对象,is.na和rep(如果需要循环使用参数) . 我怀疑这与此有关。

    df %>%
      mutate(dur = if_else(end == ymd("9999-12-31"),
                           as.duration(today() - pmax(ymd("2012-01-01"), start)),
                           as.duration(pmax(start, ymd("2012-01-01")) - end)
                           )
             )
    

             end      start                      dur
    1 9999-12-31 2012-02-27 207100800s (~6.56 years)
    2 9999-12-31 2016-02-16  81820800s (~2.59 years)
    3 2017-09-25 2009-01-05 180921600s (~5.73 years)
    4 9999-12-31 2007-10-15 212025600s (~6.72 years)
    5 9999-12-31 2003-02-18 212025600s (~6.72 years)
    6 9999-12-31 2006-07-31 212025600s (~6.72 years)
    
    2 回复  |  直到 4 年前
        1
  •  2
  •   jdobres    6 年前

    ymd as.Date pmax 以获得两个持续时间中的较大值。 提供具有相同元素数的向量间的并行最大值。例如:

     pmax(1:10, rep(5, 10))
    
     [1]  5  5  5  5  5  6  7  8  9 10
    

    df %>%
      mutate(dur = if_else(end == ymd("9999-12-31"),
                           as.duration(today() - pmax(ymd("2012-01-01"), start)),
                           as.duration(pmax(start, ymd("2012-01-01")) - end)
                           )
                        )
    
        2
  •  1
  •   Paul    6 年前

    我试着做一个变异,就像你做的,在使用 lubridate::ymd() 在你输入的字符日期上,但是 max() 不是逐行比较,而是抓住了所有起始值的最大值——也许有人能解释为什么?

    最后我和阿普去了。

    library(dplyr)
    library(lubridate)
    
    df %>%
      mutate(dur =
               apply(tbl_df(df), 1, function(x){
                 print(x)
    
                 ifelse(
                   x["end"] == ymd("9999-12-31"),
    
                   interval(today(), max(ymd("2012-01-01"), ymd(x["start"]))) %>%
                     as.duration() %>%
                     as.numeric("years"),
    
                   interval(max(x["start"], ymd("2012-01-01")), ymd(x["end"])) %>%
                     as.duration() %>%
                     as.numeric("years")
                 )
    
               }))
    
    #          end      start       dur
    # 1 9999-12-31 2012-02-27 -6.562628
    # 2 9999-12-31 2016-02-16 -2.592745
    # 3 2017-09-25 2009-01-05  8.720055
    # 4 9999-12-31 2007-10-15 -6.718686
    # 5 9999-12-31 2003-02-18 -6.718686
    # 6 9999-12-31 2006-07-31 -6.718686
    

    ymd() 再次在函数中。我以前就注意到了,我不知道为什么。