我想知道是否有解决方案来转换管道中的多个列。
让我们说我们有一个三列的元组。 iq_pre
和iq_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
以更优雅的方式解决这个问题?
答案 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)