R 数据表:如何使用列名向量按行有效地将数据传递给函数?

问题描述 投票:0回答:1

我有一些 data.tables,其中包含多年来多次检查的患者数据,以及一列,其中包含某些事件发生的年份(假设是心脏病发作)。这是一个玩具示例:

dt <- data.table(patient_ID = c("A","B","C","D"),
                 heart_attack_year = c(2010, 2011, 2016, 2011),
                 exam_1_year = c(2005, 2001, 2002, 2002),
                 exam_2_year = c(2010, 2006, 2010, 2007),
                 exam_3_year = c(2015, 2012, 2011, 2012),
                 exam_4_year = c(2020, 2017, 2017, 2014))

我想知道每个患者的心脏病发作时间最接近哪种检查。我编写了一个函数,它将目标年份和不同考试年份的列表 (v) 作为参数,并返回最接近考试的标签:

which_exam_is_closest <- function(target_year, exam_labels, v){
  return(exam_labels[which.min(abs(target_year - unlist(v)))])
}

对于不同的数据集,可以有不同数量的检查。不同数据集的考试年份的列名称也不同。因此,我希望能够使用每个数据集可能不同的字符串向量来引用列名称。

for循环可以获取列表v并为每个数据集的每一行调用该函数。例如,对于上面的玩具数据集,我可以写:

exams <- 1:4

closest_exam <- character(0)
for (i in 1:nrow(dt)){
  closest_exam <- c(closest_exam, which_exam_is_closest(dt$heart_attack_year[i], 
                                                        exams, 
                                                        as.list(dt[i,paste0("exam_",exams,"_year"), with = F])))
}
dt$closest <- closest_exam

这得到了想要的结果:

patient_ID     heart_attack_year exam_1_year exam_2_year exam_3_year exam_4_year closest
A              2010              2005        2010        2015        2020        2
B              2011              2001        2006        2012        2017        3
C              2016              2002        2010        2011        2017        4
D              2011              2002        2007        2012        2014        3

但是,使用 for 循环看起来真的很丑陋且效率低下。有没有更好的方法将每个患者的相关数据列表传递给函数,使用列名称向量,并返回“最接近”的列?

r function data.table rowwise
1个回答
0
投票

您可以逐行减去

abs
which.min

> dt[, closest := apply(abs(dt[, 3:6] - unlist(dt[, 2])), 1, which.min)]
> dt
   patient_ID heart_attack_year exam_1_year exam_2_year exam_3_year exam_4_year closest
1:          A              2010        2005        2010        2015        2020       2
2:          B              2011        2001        2006        2012        2017       3
3:          C              2016        2002        2010        2011        2017       4
4:          D              2011        2002        2007        2012        2014       3
© www.soinside.com 2019 - 2024. All rights reserved.