首页 文章

按组计算相对于基线的时间序列的相对变化 . 如果没有测量基线值,则为NA

提问于
浏览
1

我想用dplyr计算data.frame中测量变量的相对变化 . 这些变化是关于时间== 0的第一个基线值 .

我可以在以下示例中轻松完成此操作:

# with this easy example it works 
 df.easy <- data.frame( id  =c(1,1,1,2,2,2)
                   ,time=c(0,1,2,0,1,2)
                   ,meas=c(5,6,9,4,5,6))

 df.easy %>% dplyr::group_by(id) %>% dplyr::mutate(meas.relative =
 meas/meas[time==0])
     # Source: local data frame [6 x 4]
     # Groups: id [2]
     # 
     #      id  time  meas meas.relative
     #   <dbl> <dbl> <dbl>         <dbl>
     # 1     1     0     5          1.00
     # 2     1     1     6          1.20
     # 3     1     2     9          1.80
     # 4     2     0     4          1.00
     # 5     2     1     5          1.25
     # 6     2     2     6          1.50

但是,当有id 's with no measuremnt at time==0, this doesn' t工作时 . 一个类似的问题是this,但我想得到一个NA而不是简单地将第一次出现作为基线 .

# how to output NA in case there are id's with no measurement at time==0?
 df <- data.frame( id  =c(1,1,1,2,2,2,3,3)
                  ,time=c(0,1,2,0,1,2,1,2)
                  ,meas=c(5,6,9,4,5,6,5,6))

 # same approach now gives an error:
     df %>% dplyr::group_by(id) %>% dplyr::mutate(meas.relative = meas/meas[time==0])
     # Error in mutate_impl(.data, dots) : 
     #   incompatible size (0), expecting 2 (the group size) or 1

让我们尝试返回NA,以防在没有测量时= = 0,使用 ifelse

df %>% dplyr::group_by(id) %>% dplyr::mutate(meas.relative = ifelse(any(time==0), meas/meas[time==0], NA) )
     # Source: local data frame [8 x 4]
     # Groups: id [3]
     # 
     #      id  time  meas meas.relative
     #   <dbl> <dbl> <dbl>         <dbl>
     # 1     1     0     5             1
     # 2     1     1     6             1
     # 3     1     2     9             1
     # 4     2     0     4             1
     # 5     2     1     5             1
     # 6     2     2     6             1
     # 7     3     1     5            NA
     # 8     3     2     6            NA>

等等,为什么高于相对测量1?

identical(
    df %>% dplyr::group_by(id) %>% dplyr::mutate(meas.relative = ifelse(any(time==0), meas, NA) ),
    df %>% dplyr::group_by(id) %>% dplyr::mutate(meas.relative = ifelse(any(time==0), meas[time==0], NA) )
    )
    # TRUE

似乎ifelse阻止meas选择当前行,但总是选择时间== 0的子集 .

当有没有基线测量的ID时,如何计算相对变化?

1 回答

  • 1

    您的问题出现在 ifelse() 中 . 根据 ifelse 文档,它返回“相同长度的矢量...作为测试” . 由于 any(time==0) 对于每个组( TRUEFALSE )的长度为1,因此仅选择了 meas / meas[time==0] 的第一次观察 . 然后重复这个以填充每个组 .

    为了解决这个问题,我所做的只是 rep any() 是该组的长度 . 我相信这应该有效:

    df %>% dplyr::group_by(id) %>% 
           dplyr::mutate(meas.relative = ifelse(rep(any(time==0),times = n()), meas/meas[time==0], NA) )
    
      #       id  time  meas meas.relative
      #    <dbl> <dbl> <dbl>         <dbl>
      #  1     1     0     5          1.00
      #  2     1     1     6          1.20
      #  3     1     2     9          1.80
      #  4     2     0     4          1.00
      #  5     2     1     5          1.25
      #  6     2     2     6          1.50
      #  7     3     1     5            NA
      #  8     3     2     6            NA
    

    要查看在您的案例中这是如何工作不正常尝试:

    ifelse(TRUE,c(1,2,3),NA)
    #[1] 1
    

    Edit: 具有相同概念的 data.table 解决方案:

    as.data.table(df)[, meas.rel := ifelse(rep(any(time==0), .N), meas/meas[time==0], NA_real_)
                      ,by=id]
    

相关问题