【问题标题】:Handling of longitudinal (repeated measurements) data in dplyr?在 dplyr 中处理纵向(重复测量)数据?
【发布时间】: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 的帮助下),您的每一项要求都非常可行。查看dplyrgroup_by & arrangemutate 函数并查看zoona.locf 函数。
  • 你试过什么?我也很好奇,你为什么要用dplyr?现在用这个包做事是不是更优雅?
  • @agstudy:使用dplyr+zoo,这个非常简单/优雅/可读。我几乎想发布一个解决方案只是为了参考常见问题解答,但 OP 几乎没有任何迹象表明他们自己尝试解决方案。
  • @hrbrmstr 优雅/可读是非常主观的限定词。我知道我们可以使用zoo 包中的rollapply+na.locf。但我只是说有一种对dplyr 包做事的痴迷,就像它是“R 方式”或唯一的做事方式。在使用任何其他包之前,最好学习如何使用 Base R 做(至少尝试做)事情。
  • @agstudy 我认为建议人们在包之前使用base R(不管是谁写的!)是无稽之谈。使用可以最有效地解决问题的包(基础或其他)。

标签: r dplyr


【解决方案1】:

回答只是为了捍卫我在 cmets 中的主张:

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,也很难说它不可读且简洁。

警告:TREATMENT 中的NAs 可以填写“反向”,但 OP 并没有说这是要求。

【讨论】:

  • 谢谢@hrbmrstr!至于否决票;当人们不附上他们的代码尝试时,我经常看到投票失败,但通常(尤其是像我这样的新手)没有足够的编码示例来呈现......我尝试了你的答案 hrbrmrstr 并且效果很好,除了从那个血压没有更新平均值,它是整体平均值。更新的平均值是同一个人的每个新观察的新平均值。我自己也不知道该怎么做..再次感谢
  • 我会使用 rollmeanr(BLOOD_PRESSURE,2) 之类的东西来表示“更新的平均值”。
  • @AdamRobinsson 我反对并投票结束这个问题,因为您同时提出了许多问题。这在 SO 中真的不鼓励。没有你的任何尝试,这看起来像是为我做的。请注意,一旦您添加了一些代码,我就会投票赞成,并且我也会撤回我的结束投票。
  • 感谢 agstudy。我似乎没有滚动平均值解决了最后的难题。谢谢你们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-24
  • 2015-12-06
  • 1970-01-01
  • 2023-01-11
  • 2016-10-02
  • 2012-08-17
相关资源
最近更新 更多