将向量(A)中的NA替换为来自另一个向量(B)的特定值,并将向量(B)中的复制值强制转换为NAs

时间:2017-10-17 19:49:28

标签: r for-loop lapply

此问题是thisthis答案的延伸 这是一个例子df:

      name score end.s time
    1    a    1    NA   1 
    2    a    2    NA   2
    3    a    3    NA   3
    4    b    4    4    1
    5    b    5    4    2
    6    b    6    4    3
    7    c    7    NA   1
    8    c    8    NA   2
    9    d    6    6    1
   10    d    7    6    3

我想要的输出:

      name score end.s time
    1    a    1    3    1 
    2    a    2    3    2
    3    a    NA   3    3
    4    b    4    4    1
    5    b    5    4    2
    6    b    6    4    3
    7    c    7    8    1
    8    c    NA   8    2
    9    d    6    6    1
   10    d    7    6    3

转换有两个功能 - 从'得分'列中取最后一个值来替换'end.s'列中的NA 从'score'列替换该值与NA。

我认为我可以使用之前帖子中的语法来替换NA,但是一旦我看了一遍并想了一下它就不会那样了。

我在考虑应用函数是可行的方法,但我还是没有成功地完成第一步。

3 个答案:

答案 0 :(得分:2)

你想要的是有点复杂,答案也是如此:

library(dplyr)
df %>% group_by(name) %>% mutate(help=last(score)) %>% 
   mutate(score = ifelse(is.na(end.s), c(score[-n()], NA), score)) %>% 
   mutate_at(vars(end.s), funs(ifelse(is.na(.), help, .))) %>% select(-help)

## # A tibble: 10 x 4
## # Groups:   name [4]
##      name score end.s  time
##    <fctr> <int> <int> <int>
##  1      a     1     3     1
##  2      a     2     3     2
##  3      a    NA     3     3
##  4      b     4     4     1
##  5      b     5     4     2
##  6      b     6     4     3
##  7      c     7     8     1
##  8      c    NA     8     2
##  9      d     6     6     1
## 10      d     7     6     3

<强> 数据:

 df <- structure(list(name = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L,      
     3L, 4L, 4L), .Label = c("a", "b", "c", "d"), class = "factor"),      
         score = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 6L, 7L), end.s = c(NA, 
         NA, NA, 4L, 4L, 4L, NA, NA, 6L, 6L), time = c(1L, 2L, 3L,        
         1L, 2L, 3L, 1L, 2L, 1L, 3L)), .Names = c("name", "score",        
     "end.s", "time"), row.names = c("1", "2", "3", "4", "5", "6",        
     "7", "8", "9", "10"), class = "data.frame")   

答案 1 :(得分:2)

以下是data.table

的另一个选项
library(data.table)
i1 <- setDT(df)[is.na(end.s), .I[.N], name]$V1
df[is.na(end.s),  end.s := score[.N], name][i1, score := NA][]
#     name score end.s time
# 1:    a     1     3    1
# 2:    a     2     3    2
# 3:    a    NA     3    3
# 4:    b     4     4    1
# 5:    b     5     4    2
# 6:    b     6     4    3
# 7:    c     7     8    1
# 8:    c    NA     8    2
# 9:    d     6     6    1
#10:    d     7     6    3

答案 2 :(得分:1)

我相信以下是你想要的。

test <- do.call(rbind, lapply(split(test, test$name), function(x){
    i <- is.na(x$end.s)
    x$end.s[i] <- x$score[nrow(x)]
    if(any(i)) x$score[nrow(x)] <- NA
    x
}))
row.names(test) <- NULL
test