在r中使用后续值时创建新变量

时间:2017-12-01 13:55:57

标签: r dplyr mutate

我有以下数据框:

df1 <- data.frame(id = rep(1:3, each = 5), 
                  time = rep(1:5),
                  y = c(rep(1, 4), 0, 1, 0, 1, 1, 0, 0, 1, rep(0,3)))

df1
##    id time y
## 1   1    1 1
## 2   1    2 1
## 3   1    3 1
## 4   1    4 1
## 5   1    5 0
## 6   2    1 1
## 7   2    2 0
## 8   2    3 1
## 9   2    4 1
## 10  2    5 0
## 11  3    1 0
## 12  3    2 1
## 13  3    3 0
## 14  3    4 0
## 15  3    5 0

我想创建一个新的指标变量,告诉我,对于三个ID中的每一个,在所有后续响应的y = 0点。在上面的例子中,对于id 1和2,这发生在第5个时间点,而对于id 3,这发生在第3个时间点。

我在id 2上被绊倒,在时间点2 y = 1,但后来又回到了一个 - 我想指示变量以考虑后续时间点。

基本上,我正在寻找以下输出:

df1
##    id time y new_col
## 1   1    1 1       0
## 2   1    2 1       0
## 3   1    3 1       0
## 4   1    4 1       0
## 5   1    5 0       1
## 6   2    1 1       0
## 7   2    2 0       0
## 8   2    3 1       0
## 9   2    4 1       0
## 10  2    5 0       1
## 11  3    1 0       0
## 12  3    2 1       0
## 13  3    3 0       1
## 14  3    4 0       1
## 15  3    5 0       1

new_col变量指示在该时间点和所有后续时间点y = 0。

2 个答案:

答案 0 :(得分:2)

我会使用一个小辅助函数。

foo <- function(x, val) {
  pos <- max(which(x != val)) +1
  as.integer(seq_along(x) >= pos)
}

df1 %>% 
  group_by(id) %>% 
  mutate(indicator = foo(y, 0))

# # A tibble: 15 x 4
# # Groups:   id [3]
#     id  time     y indicator
#   <int> <int> <dbl>     <int>
# 1     1     1     1         0
# 2     1     2     1         0
# 3     1     3     1         0
# 4     1     4     1         0
# 5     1     5     0         1
# 6     2     1     1         0
# 7     2     2     0         0
# 8     2     3     1         0
# 9     2     4     1         0
# 10     2     5     0         1
# 11     3     1     0         0
# 12     3     2     1         0
# 13     3     3     0         1
# 14     3     4     0         1
# 15     3     5     0         1

如果您想要考虑y中的NA值,可以将foo调整为:

foo <- function(x, val) {
  pos <- max(which(x != val | is.na(x))) +1
  as.integer(seq_along(x) >= pos)
}

这样,如果在最后一个y = 0之后有一个NA,指标将保持为0.

答案 1 :(得分:0)

以下是使用data.table

的选项
library(data.table)
setDT(df1)[,  indicator := cumsum(.I %in% .I[which.max(rleid(y)*!y)]), id]
df1
#    id time y indicator
# 1:  1    1 1         0
# 2:  1    2 1         0
# 3:  1    3 1         0
# 4:  1    4 1         0
# 5:  1    5 0         1
# 6:  2    1 1         0
# 7:  2    2 0         0
# 8:  2    3 1         0
# 9:  2    4 1         0
#10:  2    5 0         1
#11:  3    1 0         0
#12:  3    2 1         0
#13:  3    3 0         1
#14:  3    4 0         1
#15:  3    5 0         1

根据@docendodiscimus的评论,如果每个'id'末尾的'y'值不是0,那么我们可以做

setDT(df1)[, indicator := {
       i1 <- rleid(y) * !y
     if(i1[.N]!= max(i1) & !is.na(i1[.N])) 0L else cumsum(.I %in% .I[which.max(i1)])  }, id]