Использование mutate_at с префиксными именами столбцов для сравнения значений - PullRequest
1 голос
/ 28 октября 2019

У меня есть датафрейм со старыми и новыми значениями. Мне нужно обновить новые значения, если что-то изменилось. Я думаю, что я действительно близко, но я не могу найти недостающую часть , используя tidyverse . С базой R - с использованием цикла for - это работает, но я не хочу создавать новые объекты или перезаписывать существующий.

data <- tribble(~id, ~firstname, ~lastname, ~old_firstname, ~old_lastname,
    1, NA, NA, "Peter", "Busch",
    2, NA, "Trochen-Pflaume", "Hans", "Trocken")


data%>%
mutate_at(vars(firstname, lastname), ~case_when(
is.na(.) & !is.na(str_c("old_",.)) ~ str_c("old_", .)),
!is.na(.) & . != str_c("old_",.) ~ .)

По сути, единственное, что нужно проверить - это новое значениепусто, тогда старое значение должно быть принято. В результате планируются более сложные запросы case_when. Но я не могу манипулировать именем столбца в функции mutate_at.

Что я хочу, но это зависит от case_when:

  tribble(~id, ~firstname, ~lastname, ~old_firstname, ~old_lastname,
            1, "Peter", "Busch", "Peter", "Busch",
            2,"Hans", "Trochen-Pflaume", "Hans", "Trocken")

Спасибо за помощь!

Ответы [ 2 ]

1 голос
/ 29 октября 2019

Это сложный вопрос. Я использую обходной путь для подобных проблем, но я еще не нашел способ, который работает с использованием mutate_at. Проблема с mutate_at заключается в том, что я не знаю, как получить доступ к имени каждой переменной. В «нормальном» вызове mutate/case_when или transmute/case_when вы определяете !! x :=, а затем можете получить доступ к имени переменной с помощью !! sym(x) и получить имена вашей переменной с помощью !! sym(paste0(“someprefix_”, x)).

. проблема будет решена с помощью пользовательской функции transmute/case_when:

recode_vars <- function(df, x) {      
  transmute(df, 
         !! x := case_when(  
           is.na(!! sym(x)) & !is.na(!! sym(paste0("old_",x))) ~ as.character(!! sym(paste0("old_", x))),
           (!is.na(!! sym(x)) & !! sym(x) != !! sym(paste0("old_",x))) ~ as.character(!! sym(x))
         )
  ) 
} 

# Define here the variable names you want to recode
var_ls <- c("firstname", "lastname")

bind_cols(map_dfc(var_ls, ~ recode_vars(data, .x)),
          select(data, -var_ls)) %>% 
          select(id, everything())

С помощью map_dfc вы получите фрейм данных со всеми вашими недавно перекодированными столбцами, а затем вам нужно будет связать их с вашим старым фреймом данныхпри отбрасывании старых столбцов - это работает, но не гладко и не происходит в чистом конвейере dplyr.

Интересно, есть ли более удобный способ использования mutate_at вместо моего подхода, описанного выше.

0 голосов
/ 29 октября 2019

Как насчет использования na.locf из пакета zoo?

library(zoo)

data <- data.frame(t(apply(data[,c(2,4)],1,function(x) na.locf(x,fromLast = T))),
                     t(apply(data[,c(3,5)],1,function(x) na.locf(x,fromLast = T))))
data <- data[,c(1,3,2,4)]

вывод:

> data
  firstname        lastname old_firstname old_lastname
1     Peter           Busch         Peter        Busch
2      Hans Trochen-Pflaume          Hans      Trocken
...