在 R 中如何循环遍历 csv 文件和新数据帧中线性回归的安全输出?

In R how to loop through csv files and safe outputs of linear regression in new dataframe?

我的脚本和前 3 个 csv 文件之一可以在我的 Github 文件夹中找到

我已将 NDVI 和气候数据列表拆分为小型 csv。每个文件包含 34 年的数据。

然后每34年应该根据冲突年份分成两部分,保存在相同的table和一定的时间范围内。但是这部分代码已经可以工作了。

现在我想用第一部分的气候数据控制列表的第二部分,通过使用多元线性回归,这也完成了。

我基本上需要做一个循环来存储一个 csv 的 lm 函数每一轮的所有系数。新列表中的文件。

我知道我可以使用 lapply 循环并将输出作为列表获取。但是实际上循环遍历 csv 有一些缺失的部分。文件。

#load libraries
library(ggplot2)
library(readr)
library(tidyr)
library(dplyr)
library(ggpubr)
library(plyr)
library(tidyverse)
library(fs)


file_paths <- fs::dir_ls("E:\PYTHON_ST\breakCSV_PYTHON\AIM_2_regions\Afghanistan")
file_paths

#create empty list and fill with file paths and loop through them
file_contents <- list()
for (i in seq_along(file_paths)) { #seq_along for vectors (list of file paths is a vector)
  file_contents[[i]] <- read_csv(file = file_paths[[i]])
                  
                for (i in seq_len(file_contents[[i]])){ # redundant?
                  
                 # do all the following steps in every file                                        
                 
                 # Step 1) 
                 # Define years to divide table
                 
                 #select conflict year in df 
                 ConflictYear = file_contents[[i]][1,9]
                 ConflictYear
                 
                 # select Start year of regression in df
                 SlopeYears = file_contents[[i]][1,7] #to get slope years (e.g.17)
                 BCStartYear = ConflictYear-SlopeYears #to get start year for regression
                 BCStartYear
                 
                 #End year of regression
                 ACEndYear = ConflictYear+(SlopeYears-1) # -1 because the conflict year is included
                 ACEndYear
                 
                 
                 # Step 2
                 
                 #select needed rows from df
                 #no headers but row numbers. NDVI.Year = [r1-r34,c2]
                 NDVI.Year <- file_contents[[i]][1:34,2]
                 NDVI <- file_contents[[i]][1:34,21]
                 T.annual.max <- file_contents[[i]][1:34,19]
                 Prec.annual.max <- file_contents[[i]][1:34,20]
                 soilM.annual.max <- file_contents[[i]][1:34,18]
                 
                 #Define BeforeConf and AfterConf depending on Slope Year number and Conflict Years
                 #Go through NDVI.Year till Conflict.Year (-1 year) since the conflict year is not included in bc
                 BeforeConf1 <- file_contents[[i]][ which(file_contents[[i]]$NDVI.Year >= BCStartYear & file_contents[[i]]$NDVI.Year < ConflictYear),] #eg. 1982 to 1999
                 BeforeConf2 <-  c(NDVI.Year, NDVI, T.annual.max, Prec.annual.max, soilM.annual.max) #which columns to include
                 BeforeConf <- BeforeConf1[BeforeConf2] #create table
                 
                 AfterConf1 <- myFiles[ which(file_contents[[i]]$NDVI.Year >= ConflictYear & file_contents[[i]]$NDVI.Year <= ACEndYear),] #eg. 1999 to 2015
                 AfterConf2 <-  c(NDVI.Year, NDVI, T.annual.max, Prec.annual.max, soilM.annual.max)
                 AfterConf <- AfterConf1[AfterConf2]
                 
                 #Step 3)a)
                 #create empty list, to fill with coefficient results from each model results for each csv file and safe in new list
                 
                 #Create an empty df for the output coefficients
                 names <- c("(Intercept)","BeforeConf$T.annual.max","BeforeConf$Prec.annual.max","BeforeConf$soilM.annual.max")
                 coef_df <- data.frame()
                 for (k in names) coef_df[[k]] <- as.character() 
                 
                 #Apply Multiple Linear Regression
                 plyrFunc <- function(x){
                   model <- lm(NDVI ~ T.annual.max + Prec.annual.max + soilM.annual.max, data = BeforeConf)
                   return(summary(model)$coefficients[1,1:4])
                 }
                 
                 coef_df <- ddply(BeforeConf, .(), x)
                 coef_DF
    }}

由于您的代码适用于单个 CSV,请考虑将进程和循环分开。具体来说:

  1. 创建一个接收单个 csv 路径作为输入参数的函数,并完成 单个 文件所需的一切。

    get_coeffs <- function(csv_path) {
      df <- read.csv(csv_path)
    
      ### Step 1
      # select conflict year, start year, and end year in df 
      ConflictYear <- df[1,9]
      SlopeYears <- df[1,7]                       # to get slope years (e.g.17)
      BCStartYear <- ConflictYear - SlopeYears    # to get start year for regression
      ACEndYear <- ConflictYear + (SlopeYears-1)  # -1 because the conflict year is included
    
      ### Step 2
      # select needed rows from df
      #no headers but row numbers. NDVI.Year = [r1-r34,c2]
      NDVI.Year <- df[1:34, 2]
      NDVI <- df[1:34, 21]
      T.annual.max <- df[1:34, 19]
      Prec.annual.max <- df[1:34, 20]
      soilM.annual.max <- df[1:34, 18]
    
      # Define BeforeConf and AfterConf depending on Slope Year number and Conflict Years
      # Go through NDVI.Year till Conflict.Year (-1 year) since the conflict year is not included in bc
      BeforeConf1 <- df[ which(df$NDVI.Year >= BCStartYear & df$NDVI.Year < ConflictYear),]
      BeforeConf2 <- c(NDVI.Year, NDVI, T.annual.max, Prec.annual.max, soilM.annual.max)
      BeforeConf  <- BeforeConf1[BeforeConf2] #create table
    
      AfterConf1 <- myFiles[ which(df$NDVI.Year >= ConflictYear & df$NDVI.Year <= ACEndYear),]
      AfterConf2 <- c(NDVI.Year, NDVI, T.annual.max, Prec.annual.max, soilM.annual.max)
      AfterConf  <- AfterConf1[AfterConf2]
    
      ### Step 3
      tryCatch({
          # Run model and return coefficients
          model <- lm(NDVI ~ T.annual.max + Prec.annual.max + soilM.annual.max, data = BeforeConf) 
          return(summary(model)$coefficients[1,1:4])
      }, error = function(e) {
          print(e)
          return(rep(NA, 4))
      })
    }
    
  2. 遍历 csv 路径,将每个文件传递到您的函数中,构建您可以使用 lapply for list return 或 sapply 处理的结果列表(或指定长度和类型的vapply)用于简化的return,例如矢量,matrix/array(如果适用)。

    mypath <- "E:\PYTHON_ST\breakCSV_PYTHON\AIM_2_regions\Afghanistan"
    file_paths <- list.files(pattern=".csv", path=mypath)
    
    # LIST RETURN
    result_list <- lapply(file_paths, get_coeffs)
    
    # MATRIX RETURN
    results_matrix <- sapply(file_paths, get_coeffs)
    results_matrix <- vapply(file_paths, get_coeffs, numeric(4))