web-dev-qa-db-ja.com

dplyrを使用したグループ/ IDによるローリング平均(移動平均)

血圧の記録を長期的に追跡しています。

ある時点での値は移動平均(ローリング平均)よりも予測性が低いため、これを計算します。データは次のようになります

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()

私もrollaplyrollmeanrを試してみましたが、成功しませんでした。

15
Adam Robinsson

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ソリューションです。これは、データセットが大きい場合、muchより高速になる可能性があります。

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
# ...
7
jlhoward

これはどう?

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

Zooパッケージの 'rollapply'関数を使用した別のソリューション(私はもっと好きです)

library(dplyr)
library(Zoo)
test2<-arrange(test,ID,YEAR_VISIT) %>%
       mutate(ma2=rollapply(BLOOD_PRESSURE,2,mean,align='right',fill=NA))
13
hyunwoo jeong

これを試して:

library(dplyr)
library(Zoo)
test2<-arrange(test,ID,YEAR_VISIT) %>% group_by(subject)%>%
       mutate(ma2=rollapply(BLOOD_PRESSURE,2,mean,align='right',fill=NA))
1
pier