Я пытаюсь создать функцию, которая отображает ответ выбранной переменной, когда хотя бы одна из переменных является категориальной.
Когда все ваши переменные являются числовыми, я обычно сохраняювсе остальные переменные имеют среднее значение, а затем изменяют целевую переменную, вот пример с mtcars:
library(tidyverse)
data("mtcars")
Сначала я изменю переменную am, чтобы она была категориальной переменной
mt2 <- mtcars %>% mutate(am = case_when(am == 0 ~ "Automatic", am == 1 ~ "Manual")) %>% select(mpg, am, wt, hp)
Тогда я покажу, что работает для меня
Это работает
для модели с только числовыми переменными, у меня нет проблем, например, с этой моделью
model1 <- lm(mpg ~ wt + hp, data = mt2)
Я могу использовать эту функцию, которую я сделал
Plot_Response <- function(Model, variable){
# generate a data.frame with all the means copied 20 times
Means <- Model$model %>% summarise_all(mean)
Means <- Means[rep(seq_len(nrow(Means)), each = 20),]
# Then generate a vector with a sequence from the min value to the max value of the variable
MinMax <- Model$model %>% select(variable) %>% pull(variable) %>% range()
MinMax <- seq(from = MinMax[1], to = MinMax[2], along.with = Means[,1])
# Replace the column of the variable that we need to plot the response plot of by this sequence
Means[colnames(Means)== as.character(variable)] <- MinMax
## Predict the fit and SE
Means$Predicted <-predict(Model, newdata = Means)
Means$SE <- predict(Model, newdata = Means, se.fit = T)$se.fit
## Plot the response
result <- ggplot(Means, aes_string(x= variable, y = "Predicted")) + geom_ribbon(aes(ymax= Predicted + SE, ymin = Predicted - SE), fill = "grey") + geom_line() + theme_classic()
return(result)
}
Если я использую эту функцию с моделью выше, я могу сделать этот график
Plot_Response(Model = model1, variable = "wt")
вот когда я попадаю в беду
Конечно, если я попробую это, когда есть категориальная переменная, у меня возникнут проблемы, так как, если она пытается получить среднее значение категориальной величины дляфрейм данных это не удается:
model2 <- lm(mpg ~ wt + hp + am, data = mt2)
Если я попытаюсь
Plot_Response(Model = model2, variable = "wt")
я получу:
Error: variable 'am' was fitted with type "character" but type "numeric" was supplied
Итак, я попробовал следующее:
Plot_Response2 <- function(Model, variable){
# First I get the names of all categorical variables
Categoricals <- Model$model %>% mutate_if(is.factor, as.character) %>% select_if(is.character) %>% colnames()
# generate a data.frame with all the means copied 20 times for each level
Means <- Model$model %>% mutate_if(is.factor, as.character) %>% mutate_if(is.numeric, mean) %>% group_by_if(is.character) %>% summarise_if(is.numeric, mean) %>% ungroup()
Means <- Means[rep(seq_len(nrow(Means)), each = 20),] %>% arrange_if(is.character) %>% group_split(substitute(variable))
return(Means)
}
Моя идея заключается в том, чтоФункция определит, какие переменные являются категориальными. Если я запрашиваю ответ числовой переменной, я получаю ответ этой переменной на каждом уровне категориальной переменной. Моя проблема до сих пор заключается в том, что когда я делаю group_split, он не распознает переменную
Что яожидайте:
Пример 1
Я ожидаю, что если я сделаю:
Plot_Response2(Model = model2, variable = "wt")
Я получу:
Я сделал для этого следующий код, но не смог добавить его в функцию:
Means <- model2$model %>% mutate_if(is.factor, as.character) %>% mutate_if(is.numeric, mean) %>% group_by_if(is.character) %>% summarise_if(is.numeric, mean) %>% ungroup()
Means <- Means[rep(seq_len(nrow(Means)), each = 20),] %>% arrange_if(is.character) %>% group_split(am)
MinMax <- model2$model %>% select(wt) %>% pull(wt) %>% range()
MinMax <- seq(from = MinMax[1], to = MinMax[2], length.out = 20)
for(i in 1:length(Means)){
Means[[i]]$wt <- MinMax
}
Means <- bind_rows(Means)
Means$Predicted <- predict(model2, Means)
Means$SE <- predict(model2, Means, se.fit = T)$se.fit
ggplot(Means, aes(x = wt, y = Predicted)) + geom_ribbon(aes(ymax = Predicted + SE, ymin = Predicted - SE, fill = am), alpha = 0.5) + geom_line(aes(color = am)) + theme_classic()
Пример 1
Я ожидаю, что если яdo:
Plot_Response2(Model = model2, variable = "am")
Я получу:
Опять же для этого я использовал этот код, который я не могуПохоже, что вместе с функцией 2
Means <- model2$model %>% mutate_if(is.factor, as.character) %>% mutate_if(is.numeric, mean) %>% group_by_if(is.character) %>% summarise_if(is.numeric, mean) %>% ungroup()
Means <- Means[rep(seq_len(nrow(Means)), each = 20),] %>% arrange_if(is.character) %>% group_split(am)
Means <- bind_rows(Means)
Means$Predicted <- predict(model2, Means)
Means$SE <- predict(model2, Means, se.fit = T)$se.fit
ggplot(Means, aes(x = am, y = Predicted)) + geom_errorbar(aes(ymin = Predicted - SE, ymax = Predicted + SE)) + geom_point() + theme_classic()
Любая помощь или предложение очень ценится, и любые необходимые разъяснения я отвечу.
Спасибо