首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如果任何剩余值为0,则将值设置为0

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

Stack Overflow用户
提问于 2020-07-17 18:54:49
回答 4查看 90关注 0票数 3

我有一个这样的data.frame

代码语言:javascript
运行
复制
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

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

我尝试过dat %>% group_by(ID) %>% mutate(value2 = ifelse(lead(value, order_by=time)==0, 0, value)),但我必须运行几次,因为它一次只更改一行(即首先更改第9行,然后更改第8行,依此类推)。

最好使用dplyr解决方案,但我会选择一切可行的解决方案:)

简短解释:价值是肿瘤的大小。如果肿瘤没有增长,但实际上在稍后的时间完全消失,它很可能是一个无关的包膜,因此应编码为“零肿瘤”。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2020-07-17 19:09:19

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

代码语言:javascript
运行
复制
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

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

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

代码语言:javascript
运行
复制
dat %>%
  group_by(ID) %>%
  arrange(ID, time) %>%
  mutate(value = if_else(cumsum(value == 0) < sum(value == 0), 0, value))

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

代码语言:javascript
运行
复制
dat %>%
  group_by(ID) %>%
  arrange(ID, time) %>%
  mutate(value = value * (cumsum(value == 0) >= sum(value == 0)))
票数 5
EN

Stack Overflow用户

发布于 2020-07-17 19:19:00

一种方法是找到0的第一次和最后一次出现的索引,并替换其间的所有内容。

代码语言:javascript
运行
复制
library(dplyr)

dat %>%
  group_by(ID) %>%
  mutate(value = replace(value, between(row_number(), which.max(value == 0), tail(which(value == 0), 1)), 0))

# A tibble: 18 x 3
# Groups:   ID [2]
      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
票数 2
EN

Stack Overflow用户

发布于 2020-07-17 19:59:27

使用data.table,您可以按特定顺序计算包含数据的字段,而无需实际重新排序数据帧。在这里很有用

代码语言:javascript
运行
复制
library(data.table)
setDT(dat)

dat[order(-time), value := fifelse(cumsum(value == 0) > 0, 0, value), ID]

dat
#     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     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
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62952522

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档