将多个 CSV 文件读入单独的数据帧
Posted
技术标签:
【中文标题】将多个 CSV 文件读入单独的数据帧【英文标题】:Read multiple CSV files into separate data frames 【发布时间】:2011-07-16 05:53:07 【问题描述】:假设我们在目录 C 中有文件 file1.csv、file2.csv、... 和 file100.csv :\R\Data 并且我们希望将它们全部读入单独的数据帧(例如 file1、file2、... 和 file100)。
这样做的原因是,尽管名称相似,但它们具有不同的文件结构,因此将它们放在列表中并没有多大用处。
我可以使用lapply
,但这会返回一个包含 100 个数据帧的列表。相反,我希望在全球环境中使用这些数据框。
如何将多个文件直接读取到全局环境中?或者,或者,如何将数据框列表的内容解压缩到其中?
【问题讨论】:
@Roman Luštrik 请参阅下面对@hadley 的评论。注意我没有问“将 X 个文件读入 R 的最佳方法是什么?”。我的问题更具体是有原因的。我想我不应该说我想阅读 100 个文件(只是试图通用),而是 8 个具有相似名称的不同文件。但是这里的人太多了。 对于看到这篇文章并拥有一组 100 个相同(或几乎如此)结构文件的人,最好的办法是将数据读入一个命名列表,如下面的 hadley 和 joran 解释的。从另一个角度来看,请查看 Gregor 对 this post 的回复,了解为什么这是有益的。 【参考方案1】:谢谢大家的回复。
为了完整起见,这里是我加载任意数量的(制表符)分隔文件的最终答案,在这种情况下,每列有 6 列数据,其中第 1 列是字符,2 是因子,其余是数字:
##Read files named xyz1111.csv, xyz2222.csv, etc.
filenames <- list.files(path="../Data/original_data",
pattern="xyz+.*csv")
##Create list of data frame names without the ".csv" part
names <-substr(filenames,1,7)
###Load all files
for(i in names)
filepath <- file.path("../Data/original_data/",paste(i,".csv",sep=""))
assign(i, read.delim(filepath,
colClasses=c("character","factor",rep("numeric",4)),
sep = "\t"))
【讨论】:
for(i in 1:length(names)【参考方案2】:草稿,未经测试:
使用list.files()
又名dir()
动态生成您的文件列表。
这会返回一个向量,只是在for
循环中沿着向量运行。
读取第i个文件,然后使用assign()
将内容放入一个新的变量file_i中
这应该对你有用。
【讨论】:
@Dirk Eddelbuettel 谢谢,那行得通。事实上,这就是我最初尝试做的,但在循环中使用i <- read.csv(...)
而不是assign(i,read.csv(...))
。为什么前者不起作用?
本地范围与全球环境。你也可以试试i <<- read.csv(...)
。
@Dirk Eddelbuettel 非常感谢,最后一个问题:如果我使用了lapply
并将所有内容都倾倒在一个列表中,我将如何“解压”它?我问是因为lapply
要快得多,而且我不喜欢循环。
证明lapply
读取N个文件的速度更快。此外,如果 you 不喜欢循环,那么阅读 *apply
家族的负担就落在了你身上。再说一次,这些天它们通常不更快。
Yowser,分配和
【参考方案3】:
将assign
与包含所需数据框名称的字符变量一起使用。
for(i in 1:100)
oname = paste("file", i, sep="")
assign(oname, read.csv(paste(oname, ".txt", sep="")))
【讨论】:
【参考方案4】:此答案旨在作为对 Hadley 答案的更有用的补充。
虽然 OP 特别希望将每个文件作为单独的对象读入他们的 R 工作区,但许多其他天真地提出这个问题的人可能认为这就是他们想要的这样做,实际上他们最好将文件读入单个数据帧列表中。
所以为了记录,这里是你可以这样做的方法。
#If the path is different than your working directory
# you'll need to set full.names = TRUE to get the full
# paths.
my_files <- list.files("path/to/files")
#Further arguments to read.csv can be passed in ...
all_csv <- lapply(my_files,read.csv,...)
#Set the name of each list element to its
# respective file name. Note full.names = FALSE to
# get only the file names, not the full path.
names(all_csv) <- gsub(".csv","",
list.files("path/to/files",full.names = FALSE),
fixed = TRUE)
现在任何文件都可以通过my_files[["filename"]]
引用,这实际上并没有更糟糕 在您的工作区中仅具有单独的filename
变量,而且通常更方便.
【讨论】:
【参考方案5】:这是一种仅使用 lapply 解压 data.frames 列表的方法
filenames <- list.files(path="../Data/original_data",
pattern="xyz+.*csv")
filelist <- lappy(filenames, read.csv)
#if necessary, assign names to data.frames
names(filelist) <- c("one","two","three")
#note the invisible function keeps lapply from spitting out the data.frames to the console
invisible(lapply(names(filelist), function(x) assign(x,filelist[[x]],envir=.GlobalEnv)))
【讨论】:
您可以使用paste0("sheet_",1:length(filelist))
“自动”命名。
当我使用这个方法时,我的列名之间的空格被替换为“.”。例如,列“仓库代码”变为“仓库代码”。你知道如何保持列格式不变吗?
嗨!我想知道,我如何将多个参数传递给read.csv
函数而不是使用默认参数调用它?例如。 read.csv(as.is = T, header = T, comment.char = "")
.【参考方案6】:
从全局环境访问列表元素的简单方法是attach
列表。请注意,这实际上在搜索路径上创建了一个新环境并将列表的元素复制到其中,因此您可能希望在附加后删除原始列表,以防止出现两个可能不同的副本。
【讨论】:
我赞成,但示例代码会更好。 不确定您在寻找什么。示例代码为attach(mylist)
。
谢谢亚伦。我试图将您的答案与原始问题联系起来,它与 list.files
到 assign
的关系以及其他答案中提到的其他内容。【参考方案7】:
从一个文件夹中读取所有 CSV 文件并创建与文件名相同的 vactor:
setwd("your path to folder where CSVs are")
filenames <- gsub("\\.csv$","", list.files(pattern="\\.csv$"))
for(i in filenames)
assign(i, read.csv(paste(i, ".csv", sep="")))
【讨论】:
【参考方案8】:一个简化版本,假设您的 csv 文件位于工作目录中:
listcsv <- list.files(pattern= "*.csv") #creates list from csv files
names <- substr(listcsv,1,nchar(listcsv)-4) #creates list of file names, no .csv
for (k in 1:length(listcsv))
assign(names[[k]] , read.csv(listcsv[k]))
#cycles through the names and assigns each relevant dataframe using read.csv
【讨论】:
【参考方案9】:#copy all the files you want to read in R in your working directory
a <- dir()
#using lapply to remove the".csv" from the filename
for(i in a)
list1 <- lapply(a, function(x) gsub(".csv","",x))
#Final step
for(i in list1)
filepath <- file.path("../Data/original_data/..",paste(i,".csv",sep=""))
assign(i, read.csv(filepath))
【讨论】:
以上是关于将多个 CSV 文件读入单独的数据帧的主要内容,如果未能解决你的问题,请参考以下文章
读取 zip 中的所有 csv 文件,并将相应的 csv 文件名作为数据帧变量名