|
| 1 | + |
| 2 | +#' Download and read a data file from Dropbox |
| 3 | +#' |
| 4 | +#' @param filename A Dropbox filename, e.g. returned by \code{drop_dir} |
| 5 | +#' @param token A dropbox token |
| 6 | +#' @param read_function A function to read the downloaded file with |
| 7 | +#' @param ... Other parameters to be passed to \code{read_function} |
| 8 | +#' @description This function downloads and reads (via a caller-supplied |
| 9 | +#' function) a file on Dropbox. |
| 10 | +#' @return A \code{\link[tibble]{tibble}} with the data. |
| 11 | +#' @export |
| 12 | +#' @author Ben Bond-Lamberty |
| 13 | +read_file_dropbox <- function(filename, token, read_function, ...) { |
| 14 | + # We don't want users to need rdrop2 to use this package (i.e. we don't |
| 15 | + # want to put it in DESCRIPTION's Imports:), so check for availability |
| 16 | + if(requireNamespace("rdrop2", quietly = TRUE)) { |
| 17 | + # download to temp file |
| 18 | + tf <- tempfile() |
| 19 | + rdrop2::drop_download(filename, local_path = tf, |
| 20 | + dtoken = token, overwrite = TRUE) |
| 21 | + read_function(tf, ...) |
| 22 | + } else { |
| 23 | + stop("rdrop2 package is not available") |
| 24 | + } |
| 25 | +} |
| 26 | + |
| 27 | + |
| 28 | +#' Read a directory of files |
| 29 | +#' |
| 30 | +#' @param datadir A directory, either in Dropbox or local |
| 31 | +#' @param pattern Filename regex pattern |
| 32 | +#' @param read_function The file-read function to use |
| 33 | +#' @param dropbox_token Optional Dropbox token |
| 34 | +#' @param progress_bar Optional progress bar to call while reading |
| 35 | +#' @param ... Other parameters to be passed to \code{read_function} |
| 36 | +#' @description A general-purpose function to read data files, either from |
| 37 | +#' Dropbox or locally. The function identifies files based on a pattern, |
| 38 | +#' reads data from each file, and binds them together Callers |
| 39 | +#' pass a `read_function` that handles the actual file read. |
| 40 | +#' @return All data files in directory, read and concatenated |
| 41 | +#' in a \code{\link[tibble]{tibble}}. |
| 42 | +#' @importFrom dplyr bind_rows |
| 43 | +#' @note This is not intended to be called directly by users; use |
| 44 | +#' \code{\link{process_sapflow_dir}}, etc., instead. |
| 45 | +#' @note We use \code{\link[dplyr]{bind_rows}} for its much greater efficiency |
| 46 | +#' over \code{\link{rbind}} |
| 47 | +#' @author Ben Bond-Lamberty |
| 48 | +process_dir <- function(datadir, pattern, read_function, |
| 49 | + dropbox_token = NULL, |
| 50 | + progress_bar = NULL, ...) { |
| 51 | + |
| 52 | + local <- is.null(dropbox_token) |
| 53 | + |
| 54 | + # Get our file list, either locally or in Dropbox |
| 55 | + if(local) { |
| 56 | + s_files <- list.files(datadir, pattern = pattern, full.names = TRUE) |
| 57 | + } else { |
| 58 | + # We don't want users to need rdrop2 to use this package (i.e. we don't |
| 59 | + # want to put it in DESCRIPTION's Imports:), so check for availability |
| 60 | + if(requireNamespace("rdrop2", quietly = TRUE)) { |
| 61 | + # Generate list of 'current' (based on token) files |
| 62 | + s_dir <- rdrop2::drop_dir(datadir, dtoken = dropbox_token) |
| 63 | + s_files <- grep(s_dir$path_display, pattern = pattern, value = TRUE) |
| 64 | + } else { |
| 65 | + stop("rdrop2 package is not available") |
| 66 | + } |
| 67 | + } |
| 68 | + |
| 69 | + # Function called by lapply below; handles progress bar and calls file reader |
| 70 | + f <- function(filename, read_function, token, total_files) { |
| 71 | + if(!is.null(progress_bar)) progress_bar(1 / total_files) |
| 72 | + # Read file, either locally or from Dropbox |
| 73 | + if(local) { |
| 74 | + read_function(filename, ...) |
| 75 | + } else { |
| 76 | + read_file_dropbox(filename, dropbox_token, read_function, ...) |
| 77 | + } |
| 78 | + } |
| 79 | + x <- lapply(s_files, f, read_function, dropbox_token, length(s_files)) |
| 80 | + bind_rows(x) |
| 81 | +} |
0 commit comments