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

如何在循环中使用mutate和ifelse?

  •  1
  • Marco  · 技术社区  · 5 年前

    # load tidyverse
    library(tidyverse)
    
    # create data
    data <- data.frame(x = runif(1:100, min=0, max=100))
    
    # What I do
    data <- data %>%
      mutate(x20 = ifelse(x >= 20, 1, 0)) %>%
      mutate(x40 = ifelse(x >= 40, 1, 0)) %>%
      mutate(x60 = ifelse(x >= 60, 1, 0)) %>%
      mutate(x80 = ifelse(x >= 80, 1, 0)) 
      
    # What I would like to do
    for (i in seq(from=0, to=100, by=20)){
      data %>% mutate(paste(x,i) = ifelse(x >= i, 1,0))
    }
    

    谢谢您。

    3 回复  |  直到 5 年前
        1
  •  3
  •   heds1    5 年前

    Ronak的base R可能是最好的,但为了完整起见,这里有另一种类似于您最初使用dplyr的方法:

    for (i in seq(from=0, to=100, by=20)){
        var <- paste0('x',i)
        data <- mutate(data, !!var := ifelse(x >= i, 1,0))
    }
    
              x x0 x20 x40 x60 x80 x100
    1 99.735037  1   1   1   1   1    0
    2  9.075226  1   0   0   0   0    0
    3 73.786282  1   1   1   1   0    0
    4 89.744719  1   1   1   1   1    0
    5 34.139207  1   1   0   0   0    0
    6 88.138611  1   1   1   1   1    0
    
        2
  •  4
  •   Ronak Shah    5 年前

    你可以用 map_dfc 在这里:

    library(dplyr)
    library(purrr)
    breaks <- seq(from=0, to=100, by=20)
    bind_cols(data, map_dfc(breaks, ~
              data %>% transmute(!!paste0('x', .x) := as.integer(x > .x))))
    
    #             x x0 x20 x40 x60 x80 x100
    #1    6.2772517  1   0   0   0   0    0
    #2   16.3520358  1   0   0   0   0    0
    #3   25.8958212  1   1   0   0   0    0
    #4   78.9354970  1   1   1   1   0    0
    #5   35.7731737  1   1   0   0   0    0
    #6    5.7395139  1   0   0   0   0    0
    #7   49.7069551  1   1   1   0   0    0
    #8   53.5134559  1   1   1   0   0    0
    #...
    #....     
    

    data[paste0('x', breaks)] <- lapply(breaks, function(x) as.integer(data$x > x))
    
        3
  •  3
  •   Darren Tsai    5 年前

    你可以用 reduce() 在里面 purrr

    library(dplyr)
    library(purrr)
    
    reduce(seq(0, 100, by = 20), .init = data,
           ~ mutate(.x, !!paste0('x', .y) := as.integer(x >= .y)))
    
    #             x x0 x20 x40 x60 x80 x100
    # 1   61.080545  1   1   1   1   0    0
    # 2   63.036673  1   1   1   1   0    0
    # 3   71.064322  1   1   1   1   0    0
    # 4    1.821416  1   0   0   0   0    0
    # 5   24.721454  1   1   0   0   0    0
    

    base Reduce() :

    Reduce(function(df, y){ df[paste0('x', y)] <- as.integer(df$x >= y); df },
           seq(0, 100, by = 20), data)