假设我们有一个包含多个data.csv文件的文件夹,每个文件包含相同数量的变量,但每个变量来自不同的时间。 在R中是否有一种方法可以同时导入它们而不是逐个导入?

我的问题是我有大约2000个数据文件要导入,并且只能通过使用代码单独导入它们:

read.delim(file="filename", header=TRUE, sep="\t")

效率不高。


当前回答

使用purrr并将文件id作为列:

library(tidyverse)


p <- "my/directory"
files <- list.files(p, pattern="csv", full.names=TRUE) %>%
    set_names()
merged <- files %>% map_dfr(read_csv, .id="filename")

如果没有set_names(), .id=将使用整数指示符,而不是实际的文件名。

如果你想要一个短的文件名而不是完整的路径:

merged <- merged %>% mutate(filename=basename(filename))

其他回答

下面是一些使用R base将.csv文件转换为data.frame的选项,以及一些可用来读取R文件的包。

这比下面的选项要慢。

# Get the files names
files = list.files(pattern="*.csv")
# First apply read.csv, then rbind
myfiles = do.call(rbind, lapply(files, function(x) read.csv(x, stringsAsFactors = FALSE)))

编辑:-更多的额外选择使用数据。表和读取器

一个fread()版本,它是数据的函数。表方案。这是目前为止R中最快的选项。

library(data.table)
DT = do.call(rbind, lapply(files, fread))
# The same using `rbindlist`
DT = rbindlist(lapply(files, fread))

使用readr,这是另一个读取csv文件的包。它比fread慢,比base R快,但功能不同。

library(readr)
library(dplyr)
tbl = lapply(files, read_csv) %>% bind_rows()

除了使用lapply或R中的其他循环构造,您还可以将CSV文件合并到一个文件中。

在Unix中,如果文件没有头文件,那么很简单:

cat *.csv > all.csv

或者如果有标题,你可以找到一个字符串匹配标题,只有标题(即假设标题行都以“年龄”开头),你会这样做:

cat *.csv | grep -v ^Age > all.csv

我认为在Windows中,你可以通过DOS命令框中的COPY和SEARCH(或FIND或其他什么)来做到这一点,但为什么不安装cygwin并获得Unix命令shell的强大功能呢?

我喜欢使用list.files(), lapply()和list2env()(或fs::dir_ls(), purrr::map()和list2env())的方法。这看起来既简单又灵活。

或者,您可以尝试小包{tor} (to-R):默认情况下,它将文件从工作目录导入到列表(list_*()变量)或全局环境(load_*()变量)。

例如,这里我使用tor::list_csv()将我工作目录中的所有.csv文件读入一个列表:

library(tor)

dir()
#>  [1] "_pkgdown.yml"     "cran-comments.md" "csv1.csv"        
#>  [4] "csv2.csv"         "datasets"         "DESCRIPTION"     
#>  [7] "docs"             "inst"             "LICENSE.md"      
#> [10] "man"              "NAMESPACE"        "NEWS.md"         
#> [13] "R"                "README.md"        "README.Rmd"      
#> [16] "tests"            "tmp.R"            "tor.Rproj"

list_csv()
#> $csv1
#>   x
#> 1 1
#> 2 2
#> 
#> $csv2
#>   y
#> 1 a
#> 2 b

现在我用tor::load_csv()将这些文件加载到我的全局环境中:

# The working directory contains .csv files
dir()
#>  [1] "_pkgdown.yml"     "cran-comments.md" "CRAN-RELEASE"    
#>  [4] "csv1.csv"         "csv2.csv"         "datasets"        
#>  [7] "DESCRIPTION"      "docs"             "inst"            
#> [10] "LICENSE.md"       "man"              "NAMESPACE"       
#> [13] "NEWS.md"          "R"                "README.md"       
#> [16] "README.Rmd"       "tests"            "tmp.R"           
#> [19] "tor.Rproj"

load_csv()

# Each file is now available as a dataframe in the global environment
csv1
#>   x
#> 1 1
#> 2 2
csv2
#>   y
#> 1 a
#> 2 b

如果您需要读取特定的文件,您可以使用regexp, ignore匹配它们的文件路径。大小写颠倒。


为了获得更大的灵活性,请使用list_any()。它允许您通过参数.f提供reader函数。

(path_csv <- tor_example("csv"))
#> [1] "C:/Users/LeporeM/Documents/R/R-3.5.2/library/tor/extdata/csv"
dir(path_csv)
#> [1] "file1.csv" "file2.csv"

list_any(path_csv, read.csv)
#> $file1
#>   x
#> 1 1
#> 2 2
#> 
#> $file2
#>   y
#> 1 a
#> 2 b

通过…传递附加参数或者在函数内部。

path_csv %>% 
  list_any(readr::read_csv, skip = 1)
#> Parsed with column specification:
#> cols(
#>   `1` = col_double()
#> )
#> Parsed with column specification:
#> cols(
#>   a = col_character()
#> )
#> $file1
#> # A tibble: 1 x 1
#>     `1`
#>   <dbl>
#> 1     2
#> 
#> $file2
#> # A tibble: 1 x 1
#>   a    
#>   <chr>
#> 1 b

path_csv %>% 
  list_any(~read.csv(., stringsAsFactors = FALSE)) %>% 
  map(as_tibble)
#> $file1
#> # A tibble: 2 x 1
#>       x
#>   <int>
#> 1     1
#> 2     2
#> 
#> $file2
#> # A tibble: 2 x 1
#>   y    
#>   <chr>
#> 1 a    
#> 2 b

基于dnlbrk的注释,对于大文件,assign可以比list2env快得多。

library(readr)
library(stringr)

List_of_file_paths <- list.files(path ="C:/Users/Anon/Documents/Folder_with_csv_files/", pattern = ".csv", all.files = TRUE, full.names = TRUE)

通过将full.names参数设置为true,您将在文件列表中获得每个文件的完整路径作为单独的字符串,例如,List_of_file_paths[1]将类似于"C:/Users/Anon/Documents/Folder_with_csv_files/ fil1 .csv"

for(f in 1:length(List_of_filepaths)) {
  file_name <- str_sub(string = List_of_filepaths[f], start = 46, end = -5)
  file_df <- read_csv(List_of_filepaths[f])  
  assign( x = file_name, value = file_df, envir = .GlobalEnv)
}

你可以利用这些数据。table package的fread或base R read.csv而不是read_csv。file_name步骤允许您整理名称,以便每个数据帧不保留文件的完整路径作为其名称。 在将数据表传输到全局环境之前,您可以扩展循环对数据表做进一步的处理,例如:

for(f in 1:length(List_of_filepaths)) {
  file_name <- str_sub(string = List_of_filepaths[f], start = 46, end = -5)
  file_df <- read_csv(List_of_filepaths[f])  
  file_df <- file_df[,1:3] #if you only need the first three columns
  assign( x = file_name, value = file_df, envir = .GlobalEnv)
}

这是我开发的代码,读取所有csv文件到R.它将为每个csv文件单独创建一个dataframe,并标题dataframe文件的原始名称(删除空格和.csv),我希望你发现它有用!

path <- "C:/Users/cfees/My Box Files/Fitness/"
files <- list.files(path=path, pattern="*.csv")
for(file in files)
{
perpos <- which(strsplit(file, "")[[1]]==".")
assign(
gsub(" ","",substr(file, 1, perpos-1)), 
read.csv(paste(path,file,sep="")))
}