【问题标题】:Importing multiple csv file from different folder and extracting the filename as additionnal columns: headers faith and multifolders case从不同文件夹导入多个 csv 文件并将文件名提取为附加列:标题和多文件夹案例
【发布时间】:2019-06-03 09:08:54
【问题描述】:

使用ldply(包“plyr”)从一个文件夹中导入多个csv文件:标题信仰,以及如何为多个文件夹做到这一点?

设置:
- 台式机:装有 iOS 10.13.6 的 MacBook Pro(2011 年初)
- 软件版本:R 版本 3.5.1 (2018-07-02) -- “羽毛喷雾”
- R 工作室:版本 1.1.456

我想从特定文件夹中导入多个 csv 文件并将它们合并到一个包含 5 列的文件中:Variable1/Variable2/file_name/experiment_nb/pulse_nb 我已经设法从同一个data.frame中的StackOverflow中以前的类似问题从同一个文件夹中导入所有文件,但是,我不确定如何为不同的文件夹执行此操作以及之后每个文件的标题的信念合并,.由于文件太大而无法手动处理(每个文件 200 000 行),我想确保没有任何错误会导致所有后续分析失败,例如每个 csv 文件数据之前的标题行进口的

csv 看起来像这样:“20190409-0001_002.csv”,带有日期,后跟示例中的实验名称 (0001),以及脉冲数 (002)

#setting package and directory
library(plyr)
library(stringr)
setwd("/Users/macbook/Desktop/Project_Folder/File_folder1")

#Creating a list of all the filenames: 
filenames <- list.files(path = "/Users/macbook/Desktop/Project_Folder/File_folder1")

#creating a function to read csv and in the same time adding an additional column with the name of the file
read_csv_filename <- function(filename)
  {
  ret <- read.csv(filename, header=TRUE, sep=",") 
  ret$Source <- filename #EDIT
  ret
}

#importing
import <- ldply(filenames, read_csv_filename)

#making a copy of import
data<-import

#modifying the file name so it removes ".csv" and change the header
data$Source<-str_sub(data$Source, end=-5)
data[1,3]<-"date_expnb_pulsenb"
t<-substr(data[1,3],1,3) 
head(data, n=10)

#create a column with the experiment number, extracted from the file name
data$expnb<-substr(data$Source, 10, 13)
data$expnb<-as.numeric(data$expnb)
head(data, n=10)
tail(data, n=10)

1° 现在我需要设法在同一个文件中导入所有其他文件夹,我最终可以手动完成,因为文件夹的数量是手动可行的(9-10),但我正在考虑为此编写代码以及用于大量实验的未来实验。怎么做 ?首先列出所有文件夹,然后列出这些文件夹中的所有文件,然后将它们重新组合到一个列表文件中?这对 list.files 可行吗? 文件夹名称将如下所示:“20190409-0001”

2° 上面代码 (head(data, n=10)) 的结果如下所示:


> head(data, n=10)
           Time   Channel.A            Source pulsenb expnb
1          (us)         (A)     expnb_pulsenb      NA    NA
2  -20.00200030 -0.29219970 20190409-0001_002       2     1
3  -20.00100030 -0.29219970 20190409-0001_002       2     1


> tail(data, n=10)
                 Time   Channel.A            Source pulsenb expnb
20800511 179.99199405 -0.81815930 20190409-0001_105     105     1
20800512 179.99299405 -0.81815930 20190409-0001_105     105     1

我想在现在的大列表上运行广泛的数据分析,我想知道如何检查在它们中间我没有一些文件标题行。与 csv 文件中的标题相同,ldply 函数是否已经考虑了标题?所有文件头会在“导入”数据框中的单独行中吗?如何检查? (不幸的是,每个文件中大约有 200 行 XXX 行,所以我无法真正手动检查标题)。

我希望我已经添加了所有必需的详细信息并以正确的格式提出问题,因为这是我第一次在这里发帖:)

提前感谢你们的帮助!

【问题讨论】:

  • 有没有办法确定文件夹的名称?它们是否共享其他文件夹没有的通用字符串/名称?或者他们的名字可以通过程序来构造?
  • 进一步:您在一个“问题”中提出了很多问题。也许最好将这篇文章分成不同的“单一”问题,每个问题都有自己的可重复示例。

标签: r


【解决方案1】:

我已经创建了一个文件夹和文件的虚假环境,假设您会在逻辑上重新组合所有文件和文件夹。

# ---
# set up folders and data
lapply( as.list(paste0("iris", 1:3)), dir.create )

iris_write <- function(name) write.csv(x = iris, file = name)
lapply( as.list(paste0("iris", 1:3, "/iris", 1:3, ".csv")), iris_write)

# Supposing you got them all in one folder, one level up
ldir <- list.dirs()
ldir <- ldir[stringr::str_detect(string = ldir, pattern = "iris")] # use 20190409-0001 in your case

# Getting all files
lfiles <- lapply( as.list(ldir), list.files )

# Getting all path
path_fun <- function(dirname) paste0(dirname, "/", list.files(dirname) )
lpath <- lapply( as.list(ldir), path_fun )

使用 r base 或/和包 data.table

# ---
# --- Import, with functions that detect automatically headers, sep + are way faster to read data

# *** Using data.table

library(data.table)
read_csv_filename <- function(filename){  
        ret <- fread(filename)
        ret$Source <- filename #EDIT
        ret
}

ldata <- lapply( lpath , read_csv_filename )

# --- if you want to regroup them
# with r base
df_final <- do.call("rbind", ldata)
# using data.table
df_final <- rbindlist(ldata)

使用包 dplyr

# *** using dplyr
library(dplyr)
read_csv_filename2 <- function(filename){  
        ret <- reader(filename)
        ret$Source <- filename #EDIT
        ret
}

ldata <- lapply( lpath , read_csv_filename )
df_final <- bind_rows(ldata)

# you may do this with plyr::ldply also
df_final2 <- plyr::ldply(ldata, data.frame)

# *** END loading

最后的建议:工具包中的 file_path_sans_ext

# modifying the file name so it removes ".csv" and change the header
library(tools)
data$Source <- tools::file_path_sans_ext( data$Source )

#create a column with the experiment number, extracted from the file name
data$expnb <- substr(data$Source, 10, 13)
data$expnb <- as.numeric(data$expnb)

希望有帮助:)

【讨论】:

  • 仅供参考,您可以一次性完成上述许多步骤。看到这个stackoverflow.com/a/48105838/786542
  • 感谢您对@Tung 的好回答的提示!顺便说一句,您的条形图中的时间是作为一次性实验给出的,还是它们是微基准的手段?我看到 Dirk Eddelbuettel 也提供了答案,我也会调查一下。
  • 基准测试由vroom 包所有者完成。代码在这里github.com/r-lib/vroom/tree/master/inst/bench
【解决方案2】:

我也会使用purrrmap_dfr添加我的解决方案

生成数据

这只会在临时目录中生成大量 csv 文件供我们操作。这是帮助我们为您解答问题的好方法。

library(tidyverse)
library(fs)

temp_directory <- tempdir()

library(nycflights13)
library(nycflights13)
purrr::iwalk(
  split(flights, flights$carrier),
  ~ { str(.x$carrier[[1]]); vroom::vroom_write(.x, paste0(temp_directory,"/", glue::glue("flights_{.y}.csv")), 
                                               delim = ",") }
)

自定义函数

看起来您有一个自定义函数来读取一些信息,因为文件的格式可能不同。这是我对你所做的事情的破解。

# List of files
my_files <- fs::dir_ls(temp_directory, glob = "*.csv")

custom_read_csv <- function(file){
  # Read without colnames
  ret <- read_csv(file, col_names = FALSE)

  # Pull out column names
  my_colnames <- unlist(ret[1,])

  # Remove the row
  ret <- ret[-1,]

  # Assign the column names
  colnames(ret) <- my_colnames

  # Trick to remove the alpha in a row you know should be time
  ret <- filter(ret, !is.na(as.numeric(T)))

}

现在您可以使用自定义函数读取所有文件,并使用 map_dfr 组合成一个数据框:

all_files <- map_dfr(my_files, custom_read_csv, .id = "filename")

head(all_files)

看起来像这样:

> head(all_files)
# A tibble: 6 x 20
  filename year  month day   dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay carrier flight tailnum
  <chr>    <chr> <chr> <chr> <chr>    <chr>          <chr>     <chr>    <chr>          <chr>     <chr>   <chr>  <chr>  
1 C:/User~ 2013  1     1     810      810            0         1048     1037           11        9E      3538   N915XJ 
2 C:/User~ 2013  1     1     1451     1500           -9        1634     1636           -2        9E      4105   N8444F 
3 C:/User~ 2013  1     1     1452     1455           -3        1637     1639           -2        9E      3295   N920XJ 
4 C:/User~ 2013  1     1     1454     1500           -6        1635     1636           -1        9E      3843   N8409N 
5 C:/User~ 2013  1     1     1507     1515           -8        1651     1656           -5        9E      3792   N8631E

您可以使用以下语法删除根路径(我的路径现在在那里):

all_files %>% 
  mutate(filename = str_remove(filename, "C:/Users/AppData/Local/Temp/RtmpkdmJCE/"))

【讨论】:

    猜你喜欢
    • 2023-02-05
    • 2013-04-11
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    • 2020-09-27
    • 2021-12-14
    相关资源
    最近更新 更多