Разделение данных и запуск цикла линейной регрессии - PullRequest
2 голосов
/ 01 апреля 2020

Я видел много подобных вопросов, но есть один ключ к l oop, который я пытаюсь написать, что мне не хватает. У меня есть набор данных с ~ 4000 различных ключей, и для каждого ключа есть ~ 1000 наблюдений. Я отфильтровал ключ, чтобы выделить наблюдения для этого ключа, выполнить линейную регрессию, проверить допущения модели и все выглядит хорошо. Однако я хочу провести l oop над этим набором данных и запустить эту линейную регрессию для каждого из ключей. Затем я хочу сохранить коэффициенты, значения, R ^ 2 и т. Д. c и просмотреть их вместе.

Вот пример моих данных:

Key y1 x1 x2
A   10 1  3
A   11 2  4 
A   12 3  5
B   13 4  6 
B   14 5  7
B   15 6  8
C   16 7  9 
C   17 8  1
C   18 9  2

Я выполнил :

datA <- data %>% filter(key=='A')
lm(y1 ~ x1 + x2, data = datA)

И затем повторить это для клавиш B и C. Каждый вопрос, который я видел здесь, рассматривает циклы по различным переменным для всего набора, но не разбивает данные по строкам.

Но мне нужно сделать это еще 4000 раз. Любая помощь в написании этого l oop будет принята с благодарностью (я ужасно пишу циклы).

Ответы [ 3 ]

3 голосов
/ 01 апреля 2020

Вы можете split данные и применить lm к каждому чанку.

list_models <- lapply(split(df, df$Key), function(x) lm(y1 ~ x1 + x2, data = x))

A tidyverse путь будет следующим:

library(dplyr)
library(purrr)

list_models <- df %>% group_split(Key) %>% map(~lm(y1 ~ x1 + x2, data = .x))

Возвращает модель для каждого индивидуума Key.

list_models
#$A
#Call:
#lm(formula = y1 ~ x1 + x2, data = x)

#Coefficients:
#(Intercept)           x1           x2  
#          9            1           NA  

#$B
#Call:
#lm(formula = y1 ~ x1 + x2, data = x)

#Coefficients:
#(Intercept)           x1           x2  
#          9            1           NA  

#$C
#Call:
#lm(formula = y1 ~ x1 + x2, data = x)

#Coefficients:
#(Intercept)           x1           x2  
#   9.00e+00     1.00e+00     7.86e-16  
2 голосов
/ 01 апреля 2020

Можно также использовать пакет метла , чтобы привести выходные данные в более читаемую форму.

list_models <- lapply(split(data, data$Key), function(x) lm(y1 ~ x1 + x2, data = x))

library(broom)

as_tibble(do.call(rbind, lapply(list_models, broom::tidy)))

# A tibble: 7 x 5
  term        estimate  std.error statistic    p.value
  <chr>          <dbl>      <dbl>     <dbl>      <dbl>
1 (Intercept) 9.00e+ 0   2.22e-15   4.05e15   1.57e-16
2 x1          1.00e+ 0   1.03e-15   9.73e14   6.54e-16
3 (Intercept) 9.00e+ 0   4.59e-15   1.96e15   3.25e-16
4 x1          1.00e+ 0   9.06e-16   1.10e15   5.77e-16
5 (Intercept) 9.00e+ 0 NaN        NaN       NaN       
6 x1          1.00e+ 0 NaN        NaN       NaN       
7 x2          3.02e-16 NaN        NaN       NaN  
2 голосов
/ 01 апреля 2020

Гораздо менее элегантно, чем ответ @ RonakShah, вы можете группировать по вашему ключу и суммировать для каждого ключа, извлекая интересующие вас значения, чтобы получить следующую таблицу:

library(dplyr)

df %>% group_by(Key) %>%
  summarise(Intercept = lm(y1 ~ x1 + x2)$coefficients[1],
            Coeff_x1 = lm(y1 ~ x1 + x2)$coefficients[2],
            Coeff_x2 = lm(y1 ~ x1 + x2)$coefficients[3],
            R2 = summary(lm(y1 ~ x1 + x2))$r.squared,
            pvalue = summary(lm(y1 ~ x1 + x2))$coefficients["x1",4])

# A tibble: 3 x 6
  Key   Intercept Coeff_x1  Coeff_x2    R2     pvalue
  <chr>     <dbl>    <dbl>     <dbl> <dbl>      <dbl>
1 A            9.     1.00 NA            1   8.00e-16
2 B            9.     1.00 NA            1   7.00e-16
3 C            9.     1.00  7.86e-16     1 NaN       
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...