【问题标题】:Replace NAs in vector (A) with specific values from another vector (B) and force the copied value in vector (B) to NAs将向量 (A) 中的 NA 替换为另一个向量 (B) 中的特定值,并将向量 (B) 中的复制值强制为 NA
【发布时间】:2018-03-29 14:44:17
【问题描述】:

此问题是对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

转换有两个特点 - 从 'score' 列中取最后一个值来替换 'end.s' 列中的 NA 从 'score' 列中替换该值不适用。

我认为我可以使用之前帖子中的语法来替换 NA,但是一旦我看了看并考虑了一秒钟,它就不会那样工作了。

我在想一个 apply 函数是可行的方法,但我什至没有设法通过第一步。

【问题讨论】:

    标签: r for-loop lapply


    【解决方案1】:

    这是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】:

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

      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")   
      

      【讨论】:

        【解决方案3】:

        我相信以下内容可以满足您的要求。

        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
        

        【讨论】:

          猜你喜欢
          • 2020-05-24
          • 1970-01-01
          • 2022-01-26
          • 1970-01-01
          • 1970-01-01
          • 2013-08-06
          • 2021-09-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多