使用 (m)apply 将多个变量迭代地替换为一个函数?

using (m)apply to substitute more than 1 variable iteratively into a function?

我有一个数据框,其中 10 列用于不同的人口统计变量,38 列用于回答调查参与者提出的 38 个不同问题。制作一个复制组织的较小数据框:

ID <- c("a", "b", "c", "d", "e")
Gender <- c("Male", "Female", "Male", "Female", "Male")
Pain_Level <- c("High", "Moderate", "Low", "High", "Moderate")
Q1 <- c("Agree", "Strongly Agree", "Disagree", "Neutral", "Agree")
Q2 <- c("Disagree", "Strongly Agree", "Disagree", "Neutral", "Agree")
Q3 <- c("Agree", "Strongly Disagree", "Disagree", "Neutral", "Agree")

df<- data.frame(ID, Gender, Pain_Level, Q1, Q2, Q3)

我想将函数 xtabs 应用于数据框的每个问题列 (Q1-38),以获得每个问题的列联表,每个人口统计变量。我能够创建一个可以针对所有 38 个问题执行此操作的函数,但一次只能针对一个人口统计使用:

varlist <- names(select(df, starts_with("Q")))       
xtabs <- lapply(varlist, function(x) {               
  xtabs(substitute(~Pain_Level + i, list(i = as.name(x))), data = df)    
}                                                                              
)  

基本上,我希望能够在上面的等式中迭代地替换疼痛水平,性别,然后是我所有其他人口统计变量,所以我最终得到一个列联表列表:每个 38 个表每个人口统计,针对每个问题。

我试过摆弄 mapply,比如:

demolist <- names(select(df,"Pain_Level", "Gender"))

myfun <- function(x,y) {
  xtabs(substitute(~j + i, list(i = as.name(y), j=as.name(x))), data=df)
        }

attempt1 <- mapply(myfun, demolist, MoreArgs = list(varlist))

attempt2 <- mapply(myfun, demolist, varlist)

但最终发生的是……它不会遍历人口统计/问题的所有组合。所以我觉得我需要以某种方式使用 lapply 但也没有取得太大的成功。

我觉得我遗漏了一些东西——比如从根本上错误的方式来解决这个问题……但我对编程还很陌生,所以我很难排除故障/思考替代方案。非常感谢任何帮助。

Map/mapply 循环遍历相应的元素(为此,它需要参数具有相同的长度,否则它可以在有单个元素时进行回收)并且不执行所有组合。如果我们需要所有组合,则需要 expand.gridouter

c(outer(demolist, varlist, Vectorize(myfun)))

或使用tidyverse

library(dplyr)
library(tidyr)
library(purrr)
crossing(demolist, varlist) %>% 
           pmap(~ myfun(..1, ..2))
#[[1]]
#        Q1
#Gender   Agree Disagree Neutral Strongly Agree
#  Female     0        0       1              1
#  Male       2        1       0              0

#[[2]]
#        Q2
#Gender   Agree Disagree Neutral Strongly Agree
#  Female     0        0       1              1
#  Male       1        2       0              0

#[[3]]
#        Q3
#Gender   Agree Disagree Neutral Strongly Disagree
#  Female     0        0       1                 1
#  Male       2        1       0                 0

#[[4]]
#          Q1
#Pain_Level Agree Disagree Neutral Strongly Agree
#  High         1        0       1              0
#  Low          0        1       0              0
# Moderate     1        0       0              1

#[[5]]
#          Q2
#Pain_Level Agree Disagree Neutral Strongly Agree
#  High         0        1       1              0
#  Low          0        1       0              0
#  Moderate     1        0       0              1

#[[6]]
#          Q3
#Pain_Level Agree Disagree Neutral Strongly Disagree
#  High         1        0       1                 0
#  Low          0        1       0                 0
#  Moderate     1        0       0                 1

哪里

demolist <- c("Pain_Level", "Gender")