Используйте числовое значение `colnames` для пересчета столбцов в data.frame, используя` dplyr` `mutate_at` или альтернативу - PullRequest
2 голосов
/ 29 апреля 2019

У меня есть 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 ]

3 голосов
/ 29 апреля 2019

В базе 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])
3 голосов
/ 29 апреля 2019

Измените, сделайте вещи, затем измените форму снова:

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
3 голосов
/ 29 апреля 2019

Вот один вариант с 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...