调查包中 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)
}
我想向使用调查包创建的 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)
}