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

时间:2016-11-29 18:30:38

标签: r loops iteration apply

此问题类似于之前的问题(基于我的搜索),但有一个转折点。我希望使用[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。

感谢您的帮助!

3 个答案:

答案 0 :(得分:0)

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

如果两个版本总是并排:那么我的代码的简化版本可能是

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")

答案 1 :(得分:0)

此 -

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")]
          })

答案 2 :(得分:0)

为了获得适用于任意数量的变量或剂量的解决方案,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