2
votes

Comment exécuter une régression multiple dans R tout en ajoutant 100 lignes supplémentaires à chaque fois

J'espère obtenir de l'aide sur le problème suivant dans R.

J'ai 4 variables, numéro d'entreprise , ventes , taille , date , pour près de 4 000 entreprises.

Je souhaite exécuter cette régression:

lm (size ~ sales) , tout en ajoutant 100 entreprises à la fois à partir des 4000.

Ainsi, la première régression aura 100 firmes, la seconde en aura 200, la troisième en aura 300 ... jusqu'à atteindre la dernière régression qui inclut toutes les firmes (4000).

La deuxième tâche, c'est que je veux enregistrer le coefficient bêta de chaque régression (c'est-à-dire chaque régression après avoir ajouté 100 entreprises supplémentaires), puis tracer le bêta sur Y et le nombre d'entreprises sur x (de 100 à 4000) pour observer comment la version bêta change lors de l'ajout d'entreprises.

Ai-je besoin d'une sorte de boucle pour les régressions, d'une boucle pour sauvegarder les bêtas et d'une boucle pour le traçage? Merci d'avoir lu


0 commentaires

3 Réponses :


0
votes

Voici un exemple minimal pour vous en utilisant le jeu de données mtcars . J'ai construit une régression en ajoutant une ligne à la fois. Je préalloue un vecteur de résultats vers la droite puis je parcours les lignes et je stocke les résultats du coefficient.

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")

Créé le 07/04/2019 par le package reprex (v0.2.1)


0 commentaires

0
votes

Pensez à diviser votre ensemble de données par entreprises, puis à exécuter de manière itérative lm en utilisant une séquence seq (1, 4000, par = 100) pour sous-ensemble diviser la liste des cadres de données:

# 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

Pour tenir compte de la ventilation par année et par mois, considérez by (similaire à split + lapply ) sous-ensemble par année, puis par mois avec split interne (similaire au processus ci-dessus) où chaque itération exécute le modèle nécessaire. Ensuite, liez les matrices à chaque niveau de mois et d'année pour une grande matrice finale. Remarque: lm_results reçoit désormais deux paramètres supplémentaires pour les colonnes de la matrice de l'indicateur mois et année.

# 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")


4 commentaires

Merci, cela a fonctionné, cependant, chaque entreprise est observée sur une base mensuelle (ce que j'ai manqué de mentionner dans ma question initiale), j'ai donc une colonne pendant des années (certaines observées de 2000 à 2016, d'autres sur moins de temps) et un colonne pour le mois qui correspond à chaque année. en tenant compte de l'année et des mois, je suppose que cela affectera la sortie de la régression, pouvez-vous s'il vous plaît conseiller sur la façon de prendre en compte les années et les mois pour chaque entreprise lors de l'exécution de model <- lm (sales ~ size, data = df) ? Ai-je besoin d'une sorte de boucle sur des mois et des années?


Hou la la! Je pensais te perdre de l'autre côté d'Internet! Parfois, nous obtenons des OP qui disparaissent. Mais qu'entendez-vous exactement par compte pendant des mois et des années. Voulez-vous diviser davantage la taille des entreprises par année / mois ou les inclure dans la régression?


Merci!! Ce que je voulais dire, c'est que chaque entreprise de l'entreprise 1 à l'entreprise 4000 est observée mensuellement au fil des ans, variable mm de 1 à 12 et aa de 2005 à 2016. Mes variables sont: vente de taille entreprise mm aa Fondamentalement, Je veux exécuter la régression pour inclure tous les mois de chaque année, puis ajouter 100 entreprises à la fois, c'est-à-dire couvrant tous les mois de toutes les années et les 4 000 entreprises. Le code que vous avez fourni, je pense, prend toutes les observations à la fois ... nous devons probablement reproduire la régression sur des mois et des années pour tenir compte du temps? Merci encore une fois, au plaisir.


Voir la répartition des mises à jour par année et par mois avec by avant les exécutions de modélisation avec split .



0
votes

La deuxième tâche, c'est que je veux enregistrer le coefficient bêta de chaque régression (c'est-à-dire chaque régression après avoir ajouté 100 entreprises supplémentaires), puis tracer le bêta sur Y et le nombre d'entreprises sur x (de 100 à 4000) pour observer comment la version bêta change lors de l'ajout d'entreprises.

Vous pouvez utiliser mon package rollRegres . C'est presque identique à l'exemple de cette vignette :

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

Il vous donne toute la valeur 40000 - 99 mais il le fait rapidement donc vous ne vous soucierez probablement pas du calcul supplémentaire

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")

0 commentaires