【问题标题】:R - New column based on previous columns, for multiple similar variablesR - 基于先前列的新列,用于多个相似变量
【发布时间】:2017-04-13 21:07:47
【问题描述】:

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

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

感谢您的帮助!

【问题讨论】:

标签: r loops iteration apply


【解决方案1】:

这-

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

【讨论】:

  • 如果某些变量有 3 个剂量,而其他变量有 2 个剂量怎么办?
  • 为简单起见,该解决方案并未泛化且仅限于问题发布的要求。你是对的,如果剂量有不同数量的版本,这将不起作用
【解决方案2】:

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

【讨论】:

    【解决方案3】:
    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")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-12
      • 2016-10-04
      • 1970-01-01
      • 2015-08-01
      • 2016-05-06
      • 2018-02-19
      • 1970-01-01
      • 2022-06-30
      相关资源
      最近更新 更多