使用 (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.grid
或 outer
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")
我有一个数据框,其中 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.grid
或 outer
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")