Как я запускаю множественную регрессию в R, каждый раз добавляя 100 дополнительных строк

Я надеюсь получить помощь по следующей проблеме в R.

У меня есть 4 переменные, firm ID, sales, size, date, почти для 4000 фирм.

Я хочу запустить эту регрессию:

lm(size~sales), при этом добавляя по 100 фирм за раз из 4000.

Итак, в первой регрессии будет 100 фирм, во второй - 200, в третьей - 300... пока не будет достигнута последняя регрессия, включающая все фирмы (4000).

Вторая задача: я хочу сохранить бета-коэффициент каждой регрессии (т. е. каждой регрессии после добавления дополнительных 100 фирм), а затем построить бета-коэффициент по Y и количество фирм по х (от 100 до 4000), чтобы наблюдать, как изменяется бета. при добавлении фирм.

Нужен ли мне какой-то цикл для регрессии, цикл для сохранения бета-версий и цикл для построения графиков? Спасибо за чтение

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
232
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вот минимальный пример использования набора данных mtcars. Я построил регрессию, добавляя по одной строке за раз. Затем я предварительно выделяю вектор результатов справа, а затем перебираю строки и сохраняю результаты коэффициентов.

results <- vector(length = nrow(mtcars))
for (j in 1:nrow(mtcars)){
  results[j] <- coef(lm(mpg ~ hp, data = mtcars[1:j, ]))[2]
}

plot(x = 1:nrow(mtcars), y = results, type = "p")

Created on 2019-04-07 by the reprex package (v0.2.1)

Ответ принят как подходящий

Рассмотрите возможность разделения набора данных по фирмам, а затем итеративного запуска lm с использованием последовательности seq(1, 4000, by=100) для подмножества списка разделенных фреймов данных:

# BUILD A LIST OF DATA FRAMES (SIZE = 4,000)
firms_df_list <- split(df, df$firm_id)

# FUNCTION TO CALL lm() AND EXTRACT RESULTS
lm_results <- function(n, df) {

  model <- lm(sales ~ size, data = df)
  res <- summary(model)

  p <- res$fstatistic
  c(num_of_firms = n,
    sales = res$coefficients[2,1],
    std_err = res$coefficients[2,2],
    t_stat = res$coefficients[2,3],
    t_pvalue = res$coefficients[2,4],
    r_sq = res$r.squared,
    adj_r_sq = res$adj.r.squared,
    f_stat = p[['value']],
    f_pvalue = unname(pf(p[1], p[2], p[3], lower.tail=FALSE))
  )
}

# BUILD MATRIX RESULTS WHERE ROWS ARE MODEL RUNS AND COLS ARE RESULT ESTIMATES
mat_results <- t(sapply(seq(1, 4000, by=100), function(i) {
     # COMBINE FIRM SUBSETS BY RANGE
     curr_df <- do.call(rbind, firms_df_list[1:i])

     # CALL MODEL AND RETRIEVE RESULTS
     lm_results(i, curr_df)
}))

# PLOT ALL SALES BETAS AND NUMBER OF FIRMS
plot(mat_results[,"num_of_firms"], mat_results[,"sales"], type = "b", 
     col = "blue", lwd=1, pch=16, xlab = "Number of Firms", ylab = "Sales Estimate")

Чтобы учесть разбивку по годам и месяцам, рассмотрите by (аналогично split + lapply) для подмножества по годам, а затем по месяцам с внутренним split (аналогично описанному выше процессу), где каждая итерация запускает необходимую модель. Затем свяжите матрицы на каждом уровне месяца и года для окончательной большой матрицы. Примечание: lm_results теперь получает еще два параметра для столбцов матрицы месяца и года индикатора.

# FUNCTION TO CALL lm() AND EXTRACT RESULTS
lm_results <- function(n, df, yy, mm) {

  model <- lm(sales ~ size, data = df)
  res <- summary(model)

  p <- res$fstatistic
  c(year = yy,
    month = mm,
    num_of_firms = n,
    sales = res$coefficients[2,1],
    std_err = res$coefficients[2,2],
    t_stat = res$coefficients[2,3],
    t_pvalue = res$coefficients[2,4],
    r_sq = res$r.squared,
    adj_r_sq = res$adj.r.squared,
    f_stat = p[['value']],
    f_pvalue = unname(pf(p[1], p[2], p[3], lower.tail=FALSE))
  )
}    

# BUILD A LIST OF MONTHLY MATRICES BY YEAR
firms_mat_list <- by(df, df$yy, function(sub_year){

  # BUILD A LIST OF FIRM MATRICES BY MONTH
  month_mat_list <- by(sub_year, sub_year$mm, function(sub_month){

    firms_df_list <- split(sub_month, sub_month$firm)

    # BUILD MATRIX RESULTS WHERE ROWS ARE MODEL RUNS AND COLS ARE RESULT ESTIMATES
    mat_results <- t(sapply(seq(1, 4000, by=100), function(i) {
      # COMBINE FIRM SUBSETS BY RANGE
      curr_df <- do.call(rbind, firms_df_list[1:i])

      # CALL MODEL AND RETRIEVE RESULTS
      lm_results(i, curr_df, curr_df$yy[1], curr_df$mm[1])
    }))

  })

  do.call(rbind, month_mat_list)
})

firms_matrix <- do.call(rbind, firms_mat_list)

firms_matrix

Спасибо, это сработало, однако за каждой фирмой наблюдают ежемесячно (о чем я не упомянул в своем первоначальном вопросе), поэтому у меня есть колонка по годам (некоторые наблюдались с 2000 по 2016 год, некоторые в меньший период времени) и столбец для месяца, который соответствует каждому году. принимая во внимание год и месяцы, я предполагаю, что это повлияет на результат регрессии, не могли бы вы посоветовать, как учитывать годы и месяцы для каждой фирмы при работе model <- lm(sales ~ size, data = df)? Нужен ли мне цикл в течение месяцев и лет?

Jack Sle 28.04.2019 13:39

Ух ты! Я думал, что потерял тебя на другой стороне интернета! Иногда мы получаем ОП, которые исчезают. Но что именно вы подразумеваете под счетом за месяцы и годы. Вы хотите дополнительно разделить размер фирмы по годам/месяцам или включить их в регрессию?

Parfait 28.04.2019 17:35

Спасибо!! Я имел в виду, что каждая фирма от фирмы 1 до фирмы 4000 наблюдается ежемесячно в течение многих лет, mm варьируется от 1 до 12 и yy с 2005 по 2016 год. Мои переменные: каждый год, а затем добавляя по 100 фирм за раз, т.е. охватывая все месяцы всех лет и все 4000 фирм. Предоставленный вами код, я думаю, учитывает все наблюдения сразу ... возможно, нам нужно воспроизвести регрессию в течение месяцев и лет, чтобы учесть время? Спасибо вам еще раз, с нетерпением жду.

Jack Sle 29.04.2019 02:39

См. разделение обновлений по годам и месяцам с помощью by до запуска моделирования с помощью split.

Parfait 29.04.2019 17:37

The second task, is I want to save the beta coefficient of each regression (i.e. each regression after I add extra 100 firms), and then plot beta on Y and number of firms on x (from 100 to 4000) to observe how beta changes when adding firms.

Вы можете использовать мой пакет rollRegres. Это почти идентично примеру в эта виньетка:

set.seed(65731482)
ngrp <- 40L
n_per_g <- 100L
# create group variable
grp <- c(sapply(1:ngrp, rep, times = n_per_g))
n <- n_per_g * ngrp
p <- 1L
X <- matrix(rnorm(p * n), n, p)
y <- drop(X %*% 1.5) + rnorm(n)

library(rollRegres)
out <- roll_regres(y ~ X, do_downdates = FALSE, width = 100L)
beta <- out$coefs

# check result
tail(out$coefs, 2)
#R      (Intercept)    X
#R 3999    -0.00552 1.51
#R 4000    -0.00571 1.51
coef(lm(y ~ X))
#R (Intercept)           X 
#R    -0.00571     1.51405 

# plot 
plot(out$coefs[, 2], xlab = "Time", ylab = "slope", type = "l")

Он дает вам все значения 40000 - 99, но делает это быстро, поэтому вам, вероятно, не нужны дополнительные вычисления.

microbenchmark::microbenchmark(
  roll_regres(y ~ X, do_downdates = FALSE, width = 100L))
#R Unit: microseconds
#R                                                   expr min  lq mean median  uq  max neval
#R roll_regres(y ~ X, do_downdates = FALSE, width = 100L) 740 750  771    763 772 1090   100

и вы можете потом подмножить beta.

Другие вопросы по теме