Эффективная стратегия для рекурсивного вызова `list.files ()` в функции R - PullRequest
0 голосов
/ 27 мая 2020

У меня есть папка, в которую будут поступать необработанные данные с удаленных станций. Структура данных в основном контролируется датой приобретения, с общим шаблоном, заданным следующим образом:

root/unit_mac_address/date/data_here/

Вот пример ограниченного запроса tree для одной единицы с несколькими днями записи.

.
├── 2020-04-03
│   ├── 2020-04-03T11-01-31_capture.txt
│   ├── 2020-04-03T11-32-36_capture.txt
│   ├── 2020-04-03T14-58-43_capture.txt
│   ├── img
│   └── temperatures.csv
...
├── 2020-05-21
│   ├── 2020-05-21T11-10-55_capture.txt
│   ├── img
│   └── temperatures.csv
└── dc:a6:32:2d:b8:62_ip.txt

Внутри каждой папки img у меня есть сотни / тысячи изображений, которые имеют временную метку с указанием даты и времени получения.

Моя цель - объединить данные в temperatures.csv со всех блоков в target_date.

Мой текущий подход следующий:

# from root dir, get all the temperatures.csv files
all_files <- list.files(pattern = "temperatures.csv",
 full.names = TRUE,
 # do it for all units 
 recursive = TRUE)
# subset the files from the list that contain the target_date
all_files <- all_files[str_detect(all_files, target_date)]
# read and bind into df
df <- lapply(all_files, function(tt) read_csv(tt)) %>%
    bind_rows()

Я решил искать temperatures.csv, потому что это без метки времени, но я думаю, что все равно просматриваю все imgs. Я не думаю, что есть способ ограничить list.files() определенным уровнем или рекурсией.

Это работает, но это лучший способ сделать это? Что можно сделать для повышения производительности? Данные поступают каждый день, поэтому растет число файлов, которые функция list.files() должна будет обработать до go для каждого из 10-20 единиц.

Было бы эффективнее, если бы файлы temperature.csv сами содержали метку времени (2020-05-26_temperatures.csv)? Я могу запросить временные метки для самих файлов temperatures.csv (не текущий подход), но я чувствую, что смогу справиться с этим на своей стороне.

Было бы более эффективно искать только каталоги, у которых есть установленный срок? а затем построить пути так, чтобы он смотрел только на первый уровень в каждом каталоге target_date? Любые намеки на это приветствуются.

Ответы [ 2 ]

0 голосов
/ 24 июня 2020

Если вы действительно беспокоитесь о производительности, вы можете рассмотреть data.table уже для его функции fas fread. Вот пример кода:

library(data.table)
target_date <- "2020-04-03"
all_units <- list.dirs(path=".", recursive = FALSE) # or insert your path
all_units <- grep(":..:..:", all_units, value = TRUE, invert = TRUE)
temp_files <- sapply(all_units,
    function(x) file.path(x, paste0(target_date, "/temperatures.csv")), 
    USE.NAMES = FALSE)
idx <- file.exists(temp_files)
df <- setNames(lapply(temp_files[idx], fread), 
        paste(basename(all_units[idx]), target_date, sep="_"))
rbindlist(df, idcol = "ID")
0 голосов
/ 27 мая 2020

Используя комментарий в качестве хорошего руководства, вот сравнительный анализ альтернативного способа сделать это.

Вот суть новой функции

all_units <- list.dirs(recursive = FALSE)
# mac address has ":" unlikely in anothed dir
all_units <- all_units[str_detect(all_units, ":")]
all_dirs <- lapply(all_units,
 function(tt) list.dirs(path = tt, recursive = FALSE)) %>%
    unlist()
# there shouldn't be children but
# we paste0 to only get the date folder and not the children of that folder
relevant_dirs <- all_dirs[str_detect(all_dirs, paste0(target_date, "$"))]
all_files <- lapply(relevant_dirs,
 function(tt) 
   list.files(tt, pattern = "temperatures.csv", full.names = TRUE)) %>%
    unlist()
df <- lapply(all_files, function(tt) read_csv(tt)) %>%
    bind_rows()

Вот реальный тест для целевой день, когда данные получают всего 2 единицы, я подозреваю, что со временем эта разница будет только увеличиваться для рекурсивного варианта.

unit: milliseconds
        expr       min        lq      mean    median        uq      max neval
   read_data 111.76401 124.17692 130.59572 127.84681 133.35566 317.6134  1000
 read_data_2  39.72021  46.58495  50.80255  49.05811  52.01692 141.2126  1000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...