大型复杂测量数据集的R方法?
我不是一名调查方法学家或人口学家,但我是托马斯·卢姆利R调查包的狂热粉丝。我一直在处理一个相对较大的复杂调查数据集,即医疗成本和利用项目(HCUP)国家急诊科样本()。正如医疗保健研究和质量机构所描述的,这是“来自30个州947家医院的急诊室就诊出院数据,约占美国医院急诊室分层样本的20%” 2006年至2012年的完整数据集包括198102435个观测值。我将数据分为40073358个创伤相关出院数据,包含66个变量。在这些数据上运行即使是简单的调查程序也要花费非常长的时间。我曾经尝试过使用RAM(2013年末的Mac Pro,3.7GHz四核,128GB(!)内存),在可用的情况下,使用类似的工具。基于设计的调查程序仍然需要几个小时。有时是几个小时。一些稍微复杂的分析需要15小时以上。我猜大部分的计算工作都与庞大的协方差矩阵有关 正如人们所料,处理原始数据的速度要快几个数量级。更有趣的是,根据程序,对于这么大的数据集,未经调整的估计值可能与调查结果非常接近。(参见下面的示例)基于设计的结果显然更精确,更可取,但数小时的计算时间与几秒的计算时间相比,对于增加的精度来说是一个不可忽略的成本。它开始看起来像是绕着街区走了很长一段路 有没有人有过这样的经历?有没有办法优化大型数据集的R调查程序?也许可以更好地利用并行处理?贝叶斯方法是否可以使用Stan等方法?或者,当调查规模较大且具有足够代表性时,是否可以接受一些未经调整的估计,尤其是相对测量 以下是两个未经调整的估计值与调查结果近似的示例 在第一个例子中,svymean在内存中花费的时间不到一个小时,内存不足需要3个多小时。直接计算耗时不到一秒钟。更重要的是,点估计值(斯维曼为34.75,未调整为34.77)以及标准误差(0.0039和0.0037)非常接近大型复杂测量数据集的R方法?,r,survey,large-data,R,Survey,Large Data,我不是一名调查方法学家或人口学家,但我是托马斯·卢姆利R调查包的狂热粉丝。我一直在处理一个相对较大的复杂调查数据集,即医疗成本和利用项目(HCUP)国家急诊科样本()。正如医疗保健研究和质量机构所描述的,这是“来自30个州947家医院的急诊室就诊出院数据,约占美国医院急诊室分层样本的20%” 2006年至2012年的完整数据集包括198102435个观测值。我将数据分为40073358个创伤相关出院数据,包含66个变量。在这些数据上运行即使是简单的调查程序也要花费非常长的时间。我曾经尝试过使用R
# 1a. svymean in memory
svydes<- svydesign(
id = ~KEY_ED ,
strata = ~interaction(NEDS_STRATUM , YEAR), note YEAR interaction
weights = ~DISCWT ,
nest = TRUE,
data = inj
)
system.time(meanAGE<-svymean(~age, svydes, na.rm=T))
user system elapsed
3082.131 143.628 3208.822
> meanAGE
mean SE
age 34.746 0.0039
# 1b. svymean out of memory
db_design <-
svydesign(
weight = ~discwt , weight variable column
nest = TRUE , whether or not psus are nested within strata
strata = ~interaction(neds_stratum , yr) , stratification variable column
id = ~key_ed ,
data = "nedsinj0612" , table name within the monet database
dbtype = "MonetDBLite" ,
dbname = "~/HCUP/HCUP NEDS/monet" folder location
)
system.time(meanAGE<-svymean(~age, db_design, na.rm=T))
user system elapsed
11749.302 549.609 12224.233
Warning message:
'isIdCurrent' is deprecated.
Use 'dbIsValid' instead.
See help("Deprecated")
mean SE
age 34.746 0.0039
# 1.c unadjusted mean and s.e.
system.time(print(mean(inj$AGE, na.rm=T)))
[1] 34.77108
user system elapsed
0.407 0.249 0.653
sterr <- function(x) sd(x, na.rm=T)/sqrt(length(x)) # write little function for s.e.
system.time(print(sterr(inj$AGE)))
[1] 0.003706483
user system elapsed
0.257 0.139 0.394
#1a。记忆中的斯维曼
svydes对于大型数据集,线性化设计(svydesign
)比复制设计(svrepdesign
)慢得多。查看survey::as.svrepdesign
中的权重函数,并使用其中一个函数直接进行复制设计。不能对此任务使用线性化。您甚至可能不使用as.svrepdesign
,而是使用其中的函数
例如,将cluster=
、strata=
和fpc=
直接用于复制加权设计,请参阅
注意:您也可以在此处查看每分钟的速度测试(每个事件都有时间戳)
还要注意,replicates=
参数对设计运行的速度几乎是100%。因此,也许可以做两个设计,一个是系数设计(只需几个重复),另一个是SEs设计(尽可能多)。以交互方式运行系数,优化白天需要的数字,然后让需要SE计算的更大过程在夜间运行一段时间,但在这一点上结束循环。正如Lumley博士在最近的评论中提到的,Charco Hui将实验性的sqlsurvey软件包重新命名为“svydb”,我发现它是在R中处理非常大的调查数据集的一个很好的工具。请参阅此处的相关帖子:您尝试过了吗?感谢您的回复,Severin。对已经尝试过bigmemory、ff、data.table。您进行了交换吗?内存中对象的大小是多少?您提供了计时,但没有提供内存信息。对于data.tables,只需键入tables()
hi@severinpapadeux没有一个与library(survey)
兼容,这就是为什么它的作者尝试使用而不是使用我们在数据库中的调查分析中考虑的方法之一,并且它只值得为非常大的数据集()进行实施工作,所以了解这样的例子很有用谢谢Anthony。这是一个很好的建议。他不知道这种可能的方法。将尝试。像svydesign(id=~1,data=yourdata,weights=~yourweights)
这样不正确的设计仍然可以相对快速地给出正确的系数,并且还可以让您测试代码,以便在夜间运行
# 2.a svyby .. svymean
system.time(AGEbyYear<-svyby(~age, ~yr, db_design, svymean, na.rm=T, vartype = c( 'ci' , 'se' )))
user system elapsed
4600.050 376.661 6594.196
yr age se ci_l ci_u
2006 2006 33.83112 0.009939669 33.81163 33.85060
2007 2007 34.07261 0.010055909 34.05290 34.09232
2008 2008 34.57061 0.009968646 34.55107 34.59014
2009 2009 34.87537 0.010577461 34.85464 34.89610
2010 2010 35.31072 0.010465413 35.29021 35.33124
2011 2011 35.33135 0.010312395 35.31114 35.35157
2012 2012 35.30092 0.010313871 35.28071 35.32114
# 2.b tapply ... mean
system.time(print(tapply(inj$AGE, inj$YEAR, mean, na.rm=T)))
2006 2007 2008 2009 2010 2011 2012
33.86900 34.08656 34.60711 34.81538 35.27819 35.36932 35.38931
user system elapsed
3.388 1.166 4.529
system.time(print(tapply(inj$AGE, inj$YEAR, sterr)))
2006 2007 2008 2009 2010 2011 2012
0.009577755 0.009620235 0.009565588 0.009936695 0.009906659 0.010148218 0.009880995
user system elapsed
3.237 0.990 4.186
# 3.a svytotal
system.time(print(svytotal(~adj_cost, svydes, na.rm=T)))
total SE
adj_cost 9.975e+10 26685092
user system elapsed
10005.837 610.701 10577.755
# 3.b "direct" calculation
SurvTot<-function(x){
N <- sum(1/svydes$prob)
m <- mean(x, na.rm = T)
total <- m * N
return(total)
}
> system.time(print(SurvTot(inj$adj_cost)))
[1] 1.18511e+11
user system elapsed
0.735 0.311 0.989