处理dplyr中的纵向(重复测量)数据?

时间:2014-09-27 10:27:18

标签: r dplyr

Hadley Wickham在 dplyr 包中确实有一些不错的功能。

我想知道包中的功能是否可以解决以下问题,这些问题与纵向数据有关(对同一个人进行重复测量);我在互联网上找到稀缺教程的主题。

数据集如下所示:

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(连续)和治疗(治疗类型,分类)每次注册都会更新。

我想做以下事情:

(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的新手,非常感谢您的帮助。

1 个答案:

答案 0 :(得分:4)

在评论中单独回答我的辩护:

library(dplyr)
library(zoo)

test %>%
  group_by(ID) %>%                                       # work on groups
  arrange(YEAR_VISIT) %>%                                # arrange by year
  mutate(first_age=min(AGE),                             # make col for min age
         first_year=min(YEAR_VISIT),                     # make col for min year
         bp_mean=mean(BLOOD_PRESSURE, na.rm=TRUE),       # make col for mean
         TREATMENT=na.locf(TREATMENT, na.rm=FALSE)) %>%  # use zoo's na.locf to fill in NAs
  ungroup()

##     Source: local data frame [15 x 8]
## 
##    ID AGE YEAR_VISIT BLOOD_PRESSURE TREATMENT first_age first_year  bp_mean
## 1   1  20       2000            130         3        20       2000 133.5000
## 2   1  21       2001            129         2        20       2000 133.5000
## 3   1  22       2002            145         3        20       2000 133.5000
## 4   1  22       2002            130         2        20       2000 133.5000
## 5   2  23       2003             NA        NA        23       2003 130.0000
## 6   2  30       2010            150         2        23       2003 130.0000
## 7   2  31       2011            110         3        23       2003 130.0000
## 8   4  50       2005            140         3        50       2005 194.0000
## 9   4  50       2005            130         3        50       2005 194.0000
## 10  4  50       2005             NA         3        50       2005 194.0000
## 11  4  51       2006            312         2        50       2005 194.0000
...

即使你不知道R,也很难说这是不可读的。简洁。

警告:NA中的TREATMENT可以“反向”填写,但OP并未说这是必需的。