Организация переменных фактора До GLM вписывается в R - PullRequest
1 голос
/ 08 марта 2020

Я много работаю с GLM в R, на довольно больших наборах данных (часто включая десятки переменных в подгонке модели). Для того, чтобы иметь возможность производить графический вывод определенного вида после того, как я подстроил модель, я считаю полезным «подготовить» любую переменную, которую я намерен использовать как фактор (те, чьи имена начинаются с f_ ниже) до того, как модель подойдет. Под этим я подразумеваю:

(i), так как я переупорядочиваю каждый фактор перед установкой GLM таким образом, чтобы опорный уровень был равен уровню с наибольшим весом, я хочу сохранить порядок уровней до relevel() command;

(ii), чтобы позже выделить контрольный уровень на графиках, я хотел бы сохранить его запись в отдельной переменной.

Я собрал пример из этот подход использует встроенный mtcars набор данных.

В настоящее время у меня есть этот код:

library(dplyr)

data(mtcars)

# tidy up and make easier to read

df <- mtcars # built in data set

# let's make it a bit easier to follow

df <- df %>%
  select(mpg,
         f_cylinders = cyl,
         c_displacement = disp,
         c_hp = hp,
         c_final_drive_ratio = drat,
         c_weight = wt,
         c_qtr_mile_time = qsec,
         f_v_or_straight = vs,
         f_transmission = am,
         f_gears = gear,
         f_num_carbs = carb)

df$f_v_or_straight <- ifelse(df$f_v_or_straight == 0, "V", "Straight")
df$f_transmission <- ifelse(df$f_transmission == 0, "Automatic", "Manual")

df$glm_weight <- 1

# organise factors - levels, reference level, weights

my_list <- list()

df$f_cylinders <- as.factor(df$f_cylinders)
my_list$f_cylinders_levels <- levels(df$f_cylinders) 
my_list$f_cylinders_weights <- df %>% group_by(f_cylinders) %>% summarise(glm_weight = sum(glm_weight)) %>% ungroup() %>% pull(glm_weight)
my_list$f_cylinders_ref <- "8"
df$f_cylinders <- df$f_cylinders %>% relevel(ref = my_list$f_cylinders_ref)

df$f_v_or_straight <- as.factor(df$f_v_or_straight)
my_list$f_v_or_straight_levels <- levels(df$f_v_or_straight) 
my_list$f_v_or_straight_weights <- df %>% group_by(f_v_or_straight) %>% summarise(glm_weight = sum(glm_weight)) %>% ungroup() %>% pull(glm_weight)
my_list$f_v_or_straight_ref <- "V"
df$f_v_or_straight <- df$f_v_or_straight %>% relevel(ref = my_list$f_v_or_straight_ref)

df$f_transmission <- as.factor(df$f_transmission)
my_list$f_transmission_levels <- levels(df$f_transmission) 
my_list$f_transmission_weights <- df %>% group_by(f_transmission) %>% summarise(glm_weight = sum(glm_weight)) %>% ungroup() %>% pull(glm_weight)
my_list$f_transmission_ref <- "Automatic"
df$f_transmission <- df$f_transmission %>% relevel(ref = my_list$f_transmission_ref)

df$f_gears <- as.factor(df$f_gears)
my_list$f_gears_levels <- levels(df$f_gears) 
my_list$f_gears_weights <- df %>% group_by(f_gears) %>% summarise(glm_weight = sum(glm_weight)) %>% ungroup() %>% pull(glm_weight)
my_list$f_gears_ref <- "3"
df$f_gears <- df$f_gears %>% relevel(ref = my_list$f_gears_ref)

df$f_num_carbs <- as.factor(df$f_num_carbs)
my_list$f_num_carbs_levels <- levels(df$f_num_carbs) 
my_list$f_num_carbs_weights <- df %>% group_by(f_num_carbs) %>% summarise(glm_weight = sum(glm_weight)) %>% ungroup() %>% pull(glm_weight)
my_list$f_num_carbs_ref <- "4"
df$f_num_carbs <- df$f_num_carbs %>% relevel(ref = my_list$f_num_carbs_ref)

Этот код работает нормально, но ... в реальном мире использует я имею дело с десятками факторных переменных, а не только 5 выше. Так что, если у меня есть 50 факторных переменных, я делаю то же самое 50 раз. Я хотел бы объединить эту подготовку в один вызов функции, по сути говоря:

Для каждого поля, имя которого начинается с f_ (ie выглядит как f_xxx):

  1. превратить его из chr / int / что угодно в коэффициент f_xxx;

  2. отработать веса f_xxx_weights

  3. определить опорный уровень f_xxx_ref (не знаете, что делать, если для отведения есть ie);

  4. сохранить уровни фактора в f_xxx_levels;

  5. переставить уровни факторов так, чтобы f_xxx_ref был первым в списке.

Я спрашиваю здесь довольно много ... но что-нибудь, что подтолкнет меня вперед, будет с благодарностью получено.

Спасибо.

1 Ответ

0 голосов
/ 09 марта 2020

Рассмотрите возможность обобщения вашего relevel процесса в определяемом пользователем методе, а затем сопоставьте столбцы f_, вызывающие ваш процесс, используя purrr::map_df (чтобы соответствовать tidy):

Данные

library(dplyr)
library(purrr)

df <- mtcars %>%
  select(mpg,
         f_cylinders = cyl,
         c_displacement = disp,
         c_hp = hp,
         c_final_drive_ratio = drat,
         c_weight = wt,
         c_qtr_mile_time = qsec,
         f_v_or_straight = vs,
         f_transmission = am,
         f_gears = gear,
         f_num_carbs = carb) %>%
  mutate(f_v_or_straight = ifelse(f_v_or_straight == 0, 
                                  "V", 
                                  "Straight"),
         f_transmission = ifelse(f_transmission == 0, 
                                 "Automatic", 
                                 "Manual"),
         glm_weight = 1)

rlevel Процесс (с использованием table частот)

proc_rlevel <- function(col) {
    agg <- df %>% group_by_at(col) %>% 
      summarise(glm_weight = sum(glm_weight)) %>%
      arrange(desc(glm_weight))

    f_ref <- df[[col]] %>% 
      as.character() %>%
      as.factor() %>%
      relevel(ref = paste(agg[[col]][1]))

    return(f_ref)
}

# REPLACING ORIGINAL f_cols WITH TWO WAY PIPES
df[grep("f_", names(df))] %<>% 
  names() %>%
  setNames(identity(.)) %>%
  map_df(proc_rlevel)

Просмотр изменений

# ORIGINAL LEVELS
df %>% 
  select(starts_with("f_")) %>%
  map_df(as.factor) %>%
  map(levels)
# $f_cylinders
# [1] "4" "6" "8"
# 
# $f_v_or_straight
# [1] "Straight" "V"       
# 
# $f_transmission
# [1] "Automatic" "Manual"   
# 
# $f_gears
# [1] "3" "4" "5"
# 
# $f_num_carbs
# [1] "1" "2" "3" "4" "6" "8"


# ADJUSTED LEVELS
df %>% 
  select(starts_with("f_")) %>%
  map_df(as.factor) %>%
  map(levels)
# $f_cylinders
# [1] "8" "4" "6"
# 
# $f_v_or_straight
# [1] "V"        "Straight"
# 
# $f_transmission
# [1] "Automatic" "Manual"   
# 
# $f_gears
# [1] "3" "4" "5"
# 
# $f_num_carbs
# [1] "2" "1" "3" "4" "6" "8"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...