R - 基于先前列的新列,用于多个相似变量

R - New column based on previous columns, for multiple similar variables

这个问题与之前的问题(基于我的搜索)类似,但有所不同。我希望使用 [s,l,v]apply 来执行此操作以提高效率。

df <- data.frame(id = c(1,2,3,1,2), var1_dose_v1 = c(2,4,NA,1,NA),
             var1_dose_v2 = c(NA,NA,4,NA,3),
             var2_dose_v1 = c(NA,4,2,3,5),
             var2_dose_v2 = c(1,NA,NA,NA,NA),
             var3_dose_v1 = c(NA,NA,2,3,5),
             var3_dose_v2 = c(1,4,NA,NA,NA)))

如下所示

id var1_dose_v1 var1_dose_v2 var2_dose_v1 var2_dose_v2 var3_dose_v1 var3_dose_v2
1            2           NA           NA            1           NA            1
2            4           NA            4           NA           NA            4
3           NA            4            2           NA            2           NA
1            1           NA            3           NA            3           NA
2           NA            3            5           NA            5           NA

我想创建一个新功能,合并每个 var# 的版本 1 (v1) 和版本 2 (v2) 的信息,生成以下输出。

id var1_dose var2_dose var3_dose
1         2          1         1
2         4          4         4
3         4          2         2
4         1          3         3
5         3          5         5

使用 apply 对我来说很重要,因为有成千上万的 var#s。

感谢您的帮助!

func <- function(i){
  col <- paste0("var",i,"_dose")
  xx <- colnames(df)[grep(col, colnames(df))]
   yy <- rowSums(df[xx], na.rm = TRUE)
}
l = lapply(1:((dim(df)[2]-1)/2)  , func)

df1 = as.data.frame(l)
colnames(df1) <- paste0("var",1:((dim(df)[2]-1)/2),"_dose")

# > df1
#   var1_dose var2_dose var3_dose
# 1         2         1         1
# 2         4         4         4
# 3         4         2         2
# 4         1         3         3
# 5         3         5         5

如果 2 个版本总是并排:那么我的代码的简洁版本可以是

l = lapply(1:((dim(df)[2]-1)/2), 
    function(i) rowSums(df[colnames(df)[c(i*2,i*2+1)]], na.rm = T))
df1 = as.data.frame(l)
colnames(df1) <- paste0("var",1:((dim(df)[2]-1)/2),"_dose")

这个-

df[is.na(df)] <- 0
new_df <- sapply(seq(1:((ncol(df)-1)/2)), function(x) 
          {
           df[, paste0("var",x,"_dose_v1")] + df[, paste0("var",x,"_dose_v2")]
          })

要获得适用于任意数量的变量或剂量的通用解决方案,dplyr 中有一个名为 'coalesce' 的新函数为此构建:

library(dplyr)
grps <- unique(sub("_v.*$?", "", names(df)[-1]))
mat <- sapply(grps, function(g) {
  do.call("coalesce", unname(as.list(df[grep(g, names(df))])))
})
df2 <- data.frame(id=df$id, mat)
#   id var1_dose var2_dose var3_dose
# 1  1         2         1         1
# 2  2         4         4         4
# 3  3         4         2         2
# 4  1         1         3         3
# 5  2         3         5         5