调查包中 svydesign 中的动态变量名称

Dynamic variable names in svydesign from survey package

我想向使用调查包创建的 survey.design 添加列,可以按以下方式完成:

library(survey)
data(api)

dclus1 <- svydesign(id = ~dnum, weights = ~pw, data = apiclus1, fpc = ~fpc)
dclus2 <- transform(dclus1, 
                    api00_b = api00 + 1)

svymean(~ api00, design = dclus2)
#>         mean     SE
#> api00 644.17 23.542
svymean(~ api00_b, design = dclus2)
#>           mean     SE
#> api00_b 645.17 23.542

对于更复杂的任务,我需要从外部向量动态创建这些变量名。以下会产生错误,但我认为提供了我想要实现的目标的说明:

vars <- c("api00_a", "api00_b")
dclus2 <- transform(dclus1, 
                    vars[[2]] = api00 + 1)

如何实现新列的动态名称?

以下是使用 purrr 的可能解决方案:

library(purrr)

vars <- c("api00_a", "api00_b")

transform_func <- function(data, vars) {
  transform(data, vars = api00 + 1)
}

map(vars, ~transform_func(dclus1, .))

这给了我们以下列表:

[[1]]
1 - level Cluster Sampling design
With (15) clusters.
update(`_data`, ...)

[[2]]
1 - level Cluster Sampling design
With (15) clusters.
update(`_data`, ...)

我认为您不能在 R 中等号的左侧使用这样的向量。您不必使用 transform,它调用 survey:::update.survey.design , 尽管。您可以直接添加新变量:

dclus2 <- dclus1
dclus2$variables[ ,vars[[1]]] <- dclus2$variables[,"api00"] + 1

这与在转换为 survey.design 对象之前创建新变量相同,只要您不使用任何调查函数来创建新变量。仅使用安东尼的评论:

apiclus2 <- apiclus1
apiclus2[ , vars[[1]]] <- apiclus2[ , "api00" ] + 1
dclus_prep_2 <- svydesign(id = ~dnum, weights = ~pw, data = apiclus2, fpc = ~fpc)

您可能更喜欢使用 srvyr,它允许您使用 dplyr!!:=:

进行编程
library(srvyr)
dclus_srvyr_1 <- as_survey_design(.data = apiclus1, 
                                ids = dnum, 
                                weights = pw, 
                                fpc = fpc)
dclus_srvyr_2 <- mutate(dclus_srvyr_1, 
                    !!vars[[1]] := api00 + 1)

所有版本结果相同:

lapply(list(dclus2, dclus_prep_2, dclus_srvyr_2), 
  function(design) svymean(~api00_a, design=design))
[[1]]
          mean     SE
api00_a 645.17 23.542

[[2]]
          mean     SE
api00_a 645.17 23.542

[[3]]
          mean     SE
api00_a 645.17 23.542

您可以使用 bquote 执行此操作。例如

vars <- c("api00_plus_1", "api00_plus_2")
exprs<-list(quote(api00+1),quote(api00+2))
names(exprs)<-vars
bquote(update(dclus1,..(exprs)), splice=TRUE)

eval(bquote(update(dclus1,..(exprs)), splice=TRUE))

这是 survey 包中的另一个块,它将公式中提到的任何字符串变量转换为因子

strings_to_factors<-function(formula,  design){
    allv<-intersect(all.vars(formula), colnames(design))
    vclass<-sapply(model.frame(design)[,allv,drop=FALSE], class)
    if (!any(vclass=="character")) return(design)
    vfix<-names(vclass)[vclass=="character"]
    l<-as.list(vfix)
    names(l)<-vfix
    fl<-lapply(l, function(li) bquote(factor(.(as.name(li)))))
    expr<-bquote(update(design, ..(fl)), splice=TRUE)
    eval(expr)
}