以整齐的方式转换多列

时间:2018-03-20 08:25:38

标签: r tidyverse

我想知道是否有解决方案来转换管道中的多个列。

让我们说我们有一个三列的元组。 iq_preiq_post必须按日志比例进行转换,并保存到新列中。

library(tidyverse)
library(magrittr)

df <- tibble(
  iq_pre = rnorm(10, 100, 15),
  iq_post = rnorm(10, 100, 18),
  gender = rep(c("m", "f"), each = 5)
)

我知道我可以通过

获得基础R的结果
df[c("iq_pre_lg", "iq_post_lg")] <- log(df[c("iq_pre", "iq_post")])

或用lapply循环遍历列。

我想出的唯一整洁的解决方案是为每个列手动使用mutate,如

df %<>% 
  mutate(iq_pre_lg = log(iq_pre),
         iq_post_lg = log(iq_post))

由于应该转换的列的名称以相同的字母开头,我也可以使用

df %<>% 
  mutate_at(vars(starts_with("iq")), funs(lg = log(.)))

但是,如果我想转换为具有不同名称的20列,该怎么办?有没有办法使用purrr::map或甚至tidyr::nest以更优雅的方式解决这个问题?

1 个答案:

答案 0 :(得分:3)

我们可以使用

df %>%
     mutate_at(vars(matches("iq")), log)

matches的一个优点是可以在一次调用中匹配多个模式。例如,如果我们需要在使用&#39; iq&#39;开始(^)的列上应用该函数。或(|)结尾($)与&#39; oq&#39;,这可以传递到单matches

df %>%
  mutate_at(vars(matches('^iq|oq$'), log)

如果列名完全不同且n列有n个模式,但如果列的位置仍有一些顺序,则列位置编号可以传递到vars。在当前的例子中,&#39; iq&#39;列是第1列和第2列

df %>% 
   mutate_at(1:2, log)

同样,如果20列占据前20个位置

df %>%
   mutate_at(1:20, log)

或者如果位置是1到6,8到12,41:50

df %>%
    mutate_at(vars(1:6, 8:12, 41:50), log)