diff --git a/R/.Rbuildignore b/R/.Rbuildignore new file mode 100644 index 0000000..91114bf --- /dev/null +++ b/R/.Rbuildignore @@ -0,0 +1,2 @@ +^.*\.Rproj$ +^\.Rproj\.user$ diff --git a/R/.gitignore b/R/.gitignore new file mode 100644 index 0000000..807ea25 --- /dev/null +++ b/R/.gitignore @@ -0,0 +1,3 @@ +.Rproj.user +.Rhistory +.RData diff --git a/R/DESCRIPTION b/R/DESCRIPTION new file mode 100644 index 0000000..a138027 --- /dev/null +++ b/R/DESCRIPTION @@ -0,0 +1,22 @@ +Package: REDCapRITS +Title: REDCap Repeating Instrument Table Splitter +Version: 0.0.0 +Authors@R: person( + "Paul", + "Egeler", + email = "paul.egeler@spectrumhealth.org", + role = c("aut", "cre")) +Description: Split REDCap repeating instruments output into multiple tables. + This will take raw output from a REDCap export and split it into a base table + and child tables for each repeating instrument. +Depends: R (>= 3.4.0) +Suggests: RCurl, + jsonlite, + testthat +License: GPL-3 +Encoding: UTF-8 +LazyData: true +RoxygenNote: 6.0.1 +Collate: + 'JSON2data.frame.r' + 'REDCap_split.r' diff --git a/R/NAMESPACE b/R/NAMESPACE new file mode 100644 index 0000000..b1bb9bf --- /dev/null +++ b/R/NAMESPACE @@ -0,0 +1,3 @@ +# Generated by roxygen2: do not edit by hand + +export(REDCap_split) diff --git a/R/R/JSON2data.frame.r b/R/R/JSON2data.frame.r new file mode 100644 index 0000000..7b97f16 --- /dev/null +++ b/R/R/JSON2data.frame.r @@ -0,0 +1,37 @@ +JSON2data.frame <- function (x) { + + if (inherits(x, "data.frame")) { + + return(x) + + } else if (inherits(x, "character")) { + + if (requireNamespace("jsonlite", quietly = TRUE)) { + + return(jsonlite::fromJSON(x)) + + } else { + + stop( + "The package 'jsonlite' is needed to convert ", + deparse(substitute(x)), + " into a data frame.", + "\n Either install 'jsonlite' or pass ", + deparse(substitute(x)), + " as a 'data.frame'.", + call. = FALSE + ) + + } + + } else { + + stop( + deparse(substitute(x)), + " must be a 'data.frame' or JSON string of class 'character'.", + call. = FALSE + ) + + } + +} diff --git a/REDCap_split.r b/R/R/REDCap_split.r similarity index 75% rename from REDCap_split.r rename to R/R/REDCap_split.r index a7adb6c..dbbcd49 100644 --- a/REDCap_split.r +++ b/R/R/REDCap_split.r @@ -1,15 +1,17 @@ #' Split REDCap repeating instruments table into multiple tables #' -#' This will take a raw \code{data.frame} from REDCap and split it into a base table -#' and give individual tables for each repeating instrument. Metadata +#' This will take output from a REDCap export and split it into a base table +#' and child tables for each repeating instrument. Metadata #' is used to determine which fields should be included in each resultant table. #' -#' @param records \code{data.frame} containing project records -#' @param metadata \code{data.frame} containing project metadata (the data dictionary) +#' @param records Exported project records. May be a \code{data.frame} or +#' \code{character} vector containing JSON from an API call. +#' @param metadata Project metadata (the data dictionary). May be a +#' \code{data.frame} or \code{character} vector containing JSON from an API +#' call. #' @author Paul W. Egeler, M.S., GStat #' @examples #' \dontrun{ -#' library(jsonlite) #' library(RCurl) #' #' # Get the metadata @@ -29,21 +31,19 @@ #' returnFormat = 'json' #' ) #' -#' # Convert JSON to data.frames -#' records <- fromJSON(result.record) -#' metadata <- fromJSON(result.meta) -#' -#' # Split the data.frame into a list of data.frames +#' # Convert exported JSON strings into a list of data.frames #' REDCap_split(records, metadata) #' } -#' @return a list of data.frames +#' @return A list of \code{"data.frame"}s: one base table and zero or more +#' tables for each repeating instrument. +#' @include JSON2data.frame.r #' @export REDCap_split <- function(records, metadata) { - stopifnot(all(sapply(list(records,metadata), inherits, "data.frame"))) + records <- JSON2data.frame(records) + metadata <- JSON2data.frame(metadata) # Check to see if there were any repeating instruments - if (!any(names(records) == "redcap_repeat_instrument")) { message("There are no repeating instruments in this data.") @@ -109,6 +109,6 @@ REDCap_split <- function(records, metadata) { } - return(out) + out } diff --git a/REDCapRITS.Rproj b/R/REDCapRITS.Rproj similarity index 54% rename from REDCapRITS.Rproj rename to R/REDCapRITS.Rproj index e83436a..cba1b6b 100644 --- a/REDCapRITS.Rproj +++ b/R/REDCapRITS.Rproj @@ -1,7 +1,7 @@ Version: 1.0 -RestoreWorkspace: Default -SaveWorkspace: Default +RestoreWorkspace: No +SaveWorkspace: No AlwaysSaveHistory: Default EnableCodeIndexing: Yes @@ -14,3 +14,8 @@ LaTeX: pdfLaTeX AutoAppendNewline: Yes StripTrailingWhitespace: Yes + +BuildType: Package +PackageUseDevtools: Yes +PackageInstallArgs: --no-multiarch --with-keep.source +PackageRoxygenize: rd,collate,namespace diff --git a/R/man/REDCap_split.Rd b/R/man/REDCap_split.Rd new file mode 100644 index 0000000..b895ec8 --- /dev/null +++ b/R/man/REDCap_split.Rd @@ -0,0 +1,53 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/REDCap_split.r +\name{REDCap_split} +\alias{REDCap_split} +\title{Split REDCap repeating instruments table into multiple tables} +\usage{ +REDCap_split(records, metadata) +} +\arguments{ +\item{records}{Exported project records. May be a \code{data.frame} or +\code{character} vector containing JSON from an API call.} + +\item{metadata}{Project metadata (the data dictionary). May be a +\code{data.frame} or \code{character} vector containing JSON from an API +call.} +} +\value{ +A list of \code{"data.frame"}s: one base table and zero or more + tables for each repeating instrument. +} +\description{ +This will take output from a REDCap export and split it into a base table +and child tables for each repeating instrument. Metadata +is used to determine which fields should be included in each resultant table. +} +\examples{ +\dontrun{ +library(RCurl) + +# Get the metadata +result.meta <- postForm( + api_url, + token = api_token, + content = 'metadata', + format = 'json' +) + +# Get the records +result.record <- postForm( + uri = api_url, + token = api_token, + content = 'record', + format = 'json', + returnFormat = 'json' +) + +# Convert exported JSON strings into a list of data.frames +REDCap_split(records, metadata) +} +} +\author{ +Paul W. Egeler, M.S., GStat +} diff --git a/R/tests/testthat.R b/R/tests/testthat.R new file mode 100644 index 0000000..dae14a9 --- /dev/null +++ b/R/tests/testthat.R @@ -0,0 +1,4 @@ +# library(testthat) +# library(REDCapRITS) +# +# test_check("REDCapRITS") diff --git a/README.md b/README.md index 1d229a2..4545ddf 100644 --- a/README.md +++ b/README.md @@ -35,15 +35,21 @@ a solution to handle the problem in both SAS and R. ## Instructions ### R -The function definition file contains [roxygen2](https://cran.r-project.org/package=roxygen2) comments to assist you. +First you must install the package. To do so, execute the following in your R console: + +```r +if (!require(devtools)) install.packages("devtools") +devtools::install_github("SpectrumHealthResearch/REDCapRITS/R") +``` + +After the package is installed, follow these instructions: -1. Run the function definition in the source editor or using `source()`. 1. Download the record dataset and metadata. This can be accomplished either by traditional methods or using the API. The `read.csv()` function should be able to handle newline characters within records, so no pre-processing of metadata csv is needed. 1. Call the function, pointing it to your record dataset and metadata -`data.frame`s. +`data.frame`s or JSON character vectors. ### SAS diff --git a/REDCap_split.sas b/SAS/REDCap_split.sas similarity index 100% rename from REDCap_split.sas rename to SAS/REDCap_split.sas