使用 R 中的 dplyr 库“打印”非 NA 列的名称

Ant*_*ser 7 r dplyr

这是我的数据框:

a <- data.frame(id=c(rep("A",2),rep("B",2)),
                x=c(rep(2,2),rep(3,2)),
                p.ABC= c(1,NA,1,1),
                p.DEF= c(NA,1,NA,NA),
                p.TAR= c(1,NA,1,1),
                p.REP= c(NA,1,1,NA),
                p.FAR= c(NA,NA,1,1))
Run Code Online (Sandbox Code Playgroud)

我想创建一个新的字符列(在 Rmutate()中的dplyr库中使用),它告诉(按行)具有非 NA 值的列的名称(此处非 NA 值始终为 1)。但是,它应该只在以“p”开头的列中搜索。它应该按字母顺序对名称进行排序,然后使用表达式“_”作为分隔符将它们连接起来。您可以在所需结果下方的“名称”列下找到:

data.frame(id=c(rep("A",2),rep("B",2)),
                x=c(rep(2,2),rep(3,2)),
                p.ABC= c(1,NA,1,1),
                p.DEF= c(NA,1,NA,NA),
                p.TAR= c(1,NA,1,1),
                p.REP= c(NA,1,1,NA),
                p.FAR= c(NA,NA,1,1),
                name=c("ABC_TAR","DEF_REP","ABC_FAR_REP_TAR","ABC_FAR_TAR"))
Run Code Online (Sandbox Code Playgroud)

我想强调的是,我真的在寻找使用 的解决方案dplyr,因为没有它我也可以做到(但它看起来不漂亮而且速度很慢)。

akr*_*run 7

这是一个选项 with tidyverse,我们将数据重新整形为“long”格式pivot_longer,分组为row_number()),paste删除前缀部分后的列名列“name”值,然后将该列与原始数据绑定

library(dplyr)
library(stringr)
library(tidyr)
a %>% 
    mutate(rn = row_number()) %>%
    select(-id, -x) %>%
    pivot_longer(cols = -rn, values_drop_na = TRUE) %>%
    group_by(rn) %>%
    summarise(name = str_c(str_remove(name, ".*\\."), collapse="_"), 
         .groups = 'drop') %>%
    select(-rn) %>% 
    bind_cols(a, .)
Run Code Online (Sandbox Code Playgroud)

-输出

# id x p.ABC p.DEF p.TAR p.REP p.FAR            name
#1  A 2     1    NA     1    NA    NA         ABC_TAR
#2  A 2    NA     1    NA     1    NA         DEF_REP
#3  B 3     1    NA     1     1     1 ABC_TAR_REP_FAR
#4  B 3     1    NA     1    NA     1     ABC_TAR_FAR
Run Code Online (Sandbox Code Playgroud)

或使用 pmap

library(purrr)
a %>% 
   mutate(name = pmap_chr(select(cur_data(), contains('.')), ~ {
       nm1 <- c(...)
       str_c(str_remove(names(nm1)[!is.na(nm1)], '.*\\.'), collapse="_")}))
#  id x p.ABC p.DEF p.TAR p.REP p.FAR            name
#1  A 2     1    NA     1    NA    NA         ABC_TAR
#2  A 2    NA     1    NA     1    NA         DEF_REP
#3  B 3     1    NA     1     1     1 ABC_TAR_REP_FAR
#4  B 3     1    NA     1    NA     1     ABC_TAR_FAR
Run Code Online (Sandbox Code Playgroud)

或者用applybase R

apply(a[-(1:2)], 1, function(x) paste(sub(".*\\.", "", 
        names(x)[!is.na(x)]), collapse="_"))
#[1] "ABC_TAR"         "DEF_REP"         "ABC_TAR_REP_FAR" "ABC_TAR_FAR"    
Run Code Online (Sandbox Code Playgroud)