【问题标题】:How to apply a regression in a for loop for all the variables of a dataset while adding rows in R如何在 for 循环中对数据集的所有变量应用回归,同时在 R 中添加行
【发布时间】:2017-04-01 17:23:59
【问题描述】:

我知道这是一个很长的问题,但请耐心等待。

我有一个这种形式的数据集:

    head(TRAINSET)
         X1        X2        X3      X4      X5    X6    X7     X8    X9     X10     X11    X12     X13        X14        Y
1 -2.973012 -2.956570 -2.386837 -0.5861751 4e-04 0.44 0.0728 0.0307 0.0354  0.0078  0.0047 0.0100 -0.0022   0.0038 -0.005200012
2 -2.937649 -2.958624 -2.373960 -0.5636891 5e-04 0.44 0.0718 0.0323 0.0351  0.0075  0.0028 0.0095 -0.0019   0.0000  0.042085781
3 -2.984238 -2.937649 -2.428712 -0.5555258 2e-04 0.43 0.0728 0.0329 0.0347  0.0088  0.0018 0.0092 -0.0019  -0.0076  0.004577122
4 -2.976535 -2.970053 -2.443424 -0.5331107 9e-04 0.47 0.0588 0.0320 0.0331  0.0253  0.0011 0.0092 -0.0170  -0.0076  0.010515970
5 -2.979631 -2.962549 -2.468805 -0.5108256 6e-04 0.46 0.0613 0.0339 0.0333 -0.0005 -0.0006 0.0090  0.0060  -0.0058  0.058487141
6 -3.030536 -2.979631 -2.528079 -0.5024574 3e-04 0.43 0.0562 0.0333 0.0327  0.0109 -0.0006 0.0093 -0.0120   0.0000 -0.022896759

这是我的火车集,有 300 行。剩下的 700 行是测试集。我想要完成的是:

  1. 为每一列拟合这种形式的线性模型:Y ~ X1。
  2. 使用创建的模型通过使用测试集的第一个 X1 来获得 Y 的预测值。
  3. 之后,取出测试集的第一行并将其绑定到训练集(现在训练集为 301 行)。
  4. 使用测试集中 X1 的第二行预测 Y 的值。
  5. 对测试集的剩余 699 行重复。
  6. 将其应用于数据集的所有剩余变量 (X2,...,X14)。

当我专门为每个变量应用代码时,我已经设法产生了准确的结果:

fittedvaluess<-NULL   #empty set to fill
for(i in 1:nrow(TESTSET)){      #beggin iteration over the rows of Test set 
  TRAINSET<-rbind(TRAINSET,TESTSET[i,]) #add the rows to the train set
  LM<-lm(Y~X1,TRAINSET)               #fit the evergrowing OLS    
  predictd<-predict(LM,TESTSET[i+1,],type = "response") #get the predicted value
  fittedvaluess<-cbind(fittedvaluess,predictd) #get the vector of the predicted values
  print(cbind(i,length(TRAINSET$LHS),length(TRAINSET$DP),nrow(TRAINSET))) #to make sure it works
}

但是,我想自动执行此操作并在列上重复它。我做了这个:

data<-TRAINSET #cause every time i had to remake the trainset
fittedvaluesss<-NULL          
for(i in 1:nrow(TESTSET){          #begin iteration on rows of Testset
  data<-rbind(data,TESTSET[i,])    # rbind the rows to the Trainset called data
  for(j in 1:ncol(TESTSET){        #iterate over the columns
    LM<-lm(data$LHS~data[,j],data)  #fit OLS
    predictd<-predict(LM,TESTSET[i+1,j],type = "response") #get the predicted value
    fittedvaluesss<-cbind(fittedvaluesss,predictd) #derive the predicted value
    print(c(i,j)) #make sure it works
  }
}

不幸的是,结果是错误的:拟合值是一个巨大的矩阵:

 dim(fittedvaluesss)
[1] 2306 3167 #Stopped around the middle of its run

这没有任何意义。我什至已经运行它了

i in 1:3
and
j in 1:3 

但矩阵仍然非常庞大。我尝试过从列开始迭代并越过行。完全一样的错误结果。出于某种原因,在每次运行中,我都从 PREDICT 函数中获得了至少 362 个值。我真的被这个问题困住了。

非常欢迎任何帮助。

编辑 1:这在金融中也称为递归预测方法。这是一种从当前数据集拟合的模型预测未来值的方法。

【问题讨论】:

  • 这看起来像是重新发明折刀的奇怪尝试,除了“添加一个”而不是“留下一个”。我不相信这会是一个有意义的练习。至少应该提供某种理论依据。它似乎不太适合 SO,更适合在 statsstackexchange.com 寻求帮助
  • 当然,fittedvalues 会变得非常大,你会在每次嵌套迭代中不断地绑定它。你想要的结果是什么?为什么不是fittedvalues 的列表,每个都对应一个变量?
  • @42 我所做工作的理论背景被称为金融预测。您使用行的值:即模型拟合中的 67 来获得第 68 行的 Y 值。
  • @Parfait 我需要得到一个700行14列的表,所有的值都是predict函数的结果

标签: r for-loop dataset regression


【解决方案1】:

考虑使用外循环中的列和内循环中的行来反转循环逻辑。此外,尝试嵌套应用函数,它返回的结构比for 循环更符合您的需求。具体来说,内部 vapply() 返回每​​个迭代列的所有测试集预测值的数字向量。然后外部sapply() 将每个返回的向量绑定到矩阵的一列。

最终,fittedvaluess 是一个具有以下维度的矩阵:TESTSET nrow X TESTSET ncol。还要注意,外循环省略了最后一列,因为您没有在 Y 上回归 Y。

fittedvaluess <- sapply(1:(ncol(TESTSET)-1), function(c){

  col <- names(TESTSET)[[c]]                     # RETRIEVE COLUMN NAME FOR LM FORMULA

  predictvals <- vapply(1:nrow(TESTSET), function(r){      
    TRAINSET <- rbind(TRAINSET, TESTSET[1:r,])   # BINDING ROWS ON AND PRIOR TO CURRENT ROW
    LM <- lm(paste0("Y~", col), TRAINSET)        # CONCATENATED STRING FORMULA
    predictd <- predict(LM, TESTSET[r+1,], type="response")
  }, numeric(1))

})

为什么是 sapply 和 vapply?

sapply()vapply() 都是 lapply() 的包装器。其中sapply() (simple lapply) 可以返回向量或矩阵,vapply() (verified lapply) 允许您专门选择返回的输出 --vector 、列表、矩阵——以及类型和长度。所以vapply 需要第三个参数来指定这样的标准。在这里,我们选择一个长度(或一个对象)的数值向量:numeric(1)。由于这个预先规范,vapply() 在某些情况下往往比lapply() 运行得更快。如果我们只选择一般的lapply(),我们将需要运行列表输出的各种转换和转换以与矩阵输出对齐。在某种程度上,我们可以做嵌套的vapply() 循环!

【讨论】:

  • 我试过了,虽然它有效,但并没有给出正确的结果。我认为这是因为 predict 函数。 (我有价值观应该是什么的解决方案)。
  • 在您的原始循环中,您更新训练集:TRAINSET&lt;-rbind(TRAINSET,TESTSET[i,])。这是否旨在为不断增长的训练集滚动到其他迭代中,还是应该在每次迭代中添加一次行,然后恢复? Vapply 稍后运行。
  • 查看增长TRAINSET 的更新,方法是在每个 vapply 调用之前和TESTSET 行之前和之上绑定所有行。请注意:这试图复制 产生准确结果的第一个循环,而不是第二个循环,因为 predict() 产生不同的结果,公式结构:lm(data$LHS~data[,j],data) vs lm(LHS~colname,data) - 可能是由于名称。跨度>
  • 是的,每次在火车集合中添加一条新线路。因此,在第一次迭代中,训练集将有 301 行。在第二次迭代 302 行等等。
  • 我刚刚运行它,它产生的结果与我的和实际值完全相同。太棒了。如果您可以请在您的代码中添加一些 cmets,以便我可以更轻松地理解它的作用,这将是很棒的,所以我接受您的回答!
【解决方案2】:

通过使用下面的代码,这是我原始代码的一个小版本,除了我没有使用predict

#EXPAND IT INTO DOING SO IN ALL COLUMNS
data<-TRAINSET
fittedvaluesss<-NULL
for(i in 1:nrow(TESTSET)){ #go each row
  data<-rbind(data,TESTSET[i,]) #update the dataset
  for(j in 1:ncol(TESTSET)){ #repead for each column the following
    LM<-lm(data$LHS~data[,j])   #OLS reg
    predictd<-coef(LM)[1]+coef(LM)[2]*TESTSET[i+1,j] #Simply apply the formula yourself A+Bx for each new iteration
    #predict(LM,TESTSET[i+1,j],type = "response")
    print(length(predictd)) #makes sure it is ONE value
    fittedvaluesss<-c(fittedvaluesss,predictd)
    print(c(i,j))
  }
}
matrixa<-matrix(fittedvaluesss,15,648) #put the values in a matrix: Note that the Ypreds are in every row
matrixa<-t(matrixa) #transpose in order to have each Ypred from a var in a column

这样做的原因是,每次迭代的预测函数都会返回一个大小为 361x15 的小矩阵(在我的初始代码中),这是针对单次迭代的。因此我放弃了预测函数并使用了系数本身。这似乎返回了正确的预测。

【讨论】:

    猜你喜欢
    • 2020-12-09
    • 2021-12-26
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 2021-08-24
    • 1970-01-01
    • 2018-08-23
    • 2020-11-04
    相关资源
    最近更新 更多