如果先前值在单独列上的最大可能值,则将后续值替换为NA

时间:2017-01-28 22:58:10

标签: r dplyr

我有数据集,其中每行代表个人进行的新测试。它有四个变量。

1)考生的ID:

id <- c(1, 1, 1, 2, 2)

2)个人参加考试的日期:

dates <- as.Date(c("2007-06-22", "2008-06-21", "2009-06-22", "2008-06-21", "2009-06-22"))

3)他们在测试中收到的分数:

scores <- c(0, 12, 12, 1, 3)

4)在该时间点之前,该得分是否是个人的最佳得分。

improvement <- c("No", "Yes", "No", "No", "Yes")

所以数据集是:

df <- data.frame(id, dates, scores, improvement) 

  id      dates scores improvement
1  1 2007-06-22      0          No
2  1 2008-06-21     12         Yes
3  1 2009-06-22     12          No
4  2 2008-06-21      1          No
5  2 2009-06-22      3         Yes

我遇到了一个问题。得分为12是最高的。因此,如果有人获得12分,就没有更多的改进空间了。你知道我怎么能做到这一点,当有人得到一个12,在任何后续的行上他们得到NA改善?

即,

   id      dates scores improvement
 1  1 2007-06-22      0          No
 2  1 2008-06-21     12         Yes
 3  1 2009-06-22     12          NA
 4  2 2008-06-21      1          No
 5  2 2009-06-22      3         Yes

3 个答案:

答案 0 :(得分:3)

如何做到这一点:我们使用dplyrid进行分组,然后对每个id我们检查是否有任何分数等于12.如果是,那么我们将替换每个值在第一个得分为12的实例之后的后续行中improvement NA

library(dplyr)

df %>% group_by(id) %>% arrange(id, dates) %>%
  mutate(improvement = replace(improvement, if(any(scores==12)) (min(which(scores==12))+1):n(), NA))
     id      dates scores improvement
  <dbl>     <date>  <dbl>      <fctr>
1     1 2007-06-22      0          No
2     1 2008-06-21     12         Yes
3     1 2009-06-22     12          NA
4     2 2008-06-21      1          No
5     2 2009-06-22      3         Yes

答案 1 :(得分:1)

也可以使用基础包完成操作。虽然它有点乱,但它为那些不熟悉parser.add_argument('--read', dest='book', help='book to read') parser.add_argument('page', nargs='?', default=1, type=int, help='page number') 包等的人创造了机会。这是代码,我在代码中解释了我的逻辑:

dplyr

答案 2 :(得分:1)

以下是使用data.table的选项。我们转换了&#39; data.frame&#39;到&#39; data.table&#39; (setDT(df)),按&#39; id&#39;,order分组&#39; id&#39;和&#39;日期&#39;,获取最高分数的逻辑索引(scores == max(scores)),找到累积总和(cumsum(...)),将其转换为逻辑vector({{ 1}})并获取行索引(>1)。在.I中指定行索引,并在&#39;改进&#39;中分配(i)元素。对应于:=

的索引
NA

更新

如果最大值不相邻,我们可以library(data.table) setDT(df)[df[order(id, dates), .I[cumsum(scores == max(scores))>1], by = id]$V1, improvement := NA] df # id dates scores improvement #1: 1 2007-06-22 0 No #2: 1 2008-06-21 12 Yes #3: 1 2009-06-22 12 NA #4: 2 2008-06-21 1 No #5: 2 2009-06-22 3 Yes 得分&#39;以及其他选择

order

对上述内容的略微改进是通过创建对象

来调用setDT(df1)[df1[order(id, dates), .I[cumsum(scores == max(scores))>1 & scores ==max(scores)], by = id]$V1, improvement := NA] df1 # id dates scores improvement #1: 1 2007-06-22 0 No #2: 1 2008-06-21 12 Yes #3: 1 2009-06-22 5 No #4: 1 2010-06-21 12 NA #5: 2 2008-06-21 1 No #6: 2 2009-06-22 3 Yes 一次
scores==max(scores)

数据

setDT(df1)[df1[order(id, dates), {mx <- scores == max(scores)
                              .I[cumsum(mx)>1 & mx]},  
                      by = id]$V1, improvement := NA]