代码之家  ›  专栏  ›  技术社区  ›  melbez

有条件地将mutate_应用于r中数据帧中的特定行

  •  1
  • melbez  · 技术社区  · 6 年前

    我在R中有一个数据帧,如下所示:

    a  b  c  condition
    1  4  2  acap
    2  3  1  acap
    2  4  3  acap
    5  6  8  ncap
    5  7  6  ncap
    8  7  6  ncap
    

    我试图重新编码条件ncap(以及其他2个条件,这里没有描述)的A、B和C列中的值,同时只保留acap的值。

    以下代码适用于前3列。我正试图弄明白,如何在保持所有内容在同一个数据帧中的同时,只将它应用于按条件指定的行。

    df = df %>%
         mutate_at(vars(a:c), function(x) 
         case_when x == 5 ~ 1, x == 6 ~ 2, x == 7 ~ 3, x == 8 ~ 4)
    

    这是预期的输出。

    a  b  c  condition
    1  4  2  acap
    2  3  1  acap
    2  4  3  acap
    1  2  4  ncap
    1  3  2  ncap
    4  3  2  ncap
    

    我四处寻找这个问题的答案,但找不到答案。如果有人知道一个已经存在的答案,我会很高兴被引导到它。

    2 回复  |  直到 6 年前
        1
  •  2
  •   akrun    6 年前

    case_when 条件是 row_number 即,如果行数为4到6,则从值中减去4,否则返回值。

    df %>% 
       mutate_at(vars(a:c), funs(case_when(row_number() %in% 4:6 ~ . - 4L, 
                                           TRUE ~ .)))
    #  a b c condition
    #1 1 4 2      acap
    #2 2 3 1      acap
    #3 2 4 3      acap
    #4 1 2 4      ncap
    #5 1 3 2      ncap
    #6 4 3 2      ncap
    

    如果这是基于值而不是行,请在值上创建条件

    df %>% 
       mutate_at(vars(a:c), funs(case_when(. %in% 5:8 ~ . - 4L, 
                                           TRUE ~ .)))
    #  a b c condition
    #1 1 4 2      acap
    #2 2 3 1      acap
    #3 2 4 3      acap
    #4 1 2 4      ncap
    #5 1 3 2      ncap
    #6 4 3 2      ncap
    

    或者如果它基于“条件”中的值

    df %>% 
       mutate_at(vars(a:c), funs(case_when(condition == 'ncap' ~ . - 4L, 
                                           TRUE ~ .)))
    

    或者不使用 酪蛋白

    df %>% 
      mutate_at(vars(a:c), funs( . - c(0, 4)[(condition == 'ncap')+1]))
    #  a b c condition
    #1 1 4 2      acap
    #2 2 3 1      acap
    #3 2 4 3      acap
    #4 1 2 4      ncap
    #5 1 3 2      ncap
    #6 4 3 2      ncap
    

    base R ,我们可以通过创建索引来完成此操作。

    i1 <- df$condition =='ncap'
    df[i1, 1:3] <- df[i1, 1:3] - 4
    

    数据

    df <- structure(list(a = c(1L, 2L, 2L, 5L, 5L, 8L), b = c(4L, 3L, 4L, 
     6L, 7L, 7L), c = c(2L, 1L, 3L, 8L, 6L, 6L), condition = c("acap", 
     "acap", "acap", "ncap", "ncap", "ncap")), class = "data.frame", 
     row.names = c(NA, -6L))
    
        2
  •  2
  •   Ronak Shah    6 年前

    你可以使用 filter 仅对特定行应用重编码值(此处不等于“acap”)。

    library(dplyr)
    df %>%
      filter(condition != "acap") %>%
      mutate_at(vars(a:c), function(x) 
      case_when(x == 5 ~ 1, x == 6 ~ 2, x == 7 ~ 3, x == 8 ~ 4)) 
    
    #  a b c condition
    #1 1 2 4      ncap
    #2 1 3 2      ncap
    #3 4 3 2      ncap
    

    如果您再次需要整个数据帧,我们可以

    df %>%
      filter(condition == "acap") %>%
      bind_rows(df %>%
         filter(condition != "acap") %>%
         mutate_at(vars(a:c), function(x) 
        case_when(x == 5 ~ 1, x == 6 ~ 2, x == 7 ~ 3, x == 8 ~ 4)))
    
    #  a b c condition
    #1 1 4 2      acap
    #2 2 3 1      acap
    #3 2 4 3      acap
    #4 1 2 4      ncap
    #5 1 3 2      ncap
    #6 4 3 2      ncap