这是我的数据框:
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
,因为没有它我也可以做到(但它看起来不漂亮而且速度很慢)。
这是一个选项 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)
或者用apply
在base 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)