dplyr:mutate_at +合并:列的动态名称

RSz*_*SzT 7 r dplyr rlang

我一直在尝试结合mutate_at使用coalesce,以防动态生成列名。

在我的示例中,只有五列,但是在实际数据中,则有更多列(并非所有列都应包含在coalesce步骤中)。

DF示例:

data_example <- data.frame(
  aa = c(1, NA, NA),
  bb = c(NA, NA, 2),
  cc = c(6, 7, 8),
  aa_extra = c(2, 2, NA),
  bb_extra = c(1, 2, 3)
)
Run Code Online (Sandbox Code Playgroud)

预期产量:

  aa bb cc aa_extra bb_extra
1  1  1  6        2        1
2  2  2  7        2        2
3 NA  2  8       NA        3

Run Code Online (Sandbox Code Playgroud)

输出为structure

structure(list(aa = c(1, 2, NA), bb = c(1, 2, 2), cc = c(6, 7, 
8), aa_extra = c(2, 2, NA), bb_extra = c(1, 2, 3)), class = "data.frame", row.names = c(NA, 
-3L))
Run Code Online (Sandbox Code Playgroud)

我已经尝试过类似的方法,但是没有成功(“只能将字符串转换为符号”)。我想避免创建额外的变量,只在mutate_at表达式中包含所有内容,因为这是较长的dplyr“流”的一部分。

data_example %>%
  dplyr::mutate_at(
    gsub("_extra", "", grep("_extra$",
                            colnames(.),
                            perl = T,
                            value = T)),
    dplyr::funs(
      dplyr::coalesce(., !!! dplyr::sym(paste0(., "_extra")))
    )
  )

Run Code Online (Sandbox Code Playgroud)

我也试过了(没有错误,但列的值bb是错误的):

data_example %>%
  dplyr::mutate_at(
    gsub("_extra", "", grep("_extra$",
                            colnames(.),
                            perl = T,
                            value = T)),
    dplyr::funs(
      dplyr::coalesce(., !!as.name(paste0(names(.), "_extra")))
    )
  )
Run Code Online (Sandbox Code Playgroud)

如何获取已处理列的名称并将其传递给coalesce

akr*_*run 6

在删除列名称的子字符串()之后,可以split将数据集转换list为data.frames "_extra",然后map循环遍历listcoalesce列,然后bind使用原始数据集中的“ _extra”列

library(tidyverse)
data_example %>% 
   split.default(str_remove(names(.), "_extra")) %>%
   map_df(~ coalesce(!!! .x)) %>%
   #or use
   # map_df(reduce, coalesce) %>%
   bind_cols(., select(data_example, ends_with("extra")))
# A tibble: 3 x 5
#     aa    bb    cc aa_extra bb_extra
#  <dbl> <dbl> <dbl>    <dbl>    <dbl>
#1     1     1     6        2        1
#2     2     2     7        2        2
#3    NA     2     8       NA        3
Run Code Online (Sandbox Code Playgroud)