[英]How to make a loop over multiple columns with the svyby function of the survey package?
I have been trying many ways, but I am not getting to solve the problem.我一直在尝试很多方法,但我无法解决问题。 I found here , here and here , but I couldn't adapt them to my problem.我找到了 here , here和here ,但我无法使它们适应我的问题。
I would like to pass the combination of two string vectors where each element of 'pop' would be combined with each element of 'territ' and over a subset of the column “enroll” through a numeric vector (“enroll_lines”).我想传递两个字符串向量的组合,其中 'pop' 的每个元素将与 'territ' 的每个元素组合,并通过数字向量(“enroll_lines”)在列“enroll”的子集上。 So, there are three iterations inside the svyby function I want to do: two over a string vector and one iteration inside a subset numeric vector.因此,我想在 svyby function 中进行三次迭代:两次在字符串向量上进行,一次在子集数值向量内进行迭代。
I want a data frame with all the result combinations of the three vectors over the design object “dclus1”.我想要一个数据框,其中包含设计 object “dclus1” 中三个向量的所有结果组合。
Thank you in advance for your attention and effort.预先感谢您的关注和努力。
data(api)
df <- apiclus1
df$pais <- 0
df$pop_tot <- 1
pop <- c("pop_tot", "stype", "awards")
territ <- c("pais","cname", "dname")
enroll_lines = c(355, 455, 555)
dclus1<-svydesign(id=~dnum, weights=~pw, data=df, fpc=~fpc)
svyloop <- function(vv1, vv2, dsgn, xx) {
svyby( as.formula( paste0( "~" , vv1)) , by = as.formula( paste0( "~" , vv2)) , subset(dsgn, enroll < xx), svytotal , vartype = 'cv')
}
svyloop(pop, territ, dclus1, enroll_lines)
#Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : contrasts can be applied only to factors with 2 or more levels
sapply(dclus1, svyloop, pop, territ, enroll_lines)
#Even though keeping just columns with two or more leves, the column "enroll" is not found, as the message below returns:
#Error in subset.default(dsgn, enroll < xx) : object 'enroll' not found
The other way I've tried was to put an "i" of iteration in the function.我尝试过的另一种方法是在 function 中放置一个迭代的“i”。
jj <- 1:3
svyloop <- function(vv1, vv2,, xx, i) {
svyby( as.formula( paste0( "~" , vv1[i])) , by = as.formula( paste0( "~" , vv2[i])) , subset(dclus1, enroll < xx[i]), svytotal , vartype = 'cv')
}
svyloop(pop, territ, enroll_lines, jj)
sapply(dclus1, svyloop, pop, territ, enroll_lines)
#Error in `contrasts<-`(` tmp \`, value = contr.funs[1 + isOF[nn]]): contrasts can be applied only to factors with 2 or more levels #Error in `contrasts<-`(` tmp \`, value = contr.funs[1 + isOF[nn]]): contrasts can be applied only to factors with 2 or more levels
As an additional note to @Mathdragon's answer, I'd use bquote
rather than as.formula
for svyloop
作为对@Mathdragon 回答的补充说明,我会使用bquote
而不是as.formula
来表示svyloop
svyloop <- function(vv1, vv2, dsgn, xx) {
eval(bquote(svyby( as.formula( ~.(vv1) , by = ~.(vv2) , subset(.(dsgn), enroll < .(xx)), svytotal , vartype = 'cv')))
}
The first argument in sapply
is looped over and you don't want to iterate over your design dclus1
but over pop
, territ
and enroll_lines
. sapply
中的第一个参数是循环的,您不想遍历设计dclus1
而是遍历pop
、 territ
和enroll_lines
。 Your solution can not work, because you dont give a design object to your svytable
-function.您的解决方案无法工作,因为您没有为您的svytable
提供设计 object 。 You can use multiple sapply
s and your function works.您可以使用多个sapply
并且您的 function 可以正常工作。 Simple but unelegant solution:简单但不优雅的解决方案:
sapply(pop,
function(x) sapply(territ,
function(y) sapply(enroll_lines, function(z)
svyloop(x, y, dclus1, z),
simplify = F),
simplify = F),
simplify = F)
This way you get a nested list of your tables and can combine them in any way you like.通过这种方式,您可以获得表格的嵌套列表,并且可以以您喜欢的任何方式组合它们。
There are probably far more efficient solutions with mapply
but nested sapplys work, too.使用mapply
可能有更有效的解决方案,但嵌套的 sapplys 也可以工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.