Как использовать два фрейма данных для запуска линейной регрессии с циклом for - PullRequest
0 голосов
/ 07 апреля 2020

Я пытаюсь провести простой анализ линейной регрессии, используя фрейм данных с 4 столбцами (все из которых являются зависимыми переменными) и фрейм данных, имеющий 194 строки и 212 столбцов. У меня есть 5 других фреймов данных для использования в качестве зависимой переменной для того же анализа

Я добился желаемых результатов, но мне нужно масштабировать это, я попытался добавить дополнительные для l oop (для столбцы зависимой переменной), но мне также нужно было бы одновременно создавать более пустые списки.

Хотелось бы узнать, как бы мне этого добиться?

Мой текущий for-l oop:

y <- data.frame(Green_Class_Commercial[,-1])
x <- data.frame(lagvar[1:175,c(-1,-2)])
out <- data.frame(NULL)              # create object to keep results

for (i in 1:length(x)) {
  m <- summary(lm(y[,1] ~ x[,i]))    # run model
  out[i, 1] <- names(x)[i]           # print variable name
  out[i, 2] <- m$coefficients[1,1]   # intercept
  out[i, 3] <- m$coefficients[2,1]   # coefficient
  out[i, 4] <-m$coefficients[2,4]    # Pvalue
  out[i,5] <-m$r.squared             # R-squared
}
names(out) <- c("Variable", "Intercept", "Coefficient","P-val","R-square")
head(out)

Предоставление вывода

> head(out)
               Variable Intercept   Coefficient     P-val     R-square
1                GDP.SC 0.2540527 -4.722220e-07 0.7032087 8.411229e-04
2               GDP.SC1 0.1148311  3.107631e-07 0.7959237 3.899366e-04
3               GDP.SC2 0.1609010  4.998762e-08 0.9673014 9.855831e-06
4               GDP.SC3 0.1353608  1.959274e-07 0.8746321 1.468544e-04
5               GDP.SC4 0.1439931  1.487237e-07 0.9064221 8.200597e-05
6 CivilianLaborForce.SC 0.2595231 -4.078450e-08 0.7716514 4.881398e-04
> 

Итак, вот переменные, которые я хочу запустить регрессию

#The x Variable
structure(list(GDP.SC = c(154698, 154698, 154698, 154698, 154698, 
154698, 154698, 154698, 154698, 154698, 160138.4, 160138.4, 160138.4, 
160138.4, 160138.4, 160138.4, 160138.4, 160138.4, 160138.4, 160138.4
), GDP.SC1 = c(NA, 154698, 154698, 154698, 154698, 154698, 154698, 
154698, 154698, 154698, 154698, 160138.4, 160138.4, 160138.4, 
160138.4, 160138.4, 160138.4, 160138.4, 160138.4, 160138.4), 
    GDP.SC2 = c(NA, NA, 154698, 154698, 154698, 154698, 154698, 
    154698, 154698, 154698, 154698, 154698, 160138.4, 160138.4, 
    160138.4, 160138.4, 160138.4, 160138.4, 160138.4, 160138.4
    ), GDP.SC3 = c(NA, NA, NA, 154698, 154698, 154698, 154698, 
    154698, 154698, 154698, 154698, 154698, 154698, 160138.4, 
    160138.4, 160138.4, 160138.4, 160138.4, 160138.4, 160138.4
    ), GDP.SC4 = c(NA, NA, NA, NA, 154698, 154698, 154698, 154698, 
    154698, 154698, 154698, 154698, 154698, 154698, 160138.4, 
    160138.4, 160138.4, 160138.4, 160138.4, 160138.4)), row.names = c(NA, 
20L), class = "data.frame")

#The Y Variable
structure(list(X = 1:20, ComBus = c(0.83, 0, 0.23, 0.09, 0.1, 
0.11, 0.15, 0.18, 0.37, 0.19, 0, 0.18, 0.09, 0.1, 0.03, 0.5, 
0.14, 0.17, 0.11, 0.06), ComCon = c(NA, 0, 0, 0, 0, 0.5, 0, 0, 
NA, 0.67, 0, 0, 0, 0, 0.5, 0, 0, NA, 1, 0), ComNoo = c(0.25, 
0.14, 0.38, 0.17, 0.14, 0.33, 0.44, 0.05, 0.04, 0.1, 0.18, 0.06, 
0.23, 0.14, 0.5, 0.14, 0.5, 0, 0.14, 0.23), ComOO = c(0, 0, 0, 
0, 0, 0.33, 0, 0, 0, 0.18, 0.22, 0.15, 0, 0, 0.17, 0, 0, 0, 0, 
0)), row.names = c(NA, 20L), class = "data.frame")

Ответы [ 2 ]

1 голос
/ 08 апреля 2020

Рассмотрим вложенный lapply с внешним вызовом, пересекающим каждый столбец фрейма данных зависимой переменной, и каждый раз, когда внутренний вызов перебирает все столбцы фрейма данных независимых переменных:

reg_data <- function(yvar, xdf) {
    # ITERATE THROUGH EACH COLUMN OF x
    df_list <- lapply(seq_along(xdf), function(i) {
      m <- summary(lm(yvar ~ x[,i]))        # run model

      data.frame(
         Variable = names(x)[i],            # print variable name
         Intercept = m$coefficients[1,1],   # intercept
         Coefficient = m$coefficients[2,1], # coefficient
         P_val = m$coefficients[2,4],       # P-value
         R_square = m$r.squared             # R-squared
      )
    })

   return(do.call(rbind, df_list))
}

# ITERATE THROUGH EACH COLUMN OF y
model_dfs <- lapply(y[-1], function(col) reg_data(col, x))

Выход

model_dfs

# $ComBus
#   Variable  Intercept   Coefficient     P_val    R_square
# 1   GDP.SC  2.6988486 -1.599147e-05 0.3262406 0.053555129
# 2  GDP.SC1 -0.1802638  2.083180e-06 0.8452577 0.002304901
# 3  GDP.SC2  0.4443504 -1.838100e-06 0.8656578 0.001843828
# 4  GDP.SC3 -0.2114691  2.310754e-06 0.8410848 0.002767098
# 5  GDP.SC4 -0.4596142  3.921280e-06 0.7517165 0.007381776

# $ComCon
#   Variable  Intercept  Coefficient     P_val    R_square
# 1   GDP.SC -0.4342988 3.752788e-06 0.8970060 0.001154220
# 2  GDP.SC1 -1.5050149 1.056908e-05 0.7148913 0.009154924
# 3  GDP.SC2 -2.2666678 1.549256e-05 0.6144502 0.018606737
# 4  GDP.SC3 -3.2822050 2.205720e-05 0.5032585 0.035178198
# 5  GDP.SC4 -4.7039571 3.124770e-05 0.3808557 0.064522691

# $ComNoo
#   Variable   Intercept  Coefficient     P_val    R_square
# 1   GDP.SC -0.02348033 1.470480e-06 0.9087818 0.000749555
# 2  GDP.SC1 -0.33062799 3.410697e-06 0.8011075 0.003836926
# 3  GDP.SC2 -1.11901191 8.455261e-06 0.5536610 0.022365205
# 4  GDP.SC3 -1.58084828 1.134370e-05 0.4400999 0.040243587
# 5  GDP.SC4 -2.12276002 1.482734e-05 0.3493362 0.062765524

# $ComOO
#   Variable   Intercept   Coefficient     P_val    R_square
# 1   GDP.SC -0.03430512  5.514300e-07 0.9481025 0.000241968
# 2  GDP.SC1  1.13773433 -6.882664e-06 0.4347716 0.036277535
# 3  GDP.SC2  1.98603902 -1.226932e-05 0.1785540 0.110105644
# 4  GDP.SC3  1.89971836 -1.171132e-05 0.2291494 0.094842038
# 5  GDP.SC4  1.78462415 -1.096733e-05 0.2963624 0.077531366

Онлайн-демонстрация

1 голос
/ 07 апреля 2020

Хорошо, это хорошо для вас? Я заменяю l oop на apply, если это нормально?

### Some dummy dataframes
x <- data.frame(v1 = rnorm(1:10),
                 v2 = rnorm(1:10),
                 v3 = runif(10, 1, 1000),
                 v4 = runif(10, 1, 1000))
x2 <- data.frame(v1 = rnorm(1:10),
                v2 = rnorm(1:10),
                v3 = runif(10, 1, 1000),
                v4 = runif(10, 1, 1000))
y <- data.frame(v1 = rnorm(1:10),
                v2 = rnorm(1:10),
                v3 = runif(10, 1, 1000),
                v4 = runif(10, 1, 1000))
y2 <- data.frame(v1 = rnorm(1:10),
                 v2 = rnorm(1:10),
                 v3 = runif(10, 1, 1000),
                 v4 = runif(10, 1, 1000)) 

###
# I tend to prefer the apply family of functions to replace loops where possible.
# This function takes two inputs, dataframes of dependent and independent variables.
# the apply function here takes the x_df and applies the following anonymous function to each column
# so for each column in x_df it performs a lm against the first column of y_df

lm_func <- function(y_df, x_df) {
  out <- apply(x_df, MARGIN = 2, function(x) {
    lm(y_df[, 1] ~ x)
  })
  return(out)
}

results_list <- lm_func(y, x)

# the output is one list element per lm. I like to keep the whole lm output just in case you need to go back to it

# we can then turn that list back into a dataframe using rbindlist from data.table
# and get what I think is your desired output using glance from broom

library(data.table)
library(broom)

results_glance <- rbindlist(lapply(results_list, glance), idcol = "var_name")

# or keep it as a list if you wish
results_list_glance <- lapply(results_list, glance)

# to run the function using a single x argument but multiple y arguments you can use mapply

results_list_m <- mapply(lm_func,
                       y_df = list(y, y2),
                       MoreArgs = list(    # other arguments you want to keep fixed
                         x_df = x
                       ),
                       SIMPLIFY = F
)

# the output is a little fiendish because it will be a list of lists
# we can include the rbindlist and glance into the function to make the output a little simpler:


lm_func_bind <- function(y_df, x_df) {
  out <- apply(x_df, MARGIN = 2, function(x) {
    lm(y_df[, 1] ~ x)
  })
  out <- rbindlist(lapply(out, glance), idcol = "var_name")
  return(out)
}
results_glance_df <- lm_func_bind(y, x)

results_list_dfs <- mapply(lm_func_bind,
                           y_df = list(y, y2),
                           MoreArgs = list(    # other arguments you want to keep fixed
                             x_df = x
                           ),
                           SIMPLIFY = F
)

Дайте мне знать, могу ли я сделать это лучше. Если вы не знакомы с некоторыми функциями, такими как apply и rbindlist, стоит ознакомиться с документацией. Ура!

PS Обычно повторяющиеся линейные модели не идеальны из-за шансов на успех. Это скорее вопрос статистики, а не кодирования!

...