【问题标题】:Replacing conditional values with previous values in r用 r 中的先前值替换条件值
【发布时间】:2019-04-02 17:44:27
【问题描述】:

我有一些关于生物体存活率随时间变化的数据。数据是使用每个时间点的许多复制的平均值构建的,这可以产生一个向前的时间步长,增加存活率。有时,这会导致生存率大于 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 的值。不是最优雅的解决方案,但它确实有效。

【问题讨论】:

  • dfTreatment 是 0 但在 df1Treatment 是 12,怎么办?
  • df 中的哪一列引用了survivorship
  • @Sonny,df1 中的列是整个数据集的子样本。 Generations 范围为 0:25。 Treatment 是第 3 列,范围为 1:4。 Survivorship 是标记为lxlx_diag 的列

标签: r dplyr


【解决方案1】:

这对我来说似乎是一个非常丑陋的解决方案,但我想不出别的:

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的值,但我似乎仍然遇到了用以前的值替换它们的问题。
【解决方案2】:

使用来自@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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-02
    • 2023-01-02
    • 1970-01-01
    • 2018-11-07
    • 2021-10-25
    • 2020-04-24
    • 1970-01-01
    • 2020-10-01
    相关资源
    最近更新 更多