【发布时间】:2014-11-22 07:09:56
【问题描述】:
Hadley Wickham 的 dplyr 包中确实有一些不错的功能。
我想知道包中的功能是否可以解决以下与纵向数据有关的问题(对同一个人的重复测量);我在 Internet 上找到了稀缺教程的主题。
数据集如下所示:
test <- read.table(header=TRUE, text = "
ID AGE YEAR_VISIT BLOOD_PRESSURE TREATMENT
1 20 2000 130 3
1 21 2001 129 2
1 22 2002 145 3
1 22 2002 130 2
2 23 2003 NA NA
2 30 2010 150 2
2 31 2011 110 3
4 50 2005 140 3
4 50 2005 130 3
4 50 2005 NA 3
4 51 2006 312 2
5 27 2010 140 4
5 28 2011 170 4
5 29 2012 160 NA
7 40 2007 120 NA
")
ID 是标识特定个体的变量(多行 = 重复测量)。 AGE、YEAR_VISIT(检查年份)、BLOOD_PRESSURE(连续)和 TREATMENT(治疗类型,分类)每次注册都会更新。
我想做以下事情:
(1) 识别并保留每个人的第一个 AGE 和第一个 YEAR_VISIT;这应该会生成两个新变量,例如 first_age 和 first_year。
2) 创建一个新变量,它是先前值和当前值的更新平均值。这意味着第一次观察的更新血压只是当前值;下一次观察更新值等于(前血压值+当前)/2。如果缺少当前值,那么它应该保留以前的值(如果有的话)。
3) 通过将前一个值向前(最后一个观察结果向前)来填充分类变量 TREATMENT 中的缺失值。
我知道这不止一个问题,但它涉及到同一个主题,即纵向数据的处理。
我自己努力解决了这个问题,但没有成功,也许更多的 R 用户有同样的困难?
我尝试了以下方法:
结转丢失的血压并确定每个人的首次观察结果
test4 <- test
test4$first <- !duplicated(test4$ID)
for(i in 2:nrow(test4)){
if(!test4$first[i] & test4$ID[i] == test4$ID[i-1] & is.na(test4$BLOOD_PRESSURE[i])){
test4$BLOOD_PRESSURE[i] <- test4$BLOOD_PRESSURE[i-1]
}
}
test
test4
更新的血压平均值
test5 <- test
test5$UM <- rep(NA, nrow(test5))
test5$first <- !duplicated(test5$ID)
for(i in 1:nrow(test5)){
if(test5$first[i]){
test5$UM[i] <- test5$BLOOD_PRESSURE[i]
}else{
test5$UM[i] <- mean(c(test5$BLOOD_PRESSURE[i] , test5$UM[i-1]), na.rm=TRUE)
}
}
test5
我认为编写代码很麻烦,特别是因为我想更新手段并继承几个变量...
正如您所指出的,我是 R 新手,非常感谢您的帮助。
【问题讨论】:
-
我认为一些反对票和接近票(这些票都不是我的)是因为没有“表现出一些努力”。使用
dplyr(在zoo的帮助下),您的每一项要求都非常可行。查看dplyr的group_by&arrange和mutate函数并查看zoo的na.locf函数。 -
你试过什么?我也很好奇,你为什么要用
dplyr?现在用这个包做事是不是更优雅? -
@agstudy:使用
dplyr+zoo,这个非常简单/优雅/可读。我几乎想发布一个解决方案只是为了参考常见问题解答,但 OP 几乎没有任何迹象表明他们自己尝试解决方案。 -
@hrbrmstr 优雅/可读是非常主观的限定词。我知道我们可以使用
zoo包中的rollapply+na.locf。但我只是说有一种对dplyr包做事的痴迷,就像它是“R 方式”或唯一的做事方式。在使用任何其他包之前,最好学习如何使用 Base R 做(至少尝试做)事情。 -
@agstudy 我认为建议人们在包之前使用base R(不管是谁写的!)是无稽之谈。使用可以最有效地解决问题的包(基础或其他)。