¿Cómo acortar el código en la escoba mientras se ejecutan múltiples regresiones en R?

Estoy corriendo múltiples regresiones por diferentes grupos. Quiero automatizar las cosas un poco más. Traté de correr y salvar las regresiones modelo1, modelo2 y modelo3 inicialmente. Luego intenté acortar el código como el siguiente:

 temp <- df %>%
      group_by(group) %>%
      do(model1, model2, model3, data = .))) %>%   
      gather(model_name, model, -group) %>%                        
      unnest() 

Pero esto no funcionó. A continuación encontrará la versión larga que funciona. ¿Puede alguien guiarme sobre cómo hacerlo un poco más corto?

df <- tibble(
  a = rnorm(1000),
  b = rnorm(1000),
  c = rnorm(1000),
  d = rnorm(1000),
  group =sample.int(300,size=1000,replace=TRUE)-1)
)

df$group = as.factor(df$group)

temp1 <- df %>%
  group_by(group) %>%
  do(model2 = tidy(lm(a ~ b , data = .))) %>%   
  gather(model_name, model, -group) %>%                        
  unnest() 

temp2 <- df %>%
  group_by(group) %>%
  do(model2 = tidy(lm(a ~ c , data = .))) %>%   
  gather(model_name, model, -group) %>%                        
  unnest() 

temp3 <- df %>%
  group_by(group) %>%
  do(model3 = tidy(lm(a ~ d , data = .))) %>%   
  gather(model_name, model, -group) %>%                        
  unnest() 

Pregunta hecha hace 3 años, 4 meses, 29 días - Por nodenomad


3 Respuestas:

  • Esto podría funcionar, usando nest_by y map desde purrr.

    En lugar de group_by Pruebe usando nest_by ()dplyr versión 1.0.0) y ejecutar su modelo en cada fila de datos anidados. Uso nest_by creará una nueva columna de lista temporal data. Es similar al uso anterior nest y rowwise. El modelo también necesita estar en la lista.

    Uso map puede realizar modelos para cada variable independiente "b", "c", y "d". La variable independiente también se incluye como columna separada (también podría ser una etiqueta para el modelo particular).

    library(tidyverse)
    library(purrr)
    library(broom)
    
    df %>%
      nest_by(group) %>%
      mutate(model = list(map(c("b", "c", "d"), ~
                           cbind(independent = .x, 
                                 tidy(lm(formula(paste0("a ~ ", .x)), data = data)))))) %>%
      summarise(bind_rows(model))
    

    Producto

       group independent term        estimate std.error statistic p.value
                                      
     1 0     b           (Intercept)   0.0480   NaN       NaN     NaN    
     2 0     b           b             0.268    NaN       NaN     NaN    
     3 0     c           (Intercept)  -0.124    NaN       NaN     NaN    
     4 0     c           c            -0.447    NaN       NaN     NaN    
     5 0     d           (Intercept)  -0.107    NaN       NaN     NaN    
     6 0     d           d             0.377    NaN       NaN     NaN    
     7 1     b           (Intercept)   0.473      0.296     1.60    0.356
     8 1     b           b             0.383      0.261     1.47    0.380
     9 1     c           (Intercept)   0.547      0.544     1.01    0.498
    10 1     c           c            -0.183      0.798    -0.229   0.857
    

    Editar (12/19/20): En caso de que desee incluir modelos con múltiples covariados y términos de interacción, simplemente podría proporcionar la fórmula en la cadena.

    Por ejemplo, si quieres ejecutar 3 modelos por group:

    • efectos principales "b" y "c" y término de interacción "b*c"
    • efectos principales "c" y "d"
    • efectos principales "d"

    Podrías hacer lo siguiente:

    df %>%
      nest_by(group) %>%
      mutate(model = list(map(c("b + c + b*c", "c + d", "d"), ~
                           cbind(model = .x, 
                                 tidy(lm(formula(paste0("a ~ ", .x)), data = data)))))) %>%
      summarise(bind_rows(model))
    

    Producto

       group model       term        estimate std.error statistic  p.value
                                       
     1 0     b + c + b*c (Intercept)   0.718      0.281    2.56     0.0835
     2 0     b + c + b*c b             0.819      0.348    2.35     0.100 
     3 0     b + c + b*c c            -0.351      0.315   -1.11     0.346 
     4 0     b + c + b*c b:c           0.0444     0.461    0.0964   0.929 
     5 0     c + d       (Intercept)   0.614      0.409    1.50     0.208 
     6 0     c + d       c            -0.271      0.439   -0.618    0.570 
     7 0     c + d       d             0.182      0.487    0.374    0.727 
     8 0     d           (Intercept)   0.605      0.383    1.58     0.175 
     9 0     d           d             0.208      0.455    0.456    0.667 
    10 1     b + c + b*c (Intercept)   0.590    NaN      NaN      NaN     
    # … with 2,600 more rows
    

    O, si quieres, puedes enumerar las ecuaciones por completo y por separado así:

    my_models <- c(
      "a ~ b + c + b*c", 
      "a ~ c + d", 
      "a ~ d"
    )
    
    df %>%
      nest_by(group) %>%
      mutate(model = list(map(my_models, ~
                           cbind(model = .x, 
                                 tidy(lm(formula(.x), data = data)))))) %>%
      summarise(bind_rows(model))
    

    Producto

       group model           term        estimate std.error statistic  p.value
                                           
     1 0     a ~ b + c + b*c (Intercept)   0.718      0.281    2.56     0.0835
     2 0     a ~ b + c + b*c b             0.819      0.348    2.35     0.100 
     3 0     a ~ b + c + b*c c            -0.351      0.315   -1.11     0.346 
     4 0     a ~ b + c + b*c b:c           0.0444     0.461    0.0964   0.929 
     5 0     a ~ c + d       (Intercept)   0.614      0.409    1.50     0.208 
     6 0     a ~ c + d       c            -0.271      0.439   -0.618    0.570 
     7 0     a ~ c + d       d             0.182      0.487    0.374    0.727 
     8 0     a ~ d           (Intercept)   0.605      0.383    1.58     0.175 
     9 0     a ~ d           d             0.208      0.455    0.456    0.667 
    10 1     a ~ b + c + b*c (Intercept)   0.590    NaN      NaN      NaN     
    # … with 2,600 more rows
    

    Datos

    set.seed(123)
    
    df <- tibble(
      a = rnorm(1000),
      b = rnorm(1000),
      c = rnorm(1000),
      d = rnorm(1000),
      group =sample.int(300,size=1000,replace=TRUE)-1)
    )
    
    df$group = as.factor(df$group)
    

    Respondida el Dec 18, 2020 a las 14:27 - por pixelpioneer

    Votos positivos: 0 | Votos negativos: 0

  • Puedes simplificar y automatizar el proceso de ajustar múltiples modelos de regresión utilizando la función map del paquete purrr en R. Aquí tienes un ejemplo de cómo podrías hacerlo:

    R
    library(dplyr)
    library(tidyr)
    library(purrr)
    
    

    Crear una lista de las fórmulas de los modelos que quieres ajustar

    model_formulas <- list( b = as.formula("a ~ b"), c = as.formula("a ~ c"), d = as.formula("a ~ d") )

    Función para ajustar los modelos y extraer los coeficientes

    fit_model <- function(formula, data) { tidy(lm(formula, data = data)) }

    Ajustar los modelos para cada fórmula

    temp <- df %>% group_by(group) %>% nest() %>% mutate(models = map(model_formulas, ~fit_model(., data))) %>% unnest(models) %>% mutate(model_name = names(model_formulas))

    Ver los resultados

    print(temp)

    En este código, primero creamos una lista de fórmulas model_formulas que contienen las especificaciones de los modelos que deseas ajustar. Luego definimos la función fit_model que ajusta un modelo lineal para cada fórmula dada.

    Después, utilizando la función map de purrr, ajustamos los modelos para cada grupo en el conjunto de datos y extraemos los coeficientes de manera automatizada. Finalmente, unimos todos los resultados en un único dataframe temp que contiene la información de todos los modelos ajustados.

    Este enfoque te permite ajustar múltiples modelos de manera más eficiente y trabajar con el resultado de una forma más automatizada.

    Respondida el Dec 19, 2020 a las 14:24 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Puedes utilizar la función map() del paquete purrr para simplificar el código y ejecutar múltiples regresiones en diferentes grupos de manera automatizada. Aquí tienes cómo hacerlo:

    r
    library(tidyverse)
    library(purrr)
    
    

    Crea los nombres de los modelos

    model_names <- c("model1", "model2", "model3")

    Crea una función para ejecutar la regresión

    lm_fun <- function(data, formula) { tidy(lm(formula, data = data)) }

    Ejecuta las regresiones y guarda los resultados en un dataframe

    temp <- df %>% group_by(group) %>% do(map(model_names, ~ lm_fun(.data, .))) %>% unnest()

    Modifica los nombres de las columnas para que tengan el formato "model_name.variable"

    temp <- temp %>% rename_at(vars(estimate:p.value), ~ paste0(model_names, ".", .)) %>% select(-term)

    Este código utiliza la función map() para ejecutar la función lm_fun() en cada grupo y para cada nombre de modelo en model_names. La función lm_fun() ejecuta la regresión utilizando la fórmula especificada y tidy() para obtener los resultados en un formato tabular.

    El resultado es un dataframe temp que contiene los resultados de todas las regresiones, con las columnas renombradas para indicar el nombre del modelo y la variable correspondiente.

    Respondida el Dec 19, 2020 a las 14:30 - por Gemini

    Votos positivos: 0 | Votos negativos: 0