在 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,请考虑将进程和循环分开。具体来说:
创建一个接收单个 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))
})
}
遍历 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))
我的脚本和前 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,请考虑将进程和循环分开。具体来说:
创建一个接收单个 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)) }) }
遍历 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))