簡體   English   中英

dplyr: mutate_at + coalesce: 列的動態名稱

[英]dplyr: mutate_at + coalesce: dynamic names of columns

我一直在嘗試將mutate_atcoalesce結合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)
)

預期輸出:

  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

我們可以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

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

猜猜現在可以使用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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM