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

时间:2019-03-03 17:55:19

标签: r dplyr rlang

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

在我的示例中,只有五列,但是在实际数据中,则有更多列(并非所有列都应包含在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)
)

预期输出:

  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

输出为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))

我已经尝试过类似的方法,但是没有成功(“只能将字符串转换为符号”)。我想避免创建额外的变量,只需在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")))
    )
  )

我也尝试过此操作(没有错误,但是列bb的值是错误的):

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

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

3 个答案:

答案 0 :(得分:3)

在删除列名的子字符串(split之后,我们可以list将数据集"_extra"放入data.frames,然后使用map遍历{{ 1}},list列,然后coalesce和原始数据集中的“ _extra”列

bind

答案 1 :(得分:1)

data.table用于meltdcast,因为我不记得spreadgather的工作原理

library(data.table)
library(dplyr)

data_example %>% 
  mutate(row = row_number()) %>% 
  melt('row') %>% 
  group_by(g = sub('_*$', '', variable), row) %>% 
  mutate(value = reduce(value, coalesce)) %>% 
  dcast(row ~ variable) %>% 
  select(-row)

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

答案 2 :(得分:0)

猜猜现在可以使用 mutate + across

达到预期的结果
data_example %>% 
  mutate(across(c(str_subset(names(.), "_extra") %>% str_remove("_extra")) ,
                ~ coalesce( ., get(str_c(cur_column(), "_extra"))  ))) 

  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