在读取和绑定多个文件时,将"filename"列添加到表中

kra*_*ray 5 r lapply

我在多个目录中有许多csv文件,我想读入R tribble或data.table.我使用"list.files()"并将递归参数设置为TRUE来创建文件名和路径列表,然后使用"lapply()"读入多个csv文件,然后"bind_rows()"将它们全部粘在一起一起:

filenames <- list.files(path, full.names = TRUE, pattern = fileptrn, recursive = TRUE)
tbl <- lapply(filenames, read_csv) %>% 
  bind_rows()
Run Code Online (Sandbox Code Playgroud)

这种方法很好.但是,我需要从每个文件名中提取一个子字符串,并将其作为列添加到最终表中.我可以使用"str_extract()"得到我需要的子字符串,如下所示:

sites <- str_extract(filenames, "[A-Z]{2}-[A-Za-z0-9]{3}")
Run Code Online (Sandbox Code Playgroud)

然而,我被困在如何将提取的子字符串添加为列,因为lapply()通过read_csv()为每个文件运行.

Soi*_*Guy 9

tidyverse方法:

更新:

read_csvreadr2.0(及更高版本)开始,现在内置支持在单个命令中将具有相同列的文件列表读取到一个输出表中。只需将同一向量中要读取的文件名传递给读取函数即可。例如读取 csv 文件:

(files <- fs::dir_ls("D:/data", glob="*.csv$"))
dat <- read_csv(files, id="path")
Run Code Online (Sandbox Code Playgroud)

或者使用map_dfrwith purrr:使用 加载 .csv 文件的示例.id = "source"中的参数添加文件名:purrr::map_dfr()

 # specify the directory, then read a list of files
  data_dir <- here("file/path")
  data_list <- fs::dir_ls(data_dir, regexp = ".csv$")

 # return a single data frame w/ purrr:map_dfr 
 my_data = data_list %>% 
    purrr::map_dfr(read_csv, .id = "source")
  
 # Alternatively, rename source from the file path to the file name
  my_data = data_list %>% 
    purrr::map_dfr(read_csv, .id = "source") %>% 
    dplyr::mutate(source = stringr::str_replace(source, "file/path", ""))
  
Run Code Online (Sandbox Code Playgroud)


Kon*_*lph 7

我通常使用以下方法,基于dplyr/tidyr:

data = tibble(File = files) %>%
    extract(File, "Site", "([A-Z]{2}-[A-Za-z0-9]{3})", remove = FALSE) %>%
    mutate(Data = lapply(File, read_csv)) %>%
    unnest(Data) %>%
    select(-File)
Run Code Online (Sandbox Code Playgroud)


CPa*_*Pak 5

您可以在此处使用purrr::map2,其工作方式与 mapply 类似

filenames <- list.files(path, full.names = TRUE, pattern = fileptrn, recursive = TRUE)
sites <- str_extract(filenames, "[A-Z]{2}-[A-Za-z0-9]{3}")  # same length as filenames

library(purrr)
library(dplyr)
library(readr)
stopifnot(length(filenames)==length(sites))  # returns error if not the same length
ans <- map2(filenames, sites, ~read_csv(.x) %>% mutate(id = .y))  # .x is element in filenames, and .y is element in sites
Run Code Online (Sandbox Code Playgroud)

的输出map2是一个列表,类似于lapply

如果您有 的开发版本purrr,则可以使用,它是带有索引的imap包装器map2