如何根据R中的列内容将列名称拉入新列

ale*_*gan 3 r dplyr data.table tidyr purrr

我需要做三个动作:

1. 计算表中按行非 NA 的值并对它们求和(在单列“check_na”中)

[我将我的解决方案放在下面,如果有人能弄清楚如何使用地图来做到这一点,我很感兴趣。我已经检查过 /sf/ask/3547628941/ 来获取答案]

2. 对于那些不为 NA 的值,创建一个列,将这些唯一值连接到新列“块详细信息”中。

[我不知道该怎么做]

3. 如果“check_na”有值,则提取列名称并将它们连接到新列中(“块类型”)

[我不知道该怎么做]

这就是最终产品应该的样子。请注意,在第 2 行中,即使“b”出现两次,它在“块详细信息”中只显示一次,但包含它的列单独列出“y|z”

      w x     y     z     na_check block_detail block_type
  <dbl> <chr> <chr> <chr>    <int> <chr>        <chr>     
1    NA a     NA    NA           1 a            x         
2    NA NA    b     b            2 b            y|z       
3    NA NA    b     c            2 b|c          y|z       
4    NA NA    NA    NA           0 NA           NA        
5    NA NA    NA    b            1 b            z 
Run Code Online (Sandbox Code Playgroud)

下面是示例数据和我对第 1 部分的解决方案:


#sample data
df <- tibble(w=rep(NA_real_,5),
       x=c(1,rep(NA_real_,4)),
       y=c(NA_real_,1,rep(NA_real_,3)),
       z=c(NA_real_,1,rep(NA_real_,2),1)
       )

#my solution to the first part, interested if someone can do this more efficiently or can do this with map as I have 100s columns that I need to do this with

df_na_check <- df %>% 
  mutate(across(everything(),
                list(na_check=~!is.na(.)),
                .names="{.col}_{.fn}")) %>% 
  rowwise() %>% 
mutate(na_check=sum(c_across(contains("na_check")))) %>% 
  select(w:z,na_check)

Run Code Online (Sandbox Code Playgroud)

我很感激任何帮助。理想情况下,如果解决方案可以使用 tidyverse 但对其他方法开放(data.table 或 base r)

And*_*own 5

我们可以首先使用rowSums来获取不是 的列数NA。然后,我们可以使用折叠不属于的purrr唯一字符。然后,我们可以使用遍历每一行来获取没有 for 的列名称。NAblock_detailapplyNAblock_type

library(tidyverse)

df %>% 
  mutate(na_check = rowSums(!is.na(.), na.rm = T),
         block_detail = pmap_chr(select(., -na_check), ~paste0(unique(na.omit(c(...))), collapse = "|")),
         block_type = apply(df, 1, \(x) paste0(names(df)[which(!is.na(x))], collapse = "|")))
Run Code Online (Sandbox Code Playgroud)

输出

   w    x    y    z na_check block_detail block_type
1 NA    a <NA> <NA>        1            a          x
2 NA <NA>    b    b        2            b        y|z
3 NA <NA>    b    c        2          b|c        y|z
4 NA <NA> <NA> <NA>        0                        
5 NA <NA> <NA>    b        1            b          z
Run Code Online (Sandbox Code Playgroud)

或者使用purrr而不是apply

df %>% 
  mutate(na_check = rowSums(!is.na(.), na.rm = T),
         block_detail = pmap_chr(select(., -na_check), ~str_c(unique(na.omit(c(...))), collapse = "|"))) %>% 
  mutate(block_type = pmap_chr(select(., -c(na_check, block_detail)), ~str_c(names(c(...))[!is.na(c(...))], collapse="|")))
Run Code Online (Sandbox Code Playgroud)

数据

df <- structure(list(w = c(NA, NA, NA, NA, NA), x = c("a", NA, NA, 
NA, NA), y = c(NA, "b", "b", NA, NA), z = c(NA, "b", "c", NA, 
"b")), class = "data.frame", row.names = c(NA, -5L))
Run Code Online (Sandbox Code Playgroud)