【问题标题】:Looping over independent variables in a regression to store P values and R squared values在回归中循环自变量以存储 P 值和 R 平方值
【发布时间】:2020-06-03 18:02:12
【问题描述】:

我正在尝试运行 150 个多元回归模型,它们具有相同的因变量(粮食产量)和协变量(年龄),但在每个实例中都有不同的预测变量。我想将每个回归结果的 R 平方值和 P 值存储在一个数据框中,我可以轻松查看数据支持哪些假设。我愿意接受替代的方法——基本上我想知道 150 个潜在预测因子中的哪些与年龄有显着的交互作用,通过看一眼表格,也很高兴知道 150 个预测因子中的哪些对他们的影响很重要自己的。我已经浏览了几十个关于 SO 的答案,但我仍然不确定最好的方法是什么。我明白运行这么多模型会导致 I 型错误膨胀。 Here 是指向我的数据的链接,但如果您愿意,可以随时在 mtcars 或 iris 中提出解决方案。到目前为止,我已经尝试过使用 lapply 和 sapply 并编写函数,使用 for 循环,使用 tidyr,在 for 循环中使用 list,在 for 循环中使用 append。这是使用 lapply 和 sapply 的解决方案,这是有希望的,但输出不是我可以展示的东西来显示哪些预测变量是重要的或不重要的——我仍然必须一个一个地调用每个结果。代码需要永远运行,这就是为什么我将它限制在前四列。所有结果都针对同一个预测变量。

`data$Grain<- as.numeric(as.character(data$Grain))
result <- sapply(names(data)[1 : 4], 
             function(x) { 
               lapply(names(data)[1 : 4], 
                      function(y) {
                        if (x != y) {
                          model <- lm(as.formula(paste0("Grain", "~", "Age", "*", x)), data) 
                          return(list(x = x, 
                                      r.squared = summary(model)$r.squared, 
                                      coefficients =  summary(model)$coefficients))
                        }
                      })
             })`

我尝试删除 function(y){}if(x!=y{},但我得到“错误:“}”中的意外'}'。

`result <- sapply(names(data)[1 : 4], 
             function(x) { 
               lapply(names(data)[1 : 4],
                          model <- lm(as.formula(paste0("Grain", "~", "Age", "*", x)), data) 
                          return(list(x = x, 
                                      r.squared = summary(model)$r.squared, 
                                      coefficients =  summary(model)$coefficients))
                      )
             })`

也许一个更有希望的解决方案是使用 lapply 生成回归列表:

reg &lt;- lapply(data[,-c(1:5,8,18)], function(x) summary(lm(data$Grain~ data$Age*x)))

问题在于我一次只能打印所有 150 个摘要——我还没有弄清楚如何在数据框中存储至少 P 值,希望还有 R 平方值。如果 P 值和 R 平方值在不同的数据帧中,则可以。我需要介绍这 150 个预测变量与谷物和年龄的关系,我认为 150 个不同的摘要打印输出的屏幕截图并不理想。感谢您阅读 - 我已尽力检查是否有重复,但如果您认为我错过了某个帖子,请告诉我。

【问题讨论】:

    标签: r


    【解决方案1】:

    您可以使用update 将“预测器”添加到基本公式fo。但是,您的因变量是一个因素(即分类变量),您应该再次考虑您的方法。此外,变量Key 是一个具有 3999 个级别的因子,交互分析可能会一直运行。

    无论如何,我将Grain 转换为数字并向您展示如何使用update。我只将数值变量包含在过程中(排除is.factor)。

    r.squared 我们最好将其存储为属性,因为它不太适合系数表。

    data <- read.csv("X:/Downloads/grain yield by environment long.csv", stringsAsFactors=T)
    ## transform Grain to numeric
    data <- transform(data, Grain=as.numeric(levels(Grain))[Grain])
    
    ## names vector of independent (numeric) variables
    nm <- names(data[!sapply(data, is.factor)])  
    
    ## base formula
    fo <- Grain ~ Age 
    
    ## try out what `update` does
    x <- "LAT"
    update(fo, paste(". ~ . *", x))
    # Grain ~ Age + LAT + Age:LAT
    
    ## using `update` in a small `sapply`
    res <- sapply(nm, function(x){
      smy <- summary(lm(update(fo, paste(". ~ . *", x)), data))
      `attr<-`(smy$coef, "r.squared", smy$r.squared)
    })
    

    结果

    length(res)
    # [1] 138
    
    head(res, 3)
    # $LAT
    #               Estimate Std. Error    t value     Pr(>|t|)
    # (Intercept) -203.80608 247.042950 -0.8249824 4.094316e-01
    # Age          444.71213 115.503286  3.8502119 1.198906e-04
    # LAT           21.48553   5.342822  4.0213824 5.894224e-05
    # Age:LAT      -14.29534   2.502305 -5.7128675 1.193053e-08
    # attr(,"r.squared")
    # [1] 0.3360184
    # 
    # $ID
    #               Estimate Std. Error    t value      Pr(>|t|)
    # (Intercept)  798.15199  14.943853  53.410054  0.000000e+00
    # Age         -214.49895   7.897641 -27.159875 4.876711e-149
    # ID          -144.12033  81.112221  -1.776802  7.567810e-02
    # Age:ID        41.77544  31.049721   1.345437  1.785617e-01
    # attr(,"r.squared")
    # [1] 0.3293592
    # 
    # $Latitude
    #                Estimate Std. Error    t value     Pr(>|t|)
    # (Intercept)  -204.04718 247.054540 -0.8259196 4.088998e-01
    # Age           444.85794 115.509219  3.8512765 1.193725e-04
    # Latitude       21.49072   5.343065  4.0221707 5.874607e-05
    # Age:Latitude  -14.29847   2.502429 -5.7138368 1.186329e-08
    # attr(,"r.squared")
    # [1] 0.3360205
    

    要从特定列表元素的属性访问r.squared,您可以这样做,例如对于LAT

    attr(res$LAT, "r.squared")
    # [1] 0.3360184
    

    【讨论】:

    • 这是朝着正确方向迈出的一步,但是当我尝试定义“res”时,我收到错误Warning messages: 1: In model.matrix.default(mt, mf, contrasts) : the response appeared on the right-hand side and was dropped 2: In model.matrix.default(mt, mf, contrasts) : problem with term 2 in model.matrix: no columns are assigned
    • @ginger_cat 您需要从名称向量nm 中排除"Gear",我们将其用于formula 的右侧,因为它是您的自变量(左-手边)。在我的代码中,这是偶然发生的,因为我通过排除 is.factor 变量来排除它。
    【解决方案2】:

    我已经能够生成三个单独的表格 - 一个用于 P 值,一个用于 R 平方值,一个用于斜率系数。出于某种原因,它们的长度不同,所以我无法将它们绑定到一张表中,但这是我所追求的 95%。我是这方面的新手,所以我愿意接受有关如何使其更优雅和/或更健壮的建议——我必须在一个有 500 列的数据框上再做一次。

    data$Grain<- as.numeric(as.character(data$Grain)) #This should be numeric
    
    ls1 <- list()
    ls2 <- list()
    ls3 <- list()
    ls4 <- list()
    ls5 <- list()
    data2 <- data[-c(1:5,9:15)] #removing non-data rows such as Key, ID, Experiment, etc
    
    for (i in names(data2)){ 
      model <- lm(as.formula(paste0("Grain", "~", "Age", "*", i)), data2)
      pval <- summary(model)$coefficients[,4] #extracts P values for model
      rsq <- summary(model)$r.squared
      slope <- summary(model)$coefficients[,1] #extracts slope coefficients for model
      ls1 <- c(ls1, pval[3]) #extracts P values of third row, which is the predictor i
      ls2 <- c(ls2, pval[4]) #extracts P values of fourth row, which is interaction of predictor i and Age
      ls3 <- c(ls3, rsq)
      ls4 <- c(ls4, slope[3]) #extracts slope of third row, which is the predictor i
      ls5 <- c(ls5, slope[4]) #extracts slope of fourth row, which is interaction of predictor i and Age
    }
    
    
    col1 <- do.call(rbind, ls1) #this puts the list into one column, for easier viewing
    col2 <- do.call(rbind, ls2)
    Rs <- do.call(rbind, ls3)
    col4 <- do.call(rbind, ls4)
    col5 <- do.call(rbind, ls5)
    Pvalues <- cbind(col1,col2)
    slopes <- cbind(col4,col5)
    
    write.csv(Pvalues, file = "C:/Users/.../Pvalues.long.csv", row.names = TRUE)
    write.csv(slopes, file = "C:/Users/.../slopes.long.csv", row.names = TRUE)
    write.csv(Rs, file = "C:/Users/.../Rs.long.csv", row.names = TRUE)
    

    现在我可以轻松地扫描这些文档,以查看哪些预测变量是显着的,它们解释了多少方差,以及它们在什么方向和多大程度上影响响应变量。

    【讨论】:

    • 我收到一条消息Warning messages: 1: In model.matrix.default(mt, mf, contrasts) : the response appeared on the right-hand side and was dropped 2: In model.matrix.default(mt, mf, contrasts) : problem with term 2 in model.matrix: no columns are assigned,但输出与预期一致,因此我将继续使用此解决方案。对此警告的任何见解将不胜感激。
    猜你喜欢
    • 2011-08-01
    • 2015-10-12
    • 2014-06-18
    • 2021-09-10
    • 1970-01-01
    • 2011-04-11
    • 1970-01-01
    相关资源
    最近更新 更多