Импорт нескольких CSV-файлов из другой папки и извлечение имени файла в виде дополнительных столбцов: случай заголовков и случай мультифолдеров - PullRequest
0 голосов
/ 03 июня 2019

Использование ldply (пакет "plyr") для импорта нескольких файлов CSV из папки: заголовок веры, и как это сделать для нескольких папок?

настроено:
- Рабочий стол: MacBook Pro (начало 2011 г.) с iOS 10.13.6
- Версия программного обеспечения: версия 3.5.1 R (2018-07-02) - "Спрей для перьев"
- R studio: Версия 1.1.456

Я хотел бы импортировать несколько CSV-файлов из определенных папок и объединить их в один файл с 5 столбцами: Переменная1 / Переменная2 / имя_файла / эксперимент_nb / pulse_nb Мне удалось сделать импорт всех файлов из одной и той же папки из предыдущих аналогичных вопросов в StackOverflow в одном и том же data.frame, однако я не уверен, как это сделать для другой папки и достоверности заголовка каждого файла после объединить. Поскольку файл слишком велик, чтобы обрабатывать его вручную (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, поэтому я не могу вручную проверить заголовки).

Надеюсь, я добавил все необходимые данные и разместил вопросы в правильном формате, так как я впервые публикую здесь :)

Заранее спасибо, ребята, за помощь!

Ответы [ 2 ]

0 голосов
/ 03 июня 2019

Я тоже добавлю свое решение, используя purrr s map_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/"))
0 голосов
/ 03 июня 2019

Я создал фиктивную среду папок и файлов, предполагая, что вы будете логически перегруппировать все свои файлы и папки.

# ---
# 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

# ---
# --- 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)

Надеюсь, что это поможет:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...