在mutate_at

时间:2018-11-04 00:15:34

标签: r dplyr purrr mutate

我想使用相同的广义one创建三个新变量(分别称为twothreemutate),但内部使用不同的现有变量mutate。为此,我想编写一个简短的代码块来完成与以下(详细)代码相同的事情:

mtcars.modified <- mtcars %>%

  mutate(one = factor(case_when(
    mpg < 10 ~ "lt10",
    mpg >= 10 & mpg <= 20 ~ "10to20",
    mpg > 20 ~ "gt20"),
    ordered=T, levels = c("lt10", "10to20", "gt20"))) %>%

  mutate(two = factor(case_when(
    disp < 10 ~ "lt10",
    disp >= 10 & disp <= 20 ~ "10to20",
    disp > 20 ~ "gt20"),
    ordered=T, levels = c("lt10", "10to20", "gt20"))) %>%

  mutate(three = factor(case_when(
    qsec < 10 ~ "lt10",
    qsec >= 10 & qsec <= 20 ~ "10to20",
    qsec > 20 ~ "gt20"),
    ordered =T, levels = c("lt10", "10to20", "gt20")))

我可以概括这种情况的一种方法是使用mutate_at的后缀行为,然后再重命名:

mtcars.modified <- mtcars %>%
  mutate_at(c("mpg", "disp", "qsec"),
            funs(mod = factor(case_when(
              . < 10 ~ "lt10",
              . >= 10 & . <= 20 ~ "10to20",
              . > 20 ~ "gt20"),
              ordered =T, levels = c("lt10", "10to20", "gt20")))) %>%
  rename(one = mpg_mod,
         two = disp_mod,
         three = qsec_mod)

不过,这似乎是一种解决方法。有什么方法可以执行此操作而无需事后rename吗?我想知道是否可以给onetwothree作为.vars,然后以某种方式将第二组变量传递到case_when中。感觉类似于一个map2问题,在该问题中,您有两个对应的向量,以及一个函数,该函数成对地取两个向量中的项。

这是我(失败的)尝试在map2参数中使用funs的尝试:

mtcars.modified <- mtcars %>%
  mutate_at(c("one", "two", "three"),
            funs(map2(.x = ., .y = c(mpg, disp, qsec), 
                      ~ factor(case_when(
                        .y < 10 ~ "lt10",
                        .y >= 10 & .y <= 20 ~ "10to20",
                        .y > 20 ~ "gt20"),
                        ordered =T, levels = c("lt10", "10to20", "gt20")))))

我想将所有内容保留在mtcars %>%管道中,而无需创建命名函数或破坏管道。

2 个答案:

答案 0 :(得分:1)

library(tidyverse)
mtcars %>%
  dplyr::mutate_at(c("mpg", "disp", "qsec"), cut,
                   breaks = c(-Inf, 10, 20, Inf),
                   labels = c("lt10", "10to20", "gt20")) %>%
  head()
#>      mpg cyl disp  hp drat    wt   qsec vs am gear carb
#> 1   gt20   6 gt20 110 3.90 2.620 10to20  0  1    4    4
#> 2   gt20   6 gt20 110 3.90 2.875 10to20  0  1    4    4
#> 3   gt20   4 gt20  93 3.85 2.320 10to20  1  1    4    1
#> 4   gt20   6 gt20 110 3.08 3.215 10to20  1  0    3    1
#> 5 10to20   8 gt20 175 3.15 3.440 10to20  0  0    3    2
#> 6 10to20   6 gt20 105 2.76 3.460   gt20  1  0    3    1

您可以使用cut function来完成此任务。这是您想要的吗?

如果要保留原始列,并且在修改后的列中需要后缀_mod,可以执行以下操作:

library(tidyverse)
mtcars %>%
  dplyr::mutate_at(c("mpg", "disp", "qsec"),
                   dplyr::funs(
                     mod = cut(.,
                               breaks = c(-Inf, 10, 20, Inf),
                               labels = c("lt10", "10to20", "gt20")
                               )
                     )
                   ) %>%
  head()
#>    mpg cyl disp  hp drat    wt  qsec vs am gear carb mpg_mod disp_mod
#> 1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4    gt20     gt20
#> 2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4    gt20     gt20
#> 3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1    gt20     gt20
#> 4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1    gt20     gt20
#> 5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2  10to20     gt20
#> 6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1  10to20     gt20
#>   qsec_mod
#> 1   10to20
#> 2   10to20
#> 3   10to20
#> 4   10to20
#> 5   10to20
#> 6     gt20

答案 1 :(得分:1)

如果使用void coordinates(unsigned int p, int xyz[3]) { xyz[0] = (p >> 20) & 0x3FF; // Get 10 Bits if(xyz[0] & 0x200) // Check MSB xyz[0] |= 0xFFFFFC00; // Sign Extend xyz[1] = (p >> 10) & 0x3FF; if(xyz[1] & 0x200) xyz[1] |= 0xFFFFFC00; xyz[2] = p & 0x3FF; if(xyz[2] & 0x200) xyz[2] |= 0xFFFFFC00; } int main(void) { int s10[3]; unsigned int u32 = 0xFFFFFFFF; coordinates(u32, s10); printf("%08X %08X %08X %08X\n", u32, s10[0], s10[1], s10[2]); printf("%d %d %d %d\n", u32, s10[0], s10[1], s10[2]); u32 = 0x1FF7FDFF; coordinates(u32, s10); printf("%08X %08X %08X %08X\n", u32, s10[0], s10[1], s10[2]); printf("%d %d %d %d\n", u32, s10[0], s10[1], s10[2]); u32 = 0x20080200; coordinates(u32, s10); printf("%08X %08X %08X %08X\n", u32, s10[0], s10[1], s10[2]); printf("%d %d %d %d\n", u32, s10[0], s10[1], s10[2]); u32 = 0x00000000; coordinates(u32, s10); printf("%08X %08X %08X %08X\n", u32, s10[0], s10[1], s10[2]); printf("%d %d %d %d\n", u32, s10[0], s10[1], s10[2]); return 0; } 函数,则可以在应用函数之前重命名。

dplyr::vars

这也与@seisdrum有关使用mtcars %>% mutate_at( vars(one = mpg, two = disp, three = qsec), funs( case_when( . < 10 ~ 'lt10', . >= 10 & . <= 20 ~ "10to20", . > 20 ~ 'gt20' ) %>% ordered(levels = c('lt10', '10to20', 'gt20')) ) )

的好建议一起使用
base::cut