传递列名以在函数内应用时出现问题
Problem passing column name to sapply within a function
我需要为多个 logit 模型计算很多预测概率,我正在尝试编写一个函数来加快该过程。但是,我无法使我的功能正常工作。问题似乎出在下面代码的“iv=x”部分。我不确定如何在那里正确传递列名。
pp <- function(iv, model, df) {
lev <- levels(df[[iv]])
l.prob <- sapply(lev, FUN=function(x){
mean(predict(model, type = "response",
newdata = mutate(df, iv = x)), na.rm=TRUE)
})
l.prob
}
test <- pp(iv="myvar", model=model1, df=mydf)
test
下面是一些示例数据,显示了该函数如何不工作:
set.seed(123123)
df=data.frame(y=sample(c(0,1), replace=TRUE, size=100), x1=as.factor(rep(c("value1", "value2"), 50)), x2=rnorm(100, mean=50, sd=10))
logit1 <- glm(y ~ x1+x2, data = df, family=binomial(link="logit"))
summary(logit1)
#what the predicted probabilities should be (0.4173400, 0.4625565)
lev <- levels(df$x1)
pp <- sapply(lev, FUN=function(x){
mean(predict(logit1, type = "response",
newdata = mutate(df, x1 = x)), na.rm=TRUE)
})
pp
#now running function (produces probabilities 0.44 and 0.44)
pp <- function(iv, model, df) {
lev <- levels(df[[iv]])
l.prob <- sapply(lev, FUN=function(x){
mean(predict(model, type = "response",
newdata = mutate(df, iv = x)), na.rm=TRUE)
})
l.prob
}
test <- pp(iv="x1", model=logit1, df=df)
test
你只需要模仿原文中的赋值pp
:x1 = x
。现在您正尝试在 sapply
中使用 iv
,但在 sapply
中您的函数仅引用 x
.
进行此更新会重现 pp
与 test
的结果:
library(dplyr)
set.seed(1L)
# hard-coded df$x1
lev <- levels(df$x1)
pp <- sapply(lev, FUN=function(x){
mean(predict(logit1, type = "response",
newdata = mutate(df, x1 = x)), na.rm=TRUE)
})
pp
value1 value2
0.4799503 0.5400409
# 'x1' passed in as :iv: arg
pp <- function(iv, model, df) {
lev <- levels(df[[iv]])
l.prob <- sapply(lev, FUN=function(x){
mean(predict(model, type = "response",
newdata = mutate(df, x1 = x)), na.rm=TRUE)
})
l.prob
}
test <- pp(iv="x1", model=logit1, df=df)
test
value1 value2
0.4799503 0.5400409
作为替代方案,您可以不加引号直接将 x1
传递给 pp()
,然后使用 {{ }}
(curly curly notation) 计算 iv
在 df
:
pp <- function(iv, model, df) {
lev <- levels(df %>% pull({{iv}})) # <-- use {{ }}
l.prob <- sapply(lev, FUN=function(x){
mean(predict(model, type = "response",
newdata = mutate(df, x1 = x)), na.rm=TRUE)
})
l.prob
}
test <- pp(iv=x1, model=logit1, df=df) # <-- x1 has no quotes
test
value1 value2
0.4799503 0.5400409
考虑在使用 [[
进行预测之前动态分配列并避免使用 mutate
(特别是如果它是 dplyr
中使用的唯一方法并且可以为您节省 library
调用).
pp <- function(iv, model, df) {
lev <- levels(df[[iv]])
l.prob <- sapply(lev, FUN=function(x){
df[[iv]] <- x
mean(predict(model, type = "response", newdata = df), na.rm=TRUE)
})
}
另一种基本 R 方法是添加具有临时名称的新列,然后使用动态参数重命名所有列。
l.prob <- sapply(lev, FUN=function(x){
mean(predict(model, type = "response",
newdata = setNames(transform(df, tmp = x), c(colnames(df), iv)),
na.rm=TRUE)
})
我需要为多个 logit 模型计算很多预测概率,我正在尝试编写一个函数来加快该过程。但是,我无法使我的功能正常工作。问题似乎出在下面代码的“iv=x”部分。我不确定如何在那里正确传递列名。
pp <- function(iv, model, df) {
lev <- levels(df[[iv]])
l.prob <- sapply(lev, FUN=function(x){
mean(predict(model, type = "response",
newdata = mutate(df, iv = x)), na.rm=TRUE)
})
l.prob
}
test <- pp(iv="myvar", model=model1, df=mydf)
test
下面是一些示例数据,显示了该函数如何不工作:
set.seed(123123)
df=data.frame(y=sample(c(0,1), replace=TRUE, size=100), x1=as.factor(rep(c("value1", "value2"), 50)), x2=rnorm(100, mean=50, sd=10))
logit1 <- glm(y ~ x1+x2, data = df, family=binomial(link="logit"))
summary(logit1)
#what the predicted probabilities should be (0.4173400, 0.4625565)
lev <- levels(df$x1)
pp <- sapply(lev, FUN=function(x){
mean(predict(logit1, type = "response",
newdata = mutate(df, x1 = x)), na.rm=TRUE)
})
pp
#now running function (produces probabilities 0.44 and 0.44)
pp <- function(iv, model, df) {
lev <- levels(df[[iv]])
l.prob <- sapply(lev, FUN=function(x){
mean(predict(model, type = "response",
newdata = mutate(df, iv = x)), na.rm=TRUE)
})
l.prob
}
test <- pp(iv="x1", model=logit1, df=df)
test
你只需要模仿原文中的赋值pp
:x1 = x
。现在您正尝试在 sapply
中使用 iv
,但在 sapply
中您的函数仅引用 x
.
进行此更新会重现 pp
与 test
的结果:
library(dplyr)
set.seed(1L)
# hard-coded df$x1
lev <- levels(df$x1)
pp <- sapply(lev, FUN=function(x){
mean(predict(logit1, type = "response",
newdata = mutate(df, x1 = x)), na.rm=TRUE)
})
pp
value1 value2
0.4799503 0.5400409
# 'x1' passed in as :iv: arg
pp <- function(iv, model, df) {
lev <- levels(df[[iv]])
l.prob <- sapply(lev, FUN=function(x){
mean(predict(model, type = "response",
newdata = mutate(df, x1 = x)), na.rm=TRUE)
})
l.prob
}
test <- pp(iv="x1", model=logit1, df=df)
test
value1 value2
0.4799503 0.5400409
作为替代方案,您可以不加引号直接将 x1
传递给 pp()
,然后使用 {{ }}
(curly curly notation) 计算 iv
在 df
:
pp <- function(iv, model, df) {
lev <- levels(df %>% pull({{iv}})) # <-- use {{ }}
l.prob <- sapply(lev, FUN=function(x){
mean(predict(model, type = "response",
newdata = mutate(df, x1 = x)), na.rm=TRUE)
})
l.prob
}
test <- pp(iv=x1, model=logit1, df=df) # <-- x1 has no quotes
test
value1 value2
0.4799503 0.5400409
考虑在使用 [[
进行预测之前动态分配列并避免使用 mutate
(特别是如果它是 dplyr
中使用的唯一方法并且可以为您节省 library
调用).
pp <- function(iv, model, df) {
lev <- levels(df[[iv]])
l.prob <- sapply(lev, FUN=function(x){
df[[iv]] <- x
mean(predict(model, type = "response", newdata = df), na.rm=TRUE)
})
}
另一种基本 R 方法是添加具有临时名称的新列,然后使用动态参数重命名所有列。
l.prob <- sapply(lev, FUN=function(x){
mean(predict(model, type = "response",
newdata = setNames(transform(df, tmp = x), c(colnames(df), iv)),
na.rm=TRUE)
})