使用mutate_at和前缀列名称比较值

时间:2019-10-28 15:53:17

标签: r dplyr tidyverse

我有一个包含旧值和新值的数据框。如果发生更改,我需要更新新值。我想我真的很亲密,但是我找不到使用tidyverse 的失物。使用base 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 个答案:

答案 0 :(得分:1)

这是一个具有挑战性的问题。我正在针对类似问题使用解决方法,但尚未找到使用mutate_at的方法。 mutate_at的问题在于我不知道如何访问每个变量的名称。在“普通” mutate/case_whentransmute/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代替我上面的方法是否还有更简便的方法。

答案 1 :(得分:0)

如何使用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