使用`colnames`的数值通过`dplyr`的`mutate_at`或替代方法

时间:2019-04-29 13:00:54

标签: r dplyr

我有一个df,我想根据该列colnames的值重新计算一些列:

library(dplyr)
df <- data.frame(year = 1:3, "10" = 0:2, "20" = 3:5)
colnames(df)[2:3] <- c("10", "20")
df
  year 10 20
1    1  0  3
2    2  1  4
3    3  2  5

预期输出为col_name - col_values。我可以通过以下方式生成预期的输出:

df %>% mutate(`10` = 10 - `10`) %>% mutate(`20` = 20 - `20`)
  year 10 20
1    1 10 17
2    2  9 16
3    3  8 15

如何在不显式复制尊重的colnames值的情况下生成相同的输出?

我尝试了以下代码(有效):

df %>% mutate(`10` = as.numeric(colnames(.)[2]) - `10`) %>% mutate(`20` = as.numeric(colnames(.)[3]) - `20`)

所以我试图进一步减少这种情况,但只能想到:

df %>% mutate_at(vars(-year), ~ as.numeric(colnames(.)[.]))

由于.有两种含义,因此显然无法正常工作。

如何使用mutate_at或其他方法实现预期的输出?

3 个答案:

答案 0 :(得分:3)

这是mutate_at

的一个选项
library(rlang)
library(tidyverse)
df %>% 
    mutate_at(2:3, list(~ as.numeric(as_name(quo(.)))- .))
#  year 10 20
#1    1 10 17
#2    2  9 16
#3    3  8 15

或者也可以使用deparse(substitute

df %>% 
     mutate_at(2:3, list(~ as.numeric(deparse(substitute(.))) - .))

或与map一起使用选项

map_dfc(names(df)[2:3], ~
          df %>%
              select(.x) %>% 
              mutate(!! .x :=   as.numeric(.x) - !! sym(.x))) %>% 
     bind_cols(df %>% 
                  select(year), .)

或与imap

df[-1] <- imap(df[-1], ~ as.numeric(.y) - .x)

答案 1 :(得分:3)

在基数R中,我们可以使用lapply

df[-1] <- lapply(names(df[-1]), function(x) as.numeric(x) - df[,x])

#  year 10 20
#1    1 10 17
#2    2  9 16
#3    3  8 15

mapply

df[-1] <- mapply(`-`, as.numeric(names(df[-1])), df[-1])

答案 2 :(得分:3)

重塑,做东西,然后再次重塑:

gather(df, key = "k", value = "v", -year) %>% 
  mutate(v = as.numeric(k) - v) %>% 
  spread(key = "k", value = "v")

#   year 10 20
# 1    1 10 17
# 2    2  9 16
# 3    3  8 15