2014-10-05 80 views
7

我有血壓記錄的縱向跟蹤。按dplyr分組/編號的滾動平均值(移動平均值)

某個點的值比移動平均值(滾動平均值)的預測性要低,這就是我爲什麼要計算它的原因。數據看起來像

test <- read.table(header=TRUE, text = " 
    ID AGE YEAR_VISIT BLOOD_PRESSURE TREATMENT 
    1 20 2000 NA 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 
        ") 

我想計算一個新變量,稱爲BLOOD_PRESSURE_UPDATED。這個變量應該是BLOOD_PRESSURE的移動平均線,並且具有以下特徵:

  • 移動平均值是當前值加前一值除以2。
  • 對於第一個觀察,BLOOD_PRESSURE_UPDATED就是當前的BLOOD_PRESSURE。如果缺少 ,則BLOOD_PRESSURE_UPDATED應該是整體平均值。
  • 缺失值應填入最近的值。

我已經試過如下:

test2 <- test %>% 
    group_by(ID) %>% 
    arrange(ID, YEAR_VISIT) %>% 
    mutate(BLOOD_PRESSURE_UPDATED = rollmean(x=BLOOD_PRESSURE, 2)) %>% 
ungroup() 

我也rollaply嘗試和rollmeanr沒有成功。

我希望得到一些幫助。

+1

當計算移動平均,返回的元素的數量小於所述數據的行數,即,僅「另一種解決方案n-1「元素被返回。因此可能在這裏引起問題。或者你會考慮分別添加移動平均值列,如:test2 $ BLOOD_PRESSURE_UPDATED < - with(test2,c(mean(BLOOD_PRESSURE,na.rm = T),rollapply(BLOOD_PRESSURE,2,mean,na.rm = T)) ) – KFB 2014-10-05 03:40:50

+0

感謝KFB的努力。不幸的是它沒有奏效。我也嘗試了一些編輯過的版本。動物園功能也許不適合這個?我已經編碼了以下工作:test5 < - test test5 $ UM < - rep(NA,nrow(test5)) test5 $ first < - !duplicateated(test5 $ ID) for(i in 1:nrow test5 $)[0] test5 $ [i] < - test5 $ BLOOD_PRESSURE [i] }其他{0} {test5 $ first [i])test5 $ UM [i] < - mean(c(test5 $ BLOOD_PRESSURE [i],test5 $ UM [i-1]),na.rm = TRUE) } } test5 但它的速度令人難以置信。 – 2014-10-05 07:09:28

回答

6

如果不致力於爲dplyr這應該工作:

get.mav <- function(bp,n=2){ 
    require(zoo) 
    if(is.na(bp[1])) bp[1] <- mean(bp,na.rm=TRUE) 
    bp <- na.locf(bp,na.rm=FALSE) 
    if(length(bp)<n) return(bp) 
    c(bp[1:(n-1)],rollapply(bp,width=n,mean,align="right")) 
} 
test <- with(test,test[order(ID,YEAR_VISIT),]) 

test$BLOOD_PRESSURE_UPDATED <- 
    unlist(aggregate(BLOOD_PRESSURE~ID,test,get.mav,na.action=NULL,n=2)$BLOOD_PRESSURE) 
test 
# ID AGE YEAR_VISIT BLOOD_PRESSURE TREATMENT BLOOD_PRESSURE_UPDATED 
# 1 1 20  2000    NA   3    134.6667 
# 2 1 21  2001   129   2    131.8333 
# 3 1 22  2002   145   3    137.0000 
# 4 1 22  2002   130   2    137.5000 
# 5 2 23  2003    NA  NA    130.0000 
# 6 2 30  2010   150   2    140.0000 
# 7 2 31  2011   110   3    130.0000 
# ... 

這適用於移動平均> 2爲好。

這裏是一個data.table解決方案,如果您的數據集很大,這個解決方案很可能會更快,這可能是更快

library(data.table) 
setDT(test)  # converts test to a data.table in place 
setkey(test,ID,YEAR_VISIT) 
test[,BLOOD_PRESSURE_UPDATED:=as.numeric(get.mav(BLOOD_PRESSURE,2)),by=ID] 
test 
# ID AGE YEAR_VISIT BLOOD_PRESSURE TREATMENT BLOOD_PRESSURE_UPDATED 
# 1: 1 20  2000    NA   3    134.6667 
# 2: 1 21  2001   129   2    131.8333 
# 3: 1 22  2002   145   3    137.0000 
# 4: 1 22  2002   130   2    137.5000 
# 5: 2 23  2003    NA  NA    130.0000 
# 6: 2 30  2010   150   2    140.0000 
# 7: 2 31  2011   110   3    130.0000 
# ... 
+0

謝謝@jlhoward! - 它解決了問題,但數據。表格法(這是兩者中速度較快的)非常緩慢(300萬行,在新的MBP上15分鐘)。但是,問題解決了。 – 2014-10-05 20:34:20

+0

謝謝@jlhoward。這爲我節省了很長的計算時間......我早先使用ddply,時間真的很糟糕! – EsBee 2015-10-22 17:44:42

6

這個怎麼樣?

library(dplyr) 
    test2<-arrange(test,ID,YEAR_VISIT) %>% 
      mutate(lag1=lag(BLOOD_PRESSURE), 
        lag2=lag(BLOOD_PRESSURE,2), 
        movave=(lag1+lag2)/2) 

在動物園包使用「rollapply」功能(我喜歡更多)

library(dplyr) 
library(zoo) 
test2<-arrange(test,ID,YEAR_VISIT) %>% 
     mutate(ma2=rollapply(BLOOD_PRESSURE,2,mean,align='right',fill=NA)) 
+0

請注意,如果使用rollapplyr,則可以刪除align參數。 – 2017-09-21 18:42:34