我有一个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
或其他方法实现预期的输出?
答案 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