читать файлы и устанавливать имена файлов в той же трубе dplyr - PullRequest
0 голосов
/ 21 сентября 2019

Это сложный вопрос dplyr & purrr. Я хочу упростить следующий код в одну трубу dplyr:

filenames <- list.files(path = data.location, pattern = "*.csv") %>%
  map_chr(function(name) gsub(paste0('(.*).csv'), '\\1', name))

files.raw <- list.files(path = data.location, pattern = "*.csv", full.names = TRUE) %>%
  map(read_csv) %>%
  setNames(filenames)

Я попытался решить это , но не удалось, поскольку имена файловдолжен использоваться с полным путем (full.names = TRUE) для read_csv (), но я хочу назначить имена файлов без полного пути.

Другими словами, это работало - но только с полным путем в именах файлов:

list.files(path = data.location, pattern = "*.csv", full.names = TRUE) %>%
  { . ->> filenames } %>%
  map(read_csv) %>%
  setNames(filenames)

, но это не так:

list.files(path = data.location, pattern = "*.csv", full.names = TRUE) %>%
{ map_chr(., function(name) gsub(paste0(data.location, '/(.*).csv'), '\\1', name)) ->> filenames } %>%
  map(read_csv) %>% 
  setNames(filenames)

Есть ли способзаставить map_chr работать с save (->> filenames), или есть еще более простой способ полностью избежать сохранения во временную переменную (имена файлов)?

Ответы [ 4 ]

1 голос
/ 23 сентября 2019

Чтобы сделать это в одном конвейере без промежуточных значений и аналогично @Ronak Shah, почему бы не задать сначала имена, а затем прочитать в CSV?Ронак вкладывает вызов setNames, но его можно поместить в конвейер, чтобы сделать его более читабельным:

library(tidyverse)
list.files(path = data.location, pattern = "*.csv", full.names = TRUE) %>%
    setNames(., sub("\\.csv$", "", basename(.))) %>% 
    map(read_csv)
1 голос
/ 21 сентября 2019

Попробуйте использовать этот метод:

all_files <- list.files(path = data.location, pattern = "*.csv", full.names = TRUE) 

purrr::map(all_files, readr::read_csv) %>%
      setNames(sub("\\.csv$", "", basename(all_files)))

Здесь мы сначала получаем полный путь ко всем файлам, используем его для чтения, используя read_csv.Мы можем использовать basename, чтобы получить только имя файла, удалить из него "csv" и присвоить имена, используя setNames.


. Чтобы сделать это в одном канале, мы можем сделать

list.files(path = data.location, pattern = "*.csv", full.names = TRUE)  %>%
    {setNames(map(., read_csv), sub("\\.csv$", "", basename(.)))}
0 голосов
/ 22 сентября 2019

Вдохновленный

  1. нижеследующий ответ @Ronak Shah
  2. посредническое назначение, предложенное @G.Grothendiek здесь

Я собрал следующее решение, которое

  1. объединяет чтение и именование файлов в одну трубу dplyr (моя первоначальная цель)
  2. делает код более интуитивно понятным для чтения (моя всегда неявная цель) - важно для соавторов или вообще.

Итак, вот мой универсальный канал dplyr:

list.files(path = data.location, pattern = "*.csv", full.names = TRUE)  %>%
  { filenames <<- . } %>%
  map(read_csv) %>%
  setNames(filenames %>% basename %>% map(~gsub(paste0('(.*).csv'), '\\1', .x)))

Единственная сложность в вышеприведенном решении - использовать оператор присваивания <<-, так как <- не будет работать.Если вы хотите использовать последнее, вы можете сделать это, поместив весь второй раздел в квадратные скобки - также предложенный @G.Гротендик в вышеуказанном посте:

list.files(path = data.location, pattern = "*.csv", full.names = TRUE)  %>%
{
  { filenames <- . } %>%
    map(read_csv) %>%
    setNames(filenames %>% basename %>% map(~gsub(paste0('(.*).csv'), '\\1', .x)))
}
0 голосов
/ 21 сентября 2019

Мы можем сделать это только с tidyverse функциями

library(readr)
library(purrr)
library(dplyr)
all_files <- list.files(path = data.location, pattern = "*\\.csv", full.names = TRUE) 
 map(all_files, read_csv) %>%
          set_names(str_remove(basename(all_files), "\\.csv$")) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...