As my second Shiny exercise, I built a browser for more than 73,000 medical diagnoses cataloged according to the International Classification of Diseases, Tenth Revision, Clinical Modification (ICD-10-CM). The browser is pretty simple, but I learned valuable new tricks.

Matching all search terms

I wanted to do a search that matched all terms. I first tried using grepl() to match each of the search terms using the following the regular expression pattern (?=.*search_term).

V1 <- c("dental fracture",
        "acute stress reaction",
        "stress fracture, right shoulder")
search_terms <- c("fracture","stress")

pattern <- paste0("(?=.*", search_terms,")", collapse="") 
grepl(pattern, V1, perl = TRUE)
## [1] FALSE FALSE  TRUE

This worked, but no matter the function I used, regex(), str_detect(), stri_detect(), the matching process was extraordinarily slow. I turned to StackOverflow for help and @onyamby provided an amazingly fast single line of code.

Reduce("&", lapply(search_terms, grepl, V1, fixed = TRUE))
## [1] FALSE FALSE  TRUE

It is surprisingly easy when you think about it, instead of looping through each string and matching all search terms with a regular expression, loop through each search term separately and then get the overlapping TRUE results. I love this solution!

DT’s lack of full table info

The next challenge was trying to update a dependent table upon a click on a row using the DT package. DT doesn’t make available full table information as inputs ready to be used by Shiny. For instance, if a user clicks on cell (2,3), you can’t know through DT the value for another cell in the same row, say cell (2,4). To solve this problem I store a vector of IDs of the “active” table. I think this is a waste of resources, but I made the best of it, instead of storing the whole “active” data frame, I store only an “index” vector.


2022 Ingrid Lagos