首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从不同文件夹导入多个csv文件,并将文件名提取为附加列:标题、信念和多文件夹大小写

从不同文件夹导入多个csv文件,并将文件名提取为附加列:标题、信念和多文件夹大小写
EN

Stack Overflow用户
提问于 2019-06-03 09:08:54
回答 2查看 656关注 0票数 1

使用ldply (包"plyr")从一个文件夹导入多个csv文件:标题信念,以及如何对多个文件夹进行导入?

设立:

  • 桌面: MacBook Pro (2011年初)和iOS 10.13.6
  • 软件版本:r版本3.5.1 (2018-07-02) --“羽毛喷雾”
  • R工作室: 1.1.456版

我想从特定的文件夹中导入多个csv文件,并将它们合并为一个文件,其中包含5列: Variable1/Variable2/file_name/experiment_nb/pulse_nb我已经成功地从同一个data.frame中以前的类似问题中导入了来自同一个文件夹的所有文件,但是,我不知道如何对不同的文件夹和合并后的每个文件的头进行导入。由于文件太大,无法手动处理(每个文件有20万行),所以我希望确保没有任何错误会导致所有后续分析失败,例如导入每个csv文件的数据之前的头行。

csv看起来是这样的:"20190409-0001_002.csv“,后面跟着示例中的实验名称(0001)和脉冲数(002)。

代码语言:javascript
运行
复制
#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“

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

代码语言:javascript
运行
复制
> 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

代码语言:javascript
运行
复制
> 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,所以我不能真正手动检查头)。

我希望我增加了所有所需的细节,并以正确的格式提出问题,因为这是我第一次在这里发帖:)

提前感谢你们的帮助!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-03 11:33:52

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

生成数据

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

代码语言:javascript
运行
复制
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 = ",") }
)

自定义函数

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

代码语言:javascript
运行
复制
# 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组合成一个单一的数据格式。

代码语言:javascript
运行
复制
all_files <- map_dfr(my_files, custom_read_csv, .id = "filename")

head(all_files)

看起来是这样的:

代码语言:javascript
运行
复制
> 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

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

代码语言:javascript
运行
复制
all_files %>% 
  mutate(filename = str_remove(filename, "C:/Users/AppData/Local/Temp/RtmpkdmJCE/"))
票数 1
EN

Stack Overflow用户

发布于 2019-06-03 11:13:47

我创建了一个文件夹和文件的假环境,假设您将逻辑地重新组合所有的文件和文件夹。

代码语言:javascript
运行
复制
# ---
# 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或/和包data.table

代码语言:javascript
运行
复制
# ---
# --- 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

代码语言:javascript
运行
复制
# *** 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

代码语言:javascript
运行
复制
# 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)

希望有此帮助:)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56424205

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档