Вывод многомерной сводки в кадр данных в R

#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. @Эйзен Ах, кажется, я теперь понимаю, что вы ищете. См.раздел правка.