如果任何剩余值为 0,则将值设置为 0

Luc*_*Pal 3 r dataframe dplyr

我有一个data.frame这样的:

dat <- data.frame("ID"=c(rep(1,13),rep(2,5)), "time"=c(seq(1,13),c(seq(1,5))), "value"=c(rep(0,5), rep(1,3), 2, 0, 1, 5, 20, rep(0,2), seq(1:3)))
   ID time value
1   1    1     0
2   1    2     0
3   1    3     0
4   1    4     0
5   1    5     0
6   1    6     1
7   1    7     1
8   1    8     1
9   1    9     2
10  1   10     0
11  1   11     1
12  1   12     5
13  1   13    20
14  2    1     0
15  2    2     0
16  2    3     1
17  2    4     2
18  2    5     3
Run Code Online (Sandbox Code Playgroud)

我的目标是将所有值设置为0,如果在剩余值中还有其他值0(对于每个唯一值ID并按 排序time)。这意味着在示例数据中,我希望0在 6:9 行中。

我试过了,dat %>% group_by(ID) %>% mutate(value2 = ifelse(lead(value, order_by=time)==0, 0, value))但我必须多次运行它,因为它一次只更改一行(即第 9 行,然后是第 8 行,等等)。

dplyr 解决方案将是首选,但我会采取一切有效的方法:)

简短说明:值是肿瘤的大小。如果肿瘤没有变大,但后来实际上完全消失了,那很可能是一个无关的包裹,因此应编码为“零肿瘤”。

Cet*_*ttt 5

我不确定这是否是您想要的输出,但也许它对您有用

dat %>%
  group_by(ID) %>%
  arrange(-time) %>%
  mutate(value = if_else(cumsum(value == 0) > 0, 0, value)) %>%
  arrange(ID, time)

     ID  time value
   <dbl> <int> <dbl>
 1     1     1     0
 2     1     2     0
 3     1     3     0
 4     1     4     0
 5     1     5     0
 6     1     6     0
 7     1     7     0
 8     1     8     0
 9     1     9     0
10     1    10     0
11     1    11     1
12     1    12     5
13     1    13    20
14     2     1     0
15     2     2     0
16     2     3     1
17     2     4     2
18     2     5     3
Run Code Online (Sandbox Code Playgroud)

基本上,我首先将观察结果按降序排列。然后我检查值 ( cumsum(value == 0) > 0)) 中是否存在零。如果是,我将所有剩余值设置为零。最后,我再次将观察结果按正确顺序排列。

如果您不想对数据进行排序和重新排序,可以使用以下代码,该代码依赖于相同的逻辑但更难阅读:

dat %>%
  group_by(ID) %>%
  arrange(ID, time) %>%
  mutate(value = if_else(cumsum(value == 0) < sum(value == 0), 0, value))
Run Code Online (Sandbox Code Playgroud)

或者在没有的情况下效率更高if_else

dat %>%
  group_by(ID) %>%
  arrange(ID, time) %>%
  mutate(value = value * (cumsum(value == 0) >= sum(value == 0)))
Run Code Online (Sandbox Code Playgroud)