├── .Rbuildignore ├── .gitignore ├── DESCRIPTION ├── NAMESPACE ├── R └── openfda.R ├── README.Rmd ├── README.md ├── inst └── CITATION ├── man ├── chain_query.Rd ├── copy_query.Rd ├── extract_field.Rd ├── fda_api_key.Rd ├── fda_count.Rd ├── fda_debug.Rd ├── fda_exec.Rd ├── fda_fetch.Rd ├── fda_filter.Rd ├── fda_limit.Rd ├── fda_plot.Rd ├── fda_query.Rd ├── fda_search.Rd ├── fda_skip.Rd ├── fda_url.Rd └── openfda.Rd └── tests ├── testthat.R ├── testthat └── test-query-builder.R └── tutorial.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | README.Rmd 4 | /figure 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | R-package.rproj 4 | /figure 5 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: openfda 2 | Title: R interface to the OpenFDA API 3 | Version: 1.7.0.9000 4 | Authors@R: c( 5 | person("Russell", "Power", email = "power@iodine.com", role = c("aut", "cre")), 6 | person("Thomas J.", "Leeper", email = "thosjleeper@gmail.com", role = "aut") 7 | ) 8 | Maintainer: Russell Power 9 | Description: Provides a simplified interface to the OpenFDA API from R. 10 | URL: http://github.com/ropenhealth/openfda 11 | BugReports: http://github.com/ropenhealth/openfda/issues 12 | Depends: 13 | R (>= 3.0.2) 14 | Imports: 15 | memoise, 16 | jsonlite, 17 | magrittr, 18 | ggplot2, 19 | httr 20 | Suggests: 21 | testthat, 22 | plyr 23 | License: GPL (>= 2) 24 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2 (4.1.0): do not edit by hand 2 | 3 | S3method(print,fda_query) 4 | export("%>%") 5 | export(extract_field) 6 | export(fda_api_key) 7 | export(fda_count) 8 | export(fda_debug) 9 | export(fda_exec) 10 | export(fda_fetch) 11 | export(fda_filter) 12 | export(fda_limit) 13 | export(fda_skip) 14 | export(fda_plot) 15 | export(fda_query) 16 | export(fda_search) 17 | export(fda_url) 18 | importFrom(ggplot2,qplot) 19 | importFrom(jsonlite,fromJSON) 20 | importFrom(magrittr,"%>%") 21 | importFrom(memoise,memoise) 22 | -------------------------------------------------------------------------------- /R/openfda.R: -------------------------------------------------------------------------------- 1 | #' @importFrom jsonlite fromJSON 2 | #' @importFrom memoise memoise 3 | #' @importFrom ggplot2 qplot 4 | #' @importFrom magrittr %>% 5 | NULL 6 | 7 | #' Pipe operator for chaining together operations. 8 | #' 9 | #' Imported from magrittr, use this to chain together 10 | #' operations in a natural way. 11 | #' 12 | #' @examples 13 | #' \dontrun{ 14 | #' # instead of 15 | #' a(b(c("hello")), "bob") 16 | #' 17 | #' # we can write: 18 | #' 19 | #' c("hello") \%>\% b() \%>\% a("bob") 20 | #' 21 | #' # this also allows for currying common arguments: 22 | #' 23 | #' my_query <- 24 | #' fda_query("/drug/event.json") \%>\% 25 | #' fda_api_key("ABC") 26 | #' } 27 | #' 28 | #' @aliases chain_query 29 | #' @rdname chain_query 30 | #' @name %>% 31 | #' @export 32 | NULL 33 | 34 | #' Make a copy of query (keeps the class). 35 | copy_query = function(query) { 36 | query = lapply(query, FUN=identity) 37 | class(query) = "fda_query" 38 | query 39 | } 40 | 41 | fetch_ <- memoise(fromJSON) 42 | 43 | #' Fetch the given URL as JSON. 44 | #' 45 | #' This uses jsonlite to fetch the URL. The result is coerced into 46 | #' a data frame. 47 | #' 48 | #' @return data.frame 49 | #' @export 50 | fda_fetch <- function(url, catch_errors=TRUE, debug=TRUE) { 51 | if (debug == TRUE) { 52 | cat("Fetching:", url, "\n") 53 | } 54 | 55 | result = httr::GET(url) 56 | # The API servers return 404 for empty search results, so 57 | # distinguish that case from 'real' errors. 58 | if (result$status_code == 404) { 59 | warning('Received 404 response from FDA servers.\n', 60 | 'Interpreting as an empty result set.') 61 | return(data.frame(results=c())); 62 | } 63 | 64 | httr::stop_for_status(result) 65 | fromJSON(httr::content(result, as='text')) 66 | } 67 | 68 | #' Create a new query. 69 | #' 70 | #' Queries can be extended with filters (using fda_filter). 71 | #' They should be terminated using either \code{search} or 72 | #' \code{count(field)}. 73 | #' @param base The API endpoint to query: \itemize{ 74 | #' \item /drug/event.json 75 | #' \item /drug/enforcement.json 76 | #' \item /device/event.json 77 | #' \item /food/event.json 78 | #' } 79 | #' 80 | #' @return fda_query 81 | #' @export 82 | fda_query <- function(base) { 83 | q <- list() 84 | q$base = base 85 | q$limit = FALSE 86 | q$skip = FALSE 87 | q$key = FALSE 88 | q$count = FALSE 89 | q$debug = TRUE 90 | q$filters = vector("character") 91 | q$operation = function(q) { 92 | print("No operation defined (try fda_count or fda_search)!") 93 | q 94 | } 95 | class(q) = "fda_query" 96 | q 97 | } 98 | 99 | #' @export 100 | print.fda_query <- function(x, ...) { 101 | print(paste("fda_query(", fda_url(x), ")", sep="")) 102 | } 103 | 104 | #' Turn off/on API debugging. 105 | #' 106 | #' When set to TRUE, this will print additional debugging information from 107 | #' the API, such as URLs being fetched. 108 | #' 109 | #' @export 110 | fda_debug <- function(q, should_debug) { 111 | q = copy_query(q) 112 | q$debug = should_debug 113 | q 114 | } 115 | 116 | #' Apply a filter to a query 117 | #' 118 | #' @param name The field to filter on (e.g. "patient.patientonsetage") 119 | #' @param value A value or range to filter on (e.g. "[1+TO+40]") 120 | #' 121 | #' @return fda_query 122 | #' @export 123 | fda_filter <- function(q, name, value) { 124 | q = copy_query(q) 125 | q$filters = c(q$filters, paste(name, value, sep=":")) 126 | q 127 | } 128 | 129 | #' Set the number of results desired by this query. 130 | #' 131 | #' The default number of results returned by the API 132 | #' is 1 (for search requests) and 100 (for count requests). 133 | #' 134 | #' @return fda_query 135 | #' @export 136 | fda_limit <- function(q, limit) { 137 | q = copy_query(q) 138 | q$limit = limit 139 | q 140 | } 141 | 142 | #' Set the number of records to skip. 143 | #' 144 | #' Skip a number of records from a search. 145 | #' If count is used, skip will be ignored. 146 | #' 147 | #' @return fda_query 148 | #' @export 149 | fda_skip <- function(q, skip) { 150 | q = copy_query(q) 151 | q$skip = skip 152 | q 153 | } 154 | 155 | #' Attach an API key to the query. 156 | #' 157 | #' All requests made to the API will have this API key 158 | #' specified. 159 | #' 160 | #' @return fda_query 161 | #' @export 162 | fda_api_key <- function(q, key) { 163 | q = copy_query(q) 164 | q$key = key 165 | q 166 | } 167 | 168 | #' Return the URL that will be fetched for the current query. 169 | #' 170 | #' @return character The url that will be fetched 171 | #' @export 172 | fda_url <- function(q) { 173 | q = copy_query(q) 174 | search <- paste("search", paste(q$filters, collapse="+AND+"), sep="=") 175 | 176 | args = c(search); 177 | 178 | if (q$key != FALSE) { 179 | args = c(args, paste("api_key", q$key, sep="=")) 180 | } 181 | 182 | if (q$limit != FALSE) { 183 | args = c(args, paste("limit", q$limit, sep="=")) 184 | } 185 | 186 | if (q$skip != FALSE) { 187 | if(q$count == FALSE) { 188 | args = c(args, paste("skip", q$skip, sep="=")) 189 | } 190 | } 191 | 192 | if (q$count != FALSE) { 193 | args = c(args, paste("count", q$count, sep="=")) 194 | } 195 | 196 | args = paste(args, collapse="&", sep="") 197 | 198 | url = paste("https://api.fda.gov", q$base, sep="") 199 | url = paste(url, args, sep="?") 200 | return(url) 201 | } 202 | 203 | #' Plot a count query. 204 | #' 205 | #' This is just a convenience function which takes the 206 | #' data frame output from fda_exec and gives it to qplot. 207 | 208 | #' @return ggplot2 209 | #' @export 210 | fda_plot <- function(df) { 211 | qplot(term, count, data=df) 212 | } 213 | 214 | extract_ <- function(obj, path) { 215 | if (length(path) == 0) { 216 | return(obj) 217 | } 218 | field = path[1] 219 | rest = path[-1] 220 | obj = obj[[field]] 221 | extract_(obj, rest) 222 | } 223 | 224 | #' Fetch a (nested field) from a list or dataframe. 225 | #' 226 | #' @export 227 | extract_field <- function(obj, path) { 228 | path = unlist(strsplit(path, ".", fixed=TRUE)) 229 | extract_(obj, path) 230 | } 231 | 232 | #' Fetch search results. 233 | #' 234 | #' When combined with \code{fda_exec}, this query will 235 | #' return a data frame consisting of the matching records. 236 | #' 237 | #' @param field The field to extract. This should be a 238 | #' dot (.) delimited path to follow to extract a field: 239 | #' e.g. 'a.b.c.d', would perform the equivalent of 240 | #' running a[[b]][[c]][[d]] 241 | #' @return fda_query 242 | #' @export 243 | fda_search <- function(q, field=FALSE) { 244 | q = copy_query(q) 245 | q$count = FALSE 246 | q$operation = function(q) { 247 | url = fda_url(q); 248 | result = fda_fetch(url, debug=q$debug)$result 249 | if (field == FALSE) { 250 | return(result) 251 | } else { 252 | return(extract_field(result, field)) 253 | } 254 | } 255 | 256 | q 257 | } 258 | 259 | 260 | #' Count results from a given field. 261 | #' 262 | #' Returns a new query which will count the given field when 263 | #' handed to \code{fda_exec} 264 | #' 265 | #' @return fda_query 266 | #' @export 267 | fda_count <- function(q, field) { 268 | q = copy_query(q) 269 | q$limit = FALSE 270 | q$count = field 271 | 272 | #' Executes a count operation for a query 273 | q$operation <- function(q) { 274 | url = fda_url(q) 275 | json = fda_fetch(url, debug=q$debug) 276 | json$result 277 | } 278 | 279 | q 280 | } 281 | 282 | #' Execute a query. 283 | #' 284 | #' This actually sends a request to the OpenFDA API servers 285 | #' which incorporates any filters or keys specified in the query 286 | #' and returns the result as a data frame. 287 | #' 288 | #' @return data.frame containing API results 289 | #' @export 290 | fda_exec <- function(q) { 291 | q$operation(q) 292 | } 293 | 294 | #' openfda: A package for interfacing to the OpenFDA API 295 | #' 296 | #' This package provides a simple wrapper around the OpenFDA API. 297 | #' 298 | #' It uses the \code{magrittr} piping interface to simplify 299 | #' building complex queries. 300 | #' 301 | #' @examples 302 | #' # Queries generally have the following format 303 | #' \dontrun{ 304 | #' fda_query(endpoint) %>% 305 | #' fda_filter(field, value) %>% 306 | #' fda_count(field) OR fda_search() %>% 307 | #' fda_exec() 308 | #' } 309 | #' 310 | #' @docType package 311 | #' @name openfda 312 | NULL 313 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | # openfda 2 | ## Convenient access to the OpenFDA API 3 | 4 | This package provides some simple helpers for accessing the [OpenFDA](https://open.fda.gov/) API 5 | from R. It uses the `jsonlite` and `magrittr` packages to provide a 6 | simple way to convert from OpenFDA queries to R dataframes suitable 7 | for quick analysis and plotting. 8 | 9 | ## Installation 10 | 11 | This library has not yet been added to CRAN, so you'll need the devtools 12 | package to install it: 13 | 14 | ```R 15 | install.packages("devtools") 16 | ```` 17 | 18 | Once devtools is installed, you can grab this package: 19 | 20 | ```R 21 | library("devtools") 22 | devtools::install_github("ropenhealth/openfda") 23 | ``` 24 | 25 | Load it in like any other package: 26 | 27 | ```{r} 28 | library("openfda") 29 | ``` 30 | 31 | ## Examples 32 | 33 | ```{r, echo=FALSE, results='hide'} 34 | library("knitr") 35 | opts_knit$set(upload.fun = imgur_upload, base.url = NULL) 36 | ``` 37 | 38 | ```{r} 39 | patient_ages = fda_query("/drug/event.json") %>% 40 | fda_count("patient.patientonsetage") %>% 41 | fda_exec() 42 | 43 | # patient ages is now a data frame with "term" and "count" columns 44 | # let's plot it with ggplot2 45 | library("ggplot2") 46 | qplot(x=term, y=count, data=patient_ages) 47 | ``` 48 | 49 | You can filter the results to count on using the `fda_filter()` method: 50 | 51 | ```{r, results="hide"} 52 | paxil_ages = fda_query("/drug/event.json") %>% 53 | fda_filter("patient.drug.openfda.generic_name", "paroxetine") %>% 54 | fda_count("patient.patientonsetage") %>% 55 | fda_exec() 56 | ``` 57 | 58 | Using this API with your API key is easy: just add 59 | `fda_api_key("MY_KEY")` to your pipeline. 60 | 61 | ```{r, results="hide"} 62 | patient_ages = fda_query("/drug/event.json") %>% 63 | fda_api_key("MYKEY") %>% 64 | fda_count("patient.patientonsetage") %>% 65 | fda_exec() 66 | ``` 67 | 68 | You can also specify options up front and re-use the query: 69 | 70 | ```{r, results="hide"} 71 | age_query = fda_query("/drug/event.json") %>% 72 | fda_api_key("MYKEY") %>% 73 | fda_count("patient.patientonsetage"); 74 | 75 | paxil_ages = age_query %>% fda_filter("patient.drug.openfda.generic_name", "paroxetine") %>% fda_exec() 76 | zoloft_ages = age_query %>% fda_filter("patient.drug.openfda.generic_name", "sertraline") %>% fda_exec() 77 | ``` 78 | 79 | R documentation for each method is also provided in the package (`? fda_exec`). 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # openfda 2 | ## Convenient access to the OpenFDA API 3 | 4 | This package provides some simple helpers for accessing the [OpenFDA](https://open.fda.gov/) API 5 | from R. It uses the `jsonlite` and `magrittr` packages to provide a 6 | simple way to convert from OpenFDA queries to R dataframes suitable 7 | for quick analysis and plotting. 8 | 9 | ## Installation 10 | 11 | This library has not yet been added to CRAN, so you'll need the devtools 12 | package to install it: 13 | 14 | ```R 15 | install.packages("devtools") 16 | ```` 17 | 18 | Once devtools is installed, you can grab this package: 19 | 20 | ```R 21 | library("devtools") 22 | devtools::install_github("ropenhealth/openfda") 23 | ``` 24 | 25 | Load it in like any other package: 26 | 27 | 28 | ```r 29 | library("openfda") 30 | ``` 31 | 32 | ## Examples 33 | 34 | 35 | 36 | 37 | ```r 38 | patient_ages = fda_query("/drug/event.json") %>% 39 | fda_count("patient.patientonsetage") %>% 40 | fda_exec() 41 | ``` 42 | 43 | ``` 44 | ## Fetching: https://api.fda.gov/drug/event.json?search=&count=patient.patientonsetage 45 | ``` 46 | 47 | ```r 48 | # patient ages is now a data frame with "term" and "count" columns 49 | # let's plot it with ggplot2 50 | library("ggplot2") 51 | qplot(x=term, y=count, data=patient_ages) 52 | ``` 53 | 54 | ![plot of chunk unnamed-chunk-3](http://i.imgur.com/peY0jEh.png) 55 | 56 | You can filter the results to count on using the `fda_filter()` method: 57 | 58 | 59 | ```r 60 | paxil_ages = fda_query("/drug/event.json") %>% 61 | fda_filter("patient.drug.openfda.generic_name", "paroxetine") %>% 62 | fda_count("patient.patientonsetage") %>% 63 | fda_exec() 64 | ``` 65 | 66 | Using this API with your API key is easy: just add 67 | `fda_api_key("MY_KEY")` to your pipeline. 68 | 69 | 70 | ```r 71 | patient_ages = fda_query("/drug/event.json") %>% 72 | fda_api_key("MYKEY") %>% 73 | fda_count("patient.patientonsetage") %>% 74 | fda_exec() 75 | ``` 76 | 77 | You can also specify options up front and re-use the query: 78 | 79 | 80 | ```r 81 | age_query = fda_query("/drug/event.json") %>% 82 | fda_api_key("MYKEY") %>% 83 | fda_count("patient.patientonsetage"); 84 | 85 | paxil_ages = age_query %>% fda_filter("patient.drug.openfda.generic_name", "paroxetine") %>% fda_exec() 86 | zoloft_ages = age_query %>% fda_filter("patient.drug.openfda.generic_name", "sertraline") %>% fda_exec() 87 | ``` 88 | 89 | R documentation for each method is also provided in the package (`? fda_exec`). 90 | -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | citHeader("To cite package 'openfda' in publications use:") 2 | 3 | year <- sub(".*(2[[:digit:]]{3})-.*", "\\1", meta$Date, perl = TRUE) 4 | vers <- paste("R package version", meta$Version) 5 | 6 | citEntry(entry="Manual", 7 | title = "'openfda: R interface to the OpenFDA API", 8 | author = personList(as.person("Russell Power")), 9 | year = year, 10 | note = vers, 11 | textVersion = 12 | paste("Russell Power (", 13 | year, 14 | "). openfda: R interface to the OpenFDA API. ", 15 | vers, ".", sep="")) -------------------------------------------------------------------------------- /man/chain_query.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \alias{chain_query} 6 | \title{Pipe operator for chaining together operations.} 7 | \description{ 8 | Imported from magrittr, use this to chain together 9 | operations in a natural way. 10 | } 11 | \examples{ 12 | \dontrun{ 13 | # instead of 14 | a(b(c("hello")), "bob") 15 | 16 | # we can write: 17 | 18 | c("hello") \\\%>\\\% b() \\\%>\\\% a("bob") 19 | 20 | # this also allows for currying common arguments: 21 | 22 | my_query <- 23 | fda_query("/drug/event.json") \\\%>\\\% 24 | fda_api_key("ABC") 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /man/copy_query.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{copy_query} 4 | \alias{copy_query} 5 | \title{Make a copy of query (keeps the class).} 6 | \usage{ 7 | copy_query(query) 8 | } 9 | \description{ 10 | Make a copy of query (keeps the class). 11 | } 12 | 13 | -------------------------------------------------------------------------------- /man/extract_field.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{extract_field} 4 | \alias{extract_field} 5 | \title{Fetch a (nested field) from a list or dataframe.} 6 | \usage{ 7 | extract_field(obj, path) 8 | } 9 | \description{ 10 | Fetch a (nested field) from a list or dataframe. 11 | } 12 | 13 | -------------------------------------------------------------------------------- /man/fda_api_key.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{fda_api_key} 4 | \alias{fda_api_key} 5 | \title{Attach an API key to the query.} 6 | \usage{ 7 | fda_api_key(q, key) 8 | } 9 | \value{ 10 | fda_query 11 | } 12 | \description{ 13 | All requests made to the API will have this API key 14 | specified. 15 | } 16 | 17 | -------------------------------------------------------------------------------- /man/fda_count.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{fda_count} 4 | \alias{fda_count} 5 | \title{Count results from a given field.} 6 | \usage{ 7 | fda_count(q, field) 8 | } 9 | \value{ 10 | fda_query 11 | } 12 | \description{ 13 | Returns a new query which will count the given field when 14 | handed to \code{fda_exec} 15 | } 16 | 17 | -------------------------------------------------------------------------------- /man/fda_debug.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{fda_debug} 4 | \alias{fda_debug} 5 | \title{Turn off/on API debugging.} 6 | \usage{ 7 | fda_debug(q, should_debug) 8 | } 9 | \description{ 10 | When set to TRUE, this will print additional debugging information from 11 | the API, such as URLs being fetched. 12 | } 13 | 14 | -------------------------------------------------------------------------------- /man/fda_exec.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{fda_exec} 4 | \alias{fda_exec} 5 | \title{Execute a query.} 6 | \usage{ 7 | fda_exec(q) 8 | } 9 | \value{ 10 | data.frame containing API results 11 | } 12 | \description{ 13 | This actually sends a request to the OpenFDA API servers 14 | which incorporates any filters or keys specified in the query 15 | and returns the result as a data frame. 16 | } 17 | 18 | -------------------------------------------------------------------------------- /man/fda_fetch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{fda_fetch} 4 | \alias{fda_fetch} 5 | \title{Fetch the given URL as JSON.} 6 | \usage{ 7 | fda_fetch(url, catch_errors = TRUE, debug = TRUE) 8 | } 9 | \value{ 10 | data.frame 11 | } 12 | \description{ 13 | This uses jsonlite to fetch the URL. The result is coerced into 14 | a data frame. 15 | } 16 | 17 | -------------------------------------------------------------------------------- /man/fda_filter.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{fda_filter} 4 | \alias{fda_filter} 5 | \title{Apply a filter to a query} 6 | \usage{ 7 | fda_filter(q, name, value) 8 | } 9 | \arguments{ 10 | \item{name}{The field to filter on (e.g. "patient.patientonsetage")} 11 | 12 | \item{value}{A value or range to filter on (e.g. "[1+TO+40]")} 13 | } 14 | \value{ 15 | fda_query 16 | } 17 | \description{ 18 | Apply a filter to a query 19 | } 20 | 21 | -------------------------------------------------------------------------------- /man/fda_limit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{fda_limit} 4 | \alias{fda_limit} 5 | \title{Set the number of results desired by this query.} 6 | \usage{ 7 | fda_limit(q, limit) 8 | } 9 | \value{ 10 | fda_query 11 | } 12 | \description{ 13 | The default number of results returned by the API 14 | is 1 (for search requests) and 100 (for count requests). 15 | } 16 | 17 | -------------------------------------------------------------------------------- /man/fda_plot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{fda_plot} 4 | \alias{fda_plot} 5 | \title{Plot a count query.} 6 | \usage{ 7 | fda_plot(df) 8 | } 9 | \value{ 10 | ggplot2 11 | } 12 | \description{ 13 | This is just a convenience function which takes the 14 | data frame output from fda_exec and gives it to qplot. 15 | } 16 | 17 | -------------------------------------------------------------------------------- /man/fda_query.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{fda_query} 4 | \alias{fda_query} 5 | \title{Create a new query.} 6 | \usage{ 7 | fda_query(base) 8 | } 9 | \arguments{ 10 | \item{base}{The API endpoint to query: \itemize{ 11 | \item /drug/event.json 12 | \item /drug/enforcement.json 13 | \item /device/event.json 14 | \item /food/event.json 15 | }} 16 | } 17 | \value{ 18 | fda_query 19 | } 20 | \description{ 21 | Queries can be extended with filters (using fda_filter). 22 | They should be terminated using either \code{search} or 23 | \code{count(field)}. 24 | } 25 | 26 | -------------------------------------------------------------------------------- /man/fda_search.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{fda_search} 4 | \alias{fda_search} 5 | \title{Fetch search results.} 6 | \usage{ 7 | fda_search(q, field = FALSE) 8 | } 9 | \arguments{ 10 | \item{field}{The field to extract. This should be a 11 | dot (.) delimited path to follow to extract a field: 12 | e.g. 'a.b.c.d', would perform the equivalent of 13 | running a[[b]][[c]][[d]]} 14 | } 15 | \value{ 16 | fda_query 17 | } 18 | \description{ 19 | When combined with \code{fda_exec}, this query will 20 | return a data frame consisting of the matching records. 21 | } 22 | 23 | -------------------------------------------------------------------------------- /man/fda_skip.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{fda_skip} 4 | \alias{fda_skip} 5 | \title{Set the number of records to skip that match the search parameter.} 6 | \usage{ 7 | fda_skip(q, skip) 8 | } 9 | \value{ 10 | fda_skip 11 | } 12 | \description{ 13 | Skip this number of records that match the search parameter, then return the matching records that follow. 14 | Use in combination with limit to paginate results. 15 | } 16 | -------------------------------------------------------------------------------- /man/fda_url.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \name{fda_url} 4 | \alias{fda_url} 5 | \title{Return the URL that will be fetched for the current query.} 6 | \usage{ 7 | fda_url(q) 8 | } 9 | \value{ 10 | character The url that will be fetched 11 | } 12 | \description{ 13 | Return the URL that will be fetched for the current query. 14 | } 15 | 16 | -------------------------------------------------------------------------------- /man/openfda.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/openfda.R 3 | \docType{package} 4 | \name{openfda} 5 | \alias{openfda} 6 | \alias{openfda-package} 7 | \title{openfda: A package for interfacing to the OpenFDA API} 8 | \description{ 9 | This package provides a simple wrapper around the OpenFDA API. 10 | } 11 | \details{ 12 | It uses the \code{magrittr} piping interface to simplify 13 | building complex queries. 14 | } 15 | \examples{ 16 | # Queries generally have the following format 17 | \dontrun{ 18 | fda_query(endpoint) \%>\% 19 | fda_filter(field, value) \%>\% 20 | fda_count(field) OR fda_search() \%>\% 21 | fda_exec() 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library("testthat") 2 | 3 | test_check("openfda") 4 | -------------------------------------------------------------------------------- /tests/testthat/test-query-builder.R: -------------------------------------------------------------------------------- 1 | library("openfda") 2 | library("ggplot2") 3 | library("magrittr") 4 | 5 | context("query-builder") 6 | #openfda::fda_debug(FALSE) 7 | 8 | test_that("build enforcement query", { 9 | df = fda_query("/drug/enforcement.json") %>% 10 | fda_filter("openfda.product_type", "otc") %>% 11 | fda_count("classification.exact") %>% 12 | fda_exec() 13 | 14 | expect_that(df, is_a("data.frame")) 15 | }) 16 | 17 | test_that("build and query", { 18 | df = fda_query("/drug/event.json") %>% 19 | fda_filter("patient.patientsex", "2") %>% 20 | fda_filter("patient.patientonsetage", "[1+TO+40]") %>% 21 | fda_count("patient.drug.drugindication.exact") %>% 22 | fda_exec() 23 | 24 | expect_that(df, is_a("data.frame")) 25 | }) 26 | 27 | test_that("api key", { 28 | url = fda_query("/drug/event.json") %>% 29 | fda_api_key("BLAH") %>% 30 | fda_filter("patient.patientsex", "2") %>% 31 | fda_url() 32 | 33 | expect_equal(url, 34 | "https://api.fda.gov/drug/event.json?search=patient.patientsex:2&api_key=BLAH") 35 | }) 36 | 37 | context("fetch"); 38 | 39 | test_that("age counting", { 40 | df = fda_query("/drug/event.json") %>% 41 | fda_filter("patient.drug.openfda.generic_name", "paroxetine") %>% 42 | fda_filter("patient.patientonsetageunit", "801") %>% 43 | fda_count("patientonsetage") %>% 44 | fda_exec() 45 | }) 46 | 47 | test_that("retrieve a field", { 48 | df = fda_query("/drug/event.json") %>% 49 | fda_filter("patient.drug.openfda.generic_name", "paroxetine") %>% 50 | fda_search("patient.drug.drugindication") %>% 51 | fda_exec() 52 | }) 53 | 54 | test_that("basic fetching works", { 55 | df = fda_fetch("http://api.fda.gov/drug/event.json?count=receivedate")$result 56 | df$time = as.Date(df$time, "%Y%m%d") 57 | plot = ggplot(df, aes(x=time, y=count)) + stat_identity() 58 | expect_that(plot, is_a("gg")) 59 | }); 60 | 61 | context("error handling") 62 | test_that("handle 404s", { 63 | df = fda_fetch("http://api.fda.gov/drug/event.json?search=patientsex:99") 64 | }); 65 | -------------------------------------------------------------------------------- /tests/tutorial.R: -------------------------------------------------------------------------------- 1 | library("ggplot2") 2 | library("plyr") 3 | library("openfda") 4 | 5 | my_query = fda_query("/drug/event.json") 6 | 7 | ages = ldply(c('Aspirin', 'Fexofenadine', 'Clonazepam'), function(drug) { 8 | df = my_query %>% 9 | fda_filter("patient.drug.openfda.generic_name", drug) %>% 10 | fda_filter("patient.patientonsetageunit", "801") %>% 11 | fda_count("patient.patientonsetage") %>% 12 | fda_exec() 13 | df$drug = drug 14 | df 15 | }) 16 | 17 | ages = ldply(c(0, 1, 2), function(gender) { 18 | df = my_query %>% 19 | fda_filter("patient.patientsex", gender) %>% 20 | fda_filter("patient.patientonsetageunit", "801") %>% 21 | fda_count("patient.patientonsetage") %>% 22 | fda_exec() 23 | 24 | df$gender = switch(as.character(gender), 25 | "0"="Male", 26 | "1"="Female", 27 | "2"="Unknown") 28 | df 29 | }) 30 | --------------------------------------------------------------------------------