用r中的先前值替换条件值

时间:2019-04-02 17:44:28

标签: r dplyr

我有一些关于生物存活率随时间变化的数据。数据是使用每个时间点许多重复样本的平均值构建的,这可以产生一个向前的时间步,并提高生存率。有时,这会导致生存率大于1,这是不可能的。如何在同一列中有条件地将大于1的值更改为之前的值?

数据如下:

>df
 Generation Treatment  time    lx
 1 0                  1     0 1    
 2 0                  1     2 1    
 3 0                  1     4 0.970
 4 0                  1     6 0.952
 5 0                  1     8 0.924
 6 0                  1    10 0.913
 7 0                  1    12 0.895
 8 0                  1    14 0.729
 9 0                  2     0 1    
10 0                  2     2 1   

我已经尝试过对感兴趣的列进行这样的突变,它仍然会产生高于1的值:

df1 <- df %>%
  group_by(Generation, Treatment) %>%
  mutate(lx_diag = as.numeric(lx/lag(lx, default = first(lx)))) %>% #calculate running survival
  mutate(lx_diag = if_else(lx_diag > 1.000000, lag(lx_diag), lx_diag)) #substitute values >1 with previous value

>df1
Generation Treatment  time    lx lx_diag
 1 12                 1     0 1       1    
 2 12                 1     2 1       1    
 3 12                 1     4 1       1    
 4 12                 1     6 0.996   0.996
 5 12                 1     8 0.988   0.992
 6 12                 1    10 0.956   0.968
 7 12                 1    12 0.884   0.925
 8 12                 1    14 0.72    0.814
 9 12                 1    15 0.729   1.01 
10 12                 1    19 0.76    1.04 

我希望结果看起来像这样:

>df1
Generation Treatment  time    lx lx_diag
 1 12                 1     0 1       1    
 2 12                 1     2 1       1    
 3 12                 1     4 1       1    
 4 12                 1     6 0.996   0.996
 5 12                 1     8 0.988   0.992
 6 12                 1    10 0.956   0.968
 7 12                 1    12 0.884   0.925
 8 12                 1    14 0.72    0.814
 9 12                 1    15 0.729   0.814 
10 12                 1    19 0.76    0.814

我知道您可以有条件地将值更改为特定值(即ifelse with no else),但是我没有找到任何可以有条件地将一列中的值更改为上一行中的值的解决方案。任何帮助表示赞赏。

编辑:我意识到,mutateif_else在转换值时非常有效。这些命令不是像我期望的那样从头到尾依次替换值,而是同时替换所有值。因此,在一系列> 1的值中,您将剩下一些。因此,如果您只运行命令:

SurvTot1$lx_diag <- if_else(SurvTot1$lx_diag > 1, lag(SurvTot1$lx_diag), SurvTot1$lx_diag)
再次

,您可以删除值> 1。不是最优雅的解决方案,但它可以工作。

2 个答案:

答案 0 :(得分:0)

这对我来说似乎是一个非常丑陋的解决方案,但是我什么也没想到:

df = data.frame(
  "Generation" = rep(12,10),
  "Treatent" = rep(1,10),
  "Time" = c(seq(0,14,by=2),15,19),
  "lx_diag" = c(1,1,1,0.996,0.992,0.968,0.925,0.814,1.04,1.04)
)


update_lag = function(x){
  k <<- k+1
  x
}

k=1

df  %>% 
  mutate(
    lx_diag2 = ifelse(lx_diag <=1,update_lag(lx_diag),lag(lx_diag,n=k))
  )

答案 1 :(得分:0)

使用@Fino的数据,这是我使用基数R的矢量化解决方案

vals.to.replace <- which(df$lx_diag > 1)
vals.to.substitute <- sapply(vals.to.replace, function(x) tail( df$lx_diag[which(df$lx_diag[1:x] <= 1)], 1) )
df$lx_diag[vals.to.replace] = vals.to.substitute
df

   Generation Treatent Time lx_diag
1          12        1    0   1.000
2          12        1    2   1.000
3          12        1    4   1.000
4          12        1    6   0.996
5          12        1    8   0.992
6          12        1   10   0.968
7          12        1   12   0.925
8          12        1   14   0.814
9          12        1   15   0.814
10         12        1   19   0.814