【问题标题】:Loop regression through different data frames通过不同的数据框循环回归
【发布时间】:2017-08-02 13:20:52
【问题描述】:

目标是对不同的训练数据帧进行多次 logit 回归,然后在各个测试数据集上评估性能。

首先,我们从df 创建多个 (5) 个随机采样的数据帧:

for(i in 1:5) {
nr <- paste("random_df", i, sep = "_")
assign(nr, random_df[sample(nrow(df)),])
}

然后,我们为训练集和测试集的分离创建指标:

train <- 1:(length(df$y)*0.8)
test  <- !(1:nrow(df) %in% train)

现在我们想在每个训练数据帧上循环一个 logit 回归。这是第一个问题,因为我们只能将输出创建为矩阵或列表。 我们也可以创建随机样本的列表、数据框或矩阵:

lr_list <- list(random_df_1,random_df_2,random_df_3,random_df_4,random_df_5)

然后,我们在列表中的所有数据帧上循环 logit 回归:

for(i in 1:5) {
  index <- paste("lr_train", i, sep = "_")
  assign(index, lapply(lr_list, function(x) {glm(y ~ x1 + x2, data=x, 
  subset=train, family=binomial)}))
}

这里lapply 创建一个列表,sapply 为每个估计结果创建一个矩阵。

目标是获得glm 对象形式的输出,以便使用每个train glm 进行预测,从而能够评估不同测试/训练中的模型性能数据星座:

lr_test_1 <- predict(lr_train_1, random_df_1[test, ], type="response")

非常感谢任何帮助。

【问题讨论】:

  • 您应该查看modelr 包。这让很多事情变得更容易:github.com/tidyverse/modelr
  • 谢谢@AndrewBrēza 您能否给我一个提示,告诉我不仅要使用resample,还要使用modelrpackage 在多个训练集和测试集上评估模型?

标签: r loops cross-validation sapply training-data


【解决方案1】:

我很确定你误解了lapply 的使用和输出。它循环输入并创建一个对象列表,这些对象属于您使用的函数输出的典型类。

如果我正确阅读了您的代码,这部分

for(i in 1:5) {
  index <- paste("lr_train", i, sep = "_")
  assign(index, lapply(lr_list, function(x) {glm(y ~ x1 + x2, data=x, 
  subset=train, family=binomial)}))
}

本质上是在同一事物上循环两次,因此创建了五个相同的列表。

相反,只需使用:

lr_train <- lapply(lr_list, function(x) {glm(y ~ x1 + x2, data=x, 
      subset=train, family=binomial)})

然后mapply 你的predict 在 glm 对象列表上。

lr_test <- mapply(function(x, y) predict(x, y[test, ], type = "response"), lr_train, lr_list)

请注意,由于缺乏有效的数据示例,因此未经测试。

【讨论】:

  • 感谢@Leo P。虽然未经测试,但效果很好。你是对的,我误解了lappy。我们继续使用:lr_estim &lt;- cut(lr_test, breaks=c(-Inf, .5, Inf), labels=c(0,1)) 创建一个因子。然后我们通过lr_tab &lt;- lapply(lr_list, function(x) {table(x$y[test], lr_estim, dnn = c("real", "prediction"))}) 创建了一个列表。下一个问题在于从 lr_tab 创建一个prop.table,因为它是一个列表,而不是一个表格。感谢您的帮助。
【解决方案2】:

好吧,不久前我学会了一个使用 dplyrpurrr 包的技巧。这是关于使用嵌套的data.frame

nested_df <- tibble(subdf = 1:5) %>% # Choose number of 'random_df' 
  rowwise() %>% 
  mutate(data = list(df[sample(nrow(df)),])) %>% # create a list of random data.frames within our data.frame
  ungroup() %>% 
  mutate(model = map(data, ~ glm(y ~ x1 + x2, data = .x, 
                                     subset = train, family = binomial))) # iterate with map throug all of data.frame's in column data


nested_df

  subdf                   data     model
  <int>                 <list>    <list>
1     1 <data.frame [100 x 3]> <S3: glm>
2     2 <data.frame [100 x 3]> <S3: glm>
3     3 <data.frame [100 x 3]> <S3: glm>
4     4 <data.frame [100 x 3]> <S3: glm>
5     5 <data.frame [100 x 3]> <S3: glm>

我们可以查看每个model

nested_df$model[[1]]

Call:  glm(formula = y ~ x1 + x2, family = binomial, data = .x, subset = train)

Coefficients:
(Intercept)          x1b          x1c           x2  
  3.467e+00   -5.085e-03    1.300e-02    9.368e-05  

Degrees of Freedom: 79 Total (i.e. Null);  76 Residual
Null Deviance:      0.3428 
Residual Deviance: 0.3408   AIC: 12.7

输出来自我快速模拟的df

df <- data.frame(y = rnorm(100, 100),
                 x1 = sample(letters[1:3], size = 100, replace = T),
                 x2 = runif(100 ,0, 1000)) %>% 
  mutate(y = y/max(y))

您可以对具有mutate()map() 类似结构的每个glm 进行预测

【讨论】:

  • 你需要使用map2/pmap进行预测... %>% mutate(pred = map2(model, data, predict))
  • map 属于哪个包?
  • @Dima 我的回答有误,包裹purrr
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-12
  • 2020-03-30
  • 2020-12-09
  • 1970-01-01
  • 1970-01-01
  • 2020-07-12
  • 1970-01-01
相关资源
最近更新 更多