#r
Вопрос:
Я создал мультиномиальную логистическую регрессию ниже:
Я сохранил коэффициенты, стандартные ошибки, статистику z и значения p в разных переменных. Я пытаюсь создать фрейм данных для хранения всей этой информации.
library(foreign)
library(nnet)
ml <- read.dta("https://stats.idre.ucla.edu/stat/data/hsbdemo.dta")
ml$prog2 <- relevel(ml$prog, ref = "academic")
test <- multinom(prog2 ~ 1, data = ml)
coeff <- summary(test)$coefficients
std.errs <- summary(test)$standard.errors
# calculate z-statistics of coefficients
z_stats <- summary(test)$coefficients/
summary(test)$standard.errors
# convert to p-values
p_values <- (1 - pnorm(abs(z_stats)))*2
> std.errs
(Intercept)
general 0.1781742
vocation 0.1718249
> coeff
(Intercept)
general -0.8472980
vocation -0.7419374
> p_values
(Intercept)
general 1.980067e-06
vocation 1.574605e-05
> z_stats
(Intercept)
general -4.755448
vocation -4.317984
Это мой ожидаемый результат. Как я могу создать этот фрейм данных из созданных мной переменных? У меня возникли проблемы с использованием столбца (Перехват) для создания general_intercept. Я хочу, чтобы это было сделано через dplyr.
feature coefficient std.error pval z.stat
general_intercept -0.8472980 0.1781742 1.980067e-06 -4.755448
vocation_intercept -0.7419374 0.1718249 1.574605e-05 -4.317984
Мне нужно, чтобы он был динамичным и по количеству переменных.
Например, если бы я запустил эту мультиномиальную логистическую регрессию
multinom(prog ~ ses write, data=mdata)
Я бы получил эту структуру таблицы:
feature coefficient std.error p.val z_stat
academic_intercept
academic_sesmiddle
academic_seshigh
vocation_intercept
vocation_sesmiddle
vocation_seshigh
Ответ №1:
df <- cbind(coeff, std.errs, p_values, z_stats)
colnames(df) <- c("coefficient", "SE", "p_val", "z_stat")
coefficient SE p_val z_stat
general -0.8472980 0.1781742 1.980067e-06 -4.755448
vocation -0.7419374 0.1718249 1.574605e-05 -4.317984
Если вы хотите переименовать индекс строки:
rownames(df) <- c("general_intercept", "vocation_intercept")
coefficient SE p_val z_stat
general_intercept -0.8472980 0.1781742 1.980067e-06 -4.755448
vocation_intercept -0.7419374 0.1718249 1.574605e-05 -4.317984
Чтобы динамически изменять имена строк, вы можете:
rownames(df) <- paste(rownames(df), tolower(gsub("[^a-zA-Z]", "", colnames(coeff))), sep = "_")
coefficient SE p_val z_stat
general_intercept -0.8472980 0.1781742 1.980067e-06 -4.755448
vocation_intercept -0.7419374 0.1718249 1.574605e-05 -4.317984
ПРАВКА: С учетом новых требований мы можем написать функцию, которая может это сделать. Это немного монолитно и, вероятно, может быть разделено на несколько функций. Обратите внимание, что для того, чтобы это сработало, объекты должны быть переданы в виде именованного списка. Эта функция написана для работы с тем, как вы уже определили различные статистические данные, например. coeff <- summary(test)$coefficients
. В дополнение к пакетам, которые вы используете, требуется reshape2
и dplyr
.
create_summary = function(stats) {
if (!is.list(stats)) {
stop("Argument must be a named list")
}
df = NULL
for (i in 1:length(stats)) {
stat = as.data.frame(stats[[i]])
stat$feature = rownames(stat)
stat = stat %>%
melt(id.vars = c("feature")) %>%
mutate(feature = paste(feature,
tolower(gsub(pattern = "[^a-zA-Z]",
replacement = "",
variable)),
sep = "_")) %>%
select(feature, value)
colnames(stat) = c("feature", names(stats)[i])
if (is.null(df)) {
df = stat
} else {
df = merge(df, stat, by = "feature")
}
}
return(df)
}
С исходной моделью test <- multinom(prog2 ~ 1, data=ml)
:
create_summary((list(coefficients = coeff,
se = std.errs,
p_val = p_values,
z_stat = z_stats)))
feature coefficients se p_val z_stat
1 general_intercept -0.8472980 0.1781742 1.980067e-06 -4.755448
2 vocation_intercept -0.7419374 0.1718249 1.574605e-05 -4.317984
С вашей второй моделью test <- multinom(prog ~ ses write, data=ml)
:
feature coefficients se p_val z_stat
1 academic_intercept -2.85197258 1.16643741 0.01448407 -2.4450284
2 academic_seshigh 1.16282574 0.51422150 0.02373868 2.2613324
3 academic_sesmiddle 0.53329140 0.44373191 0.22942845 1.2018324
4 academic_write 0.05792480 0.02141092 0.00682251 2.7053858
5 vocation_intercept 2.36609732 1.17425127 0.04390634 2.0149838
6 vocation_seshigh 0.18021764 0.64845085 0.78107356 0.2779203
7 vocation_sesmiddle 0.82463840 0.49012366 0.09246981 1.6825109
8 vocation_write -0.05567514 0.02333135 0.01701977 -2.3862803
Вы можете продолжать добавлять функции, и сводка будет увеличиваться в объеме.
Комментарии:
1. Спасибо вам за это решение. У вас есть один, где используется dplyr, а также динамический, где пользователю не нужно указывать имена строк вручную?
2. Когда вы говорите динамически, вы просто хотите
_intercept
добавить в конец имя строки, каково бы оно ни было? Если нет, то откуда берутся имена строк?3. Это независимо от того, как называется столбец. В этом случае (Перехват) является единственным столбцом, так как я подгоняю модель только для перехвата. Если бы я соответствовал другим функциям, было бы больше столбцов функций.
4. Эй, я только что обновил свой вопрос. Это работает, но не зависит от количества подходящих функций. Например, если бы я добавил в модель другую переменную. имена столбцов(df) прерываются.
5. @Эйзен Ах, кажется, я теперь понимаю, что вы ищете. См.раздел правка.