列表元素在for循环R中被覆盖?

List elements getting overwritten in for loop R?

我有一堆 csv 文件,我试图一次将它们全部读入 R,csv 中的每个数据帧都成为列表的一个元素。循环在很大程度上起作用,但它们不断覆盖列表元素。因此,例如,如果我遍历前 2 个文件,list[[1]] 和 list[[2]] 中的数据框都将包含第二个文件的数据框。

#function to open one group of files named with "cores"
open_csv_core<- function(year, orgtype){
  file<- paste(year, "/coreco.core", year, orgtype, ".csv", sep = "")
  df <- read.csv(file)
  names(df) <- tolower(names(df))
  df <- df[df$ntee1 %in% c("C","D"),]
  df<- df[!(df$nteecc %in% c("D20","D40", "D50", "D60", "D61")),]
  return(df)
}

#function to open one group of files named with "nccs"
open_csv_nccs<- function(year, orgtype){
  file2<- paste(year, "/nccs.core", year, orgtype, ".csv", sep="")
  df2 <- read.csv(file2)
  names(df2) <- tolower(names(df2))
  df2 <- df2[df2$ntee1 %in% c("C","D"),]
  df2<- df2[!(df2$nteecc %in% c("D20","D40", "D50", "D60", "D61")),]
  return(df2)
}
#############################################################################
yrpc<- list()
yrpf<- list()
yrco<- list()
fname<- vector()
file_yrs<- as.character(c(1989:2019))
for(i in 1:length(file_yrs)){
  
  fname<- list.files(path = file_yrs[i], pattern = NULL)

#accessing files in a folder and assigning to the proper function to open them based on how the file is named  
for(j in 1:length(fname)){
    
    if(grepl("pc.csv", fname[j])==T) { 
      
      if(grepl("nccs", fname[j])==T){
        a <- open_csv_nccs(file_yrs[j], "pc") 
        yrpc[[paste0(file_yrs[i], "pc")]] <- a
        
      } else {
        b<- open_csv_core(file_yrs[j], "pc")
        yrpc[[paste0(file_yrs[i], "pc")]] <- b
      }
      
    } else if (grepl("pf.csv", fname[j])==T){
      
      if(grepl("nccs", fname[j])==T){
        c <- open_csv_nccs(file_yrs[j], "pf")
        yrpf[[paste0(file_yrs[i], "pf")]] <- c
        
      } else {
        d<- open_csv_core(file_yrs[j], "pf")
        yrpf[[paste0(file_yrs[i], "pf")]] <- d
      }
      
    } else {
      
      if(grepl("nccs", fname[j])==T){
        e<- open_csv_nccs(file_yrs[j], "co")
        yrco[[paste0(file_yrs[i], "co")]] <- e
        
      } else {
        f<- open_csv_core(file_yrs[j], "co")
        yrco[[paste0(file_yrs[i], "co")]] <- f
      }
    }
    
    
  }

}

您的 for(j in 1:length(fname)){... 中似乎正在创建 4 个变量之一 abcd。而且您正在重复使用这些变量名称,因此它们会被覆盖。

执行此操作的“正确”方法是使用 lapply 代替 for 循环。将文件列表和所需函数(即 open_csv_core 等)传递给 lapply,返回的 return 值是结果列表。

实际上,您的两个 csv 读取功能完全相同, 除了路径不同。

如果您找到一种使用抽象路径而不是相对路径列出文件的方法 路径(只是文件名),你不需要像这样重建路径 你做。这可以通过 full.names = TRUElist.files().

中实现

第二点,好像从来没有同年同款的 除了“coreco.core”文件外,还有一个“nccs.core”文件。所以他们是相互的 独家的。那么,就没有必要的逻辑来区分这些情况,从而简化了我们的代码。

第三点是,您只想按文件类型(“pc”、“pf”、“co”)和年份分隔数据帧。

我不会为每种类型创建 3 个列表,而是创建一个 res-ults 列表,其中为每种类型包含一个内部列表。

我会这样解决:

years <- c(1989:2019) 

path_to_type <- function(path) gsub(".*(pc|pf|co)\.csv", "\1", path)

res <- list("pc" = list(),
            "pf" = list(),
            "co" = list())

lapply(years, function(year) {
  files <- list.files(path = year, pattern = "\.csv", full.names = TRUE)
  dfs <- lapply(files, function(path) {
    print(path) # just to signal that the path is getting processed
    df <- read.csv(path)
    file_type <- path_to_type(path)
    names(df) <- tolower(names(df))
    df <- df[df$ntee1 %in% c("C", "D"), ]
    df <- df[!(df$nteecc %in% c("D20", "D40", "D50", "D60", "D61")), ]
    res[[file_type]][[year]] <- df
  })
}) 

现在您可以通过 file_type 和年份从结果列表中调用 例如:

res[["co"]][[1995]]
res[["pf"]][[2018]]

以此类推

实际上,在这种情况下 lapply() 调用的结果是 没意思。只是 res 的内容...(结果列表)。