列表元素在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 个变量之一 a
、b
、c
或 d
。而且您正在重复使用这些变量名称,因此它们会被覆盖。
执行此操作的“正确”方法是使用 lapply
代替 for
循环。将文件列表和所需函数(即 open_csv_core
等)传递给 lapply
,返回的 return 值是结果列表。
实际上,您的两个 csv 读取功能完全相同,
除了路径不同。
如果您找到一种使用抽象路径而不是相对路径列出文件的方法
路径(只是文件名),你不需要像这样重建路径
你做。这可以通过 full.names = TRUE
在 list.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
的内容...(结果列表)。
我有一堆 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 个变量之一 a
、b
、c
或 d
。而且您正在重复使用这些变量名称,因此它们会被覆盖。
执行此操作的“正确”方法是使用 lapply
代替 for
循环。将文件列表和所需函数(即 open_csv_core
等)传递给 lapply
,返回的 return 值是结果列表。
实际上,您的两个 csv 读取功能完全相同, 除了路径不同。
如果您找到一种使用抽象路径而不是相对路径列出文件的方法
路径(只是文件名),你不需要像这样重建路径
你做。这可以通过 full.names = TRUE
在 list.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
的内容...(结果列表)。