Sections:

  • Visualizations – list totals, bar chart of when created by year/month last 12 months, bar chart of top 20 users creating

  • Interpretations – Total+comments, total users, count for top 20 users, visualizations with an interpretation/comment

  • Dashboards – Comparison (views, users, visualizations), over time, average views by hour of each day, distinct user-days viewing each dashboard, interpretations left on dashboard objects

  • Viz Profile – Views for the image (total views and total users), interpretations+comments

To do:

  • Main issue is how to categorize & find the users of interest at a local level.
  • Should target users all belong to a specific user group, or do they need read access below to a certain OU only? Prefer to put them all in same user group.
  • Should visualizations include just those the target users created? Or those they can view in dashboards?
  • Messages – Total read and unread, by type, and month over month (TO DO)

Set up and login

# baseurl<-"https://play.dhis2.org/2.37dev/"
# username<-"admin"
# password<-"district"
# 
# startdate<-"2015-01-01"
# enddate<-"2021-12-01"

# If set by parameters
baseurl<-params$baseurl
username<-params$username
password<-params$password

startdate<-params$startdate
enddate<-params$enddate


####Load required packages
packages<-c("httr","assertthat","tidyverse","jsonlite","knitr","lubridate","here")      
install_or_load_pack <- function(pack){
  create.pkg <- pack[!(pack %in% installed.packages()[, "Package"])]
  if (length(create.pkg))
    install.packages(create.pkg, dependencies = TRUE, quiet=TRUE)
  sapply(pack, require, character.only = TRUE)
}

install_or_load_pack(packages)
##       httr assertthat  tidyverse   jsonlite      knitr  lubridate       here 
##       TRUE       TRUE       TRUE       TRUE       TRUE       TRUE       TRUE
# Set theme for charts etc
theme_set(theme_minimal())

# Extract login info from directory
# if (!file.exists("auth.json")){
#   stop("Please add auth.json to directory") 
# } else {
#   baseurl<-chuck(fromJSON("auth.json"), "dhis","baseurl")
#   username<-chuck(fromJSON("auth.json"), "dhis","username")
# }


##test login
loginDHIS2<-function(baseurl,username,password){
  url<-paste0(baseurl,"api/me")
  r<-GET(url,authenticate(username,password))
  assert_that(r$status_code == 200L)}

if(loginDHIS2(baseurl,username,password)){
  print("successfully logged in")
}else{
  stop("could not log in! Please check url, username and password in auth.json")
}
## [1] "successfully logged in"

Visualizations

Extract visualizations and their interpretations

#extract viz types
#might wittle down the fields we want in request, later

fetch_viz_obj<-function(obj_name){
  
url<-paste0(baseurl,"api/",obj_name,".json?fields=:all&paging=false")

fromJSON(content(GET(url),type="text", encoding="UTF-8")) %>% 
  pluck(obj_name) %>%
  select(any_of(c("name","id","createdBy","created", "interpretations","type"))) %>%
  jsonlite::flatten() %>% 
  as_tibble() %>% 
  complete() %>% 
  mutate(int_count = map_int(interpretations, n_distinct),
         obj_name = obj_name) %>% 
  select(any_of(c("name","id", "type","int_count","obj_name","created", 
                  "createdBy.name","createdBy.id")))
         
}

# ev_viz<-fetch_viz_obj("eventReports")


viz_list<-list("eventReports","maps","eventCharts","visualizations")

viz_users<-viz_list %>% 
    map_dfr(~fetch_viz_obj(.)) %>% 
    mutate(type=if_else(is.na(type),toupper(obj_name),type))

# 
# viz_users %>% 
#   filter(is.na(creator_id) & !is.na(creator_name))


viz_users %>% select(name,type,int_count) %>% slice_sample(n=6) %>% 
  kable(caption="A selection of visualizations and their interpretation count")
A selection of visualizations and their interpretation count
name type int_count
HIV: HIV testing by gender COLUMN 0
Inpatient: Mode of discharge last 12 months (stacked) STACKED_COLUMN 1
Immunization: Measles Cov Facilities this year MAPS 0
Immunization: Std dev doses given last 12 months COLUMN 0
Commodities: Maternal Health districts last 4 quarters PIVOT_TABLE 0
Child Health: Diarrhoea <5 LINE 1

Total viz saved and interpretations by viz type

419 visualizations created by 7 users.

“Interpretations” here does not include user comments on interpretations.

# viz_users %>% 
#   count(type,sort=T)


viz_users %>% 
  group_by(type) %>% 
  summarize(total_saved=n(),
            total_interpretations=sum(int_count)) %>% 
  arrange(-total_saved) %>% 
  knitr::kable(caption="Visualizations saved in time window")
Visualizations saved in time window
type total_saved total_interpretations
PIVOT_TABLE 130 9
COLUMN 96 12
MAPS 93 2
EVENTREPORTS 31 2
LINE 18 5
PIE 15 3
STACKED_COLUMN 12 1
GAUGE 6 0
BAR 4 2
RADAR 3 0
AREA 2 0
SCATTER 2 0
STACKED_BAR 2 0
YEAR_OVER_YEAR_LINE 2 0
SINGLE_VALUE 1 0
STACKED_AREA 1 0
YEAR_OVER_YEAR_COLUMN 1 0

“Viz” include event charts, event reports, pivot tables, and maps.

viz_users %>% 
  mutate(year=year(created)) %>% 
  count(year) %>%
  complete(year=seq(min(year),max(year)), fill=list(n=0)) %>% 
  ggplot(aes(x=year,y=n)) +
  geom_col() +
  labs(title="Visualizations Created By Year")

viz_users %>% 
    mutate(month=month(created,label=TRUE),
           year=year(created)) %>% 
    filter(year==year(Sys.Date())) %>% 
    count(month) %>% 
    complete(month, fill=list(n=0)) %>%
    ggplot(aes(x=month,y=n)) +
    geom_col() +
    labs(title="Visualizations Created This Year By Month")

Top 10 users creating visualizations

viz_users %>% 
  count(createdBy.name, sort=T) %>% 
  head(10) %>% 
  kable(caption="Total visualizations created, top 10 users")
Total visualizations created, top 10 users
createdBy.name n
Tom Wakiki 343
John Traore 47
NA 21
Didier Konan 5
Ali Nana 1
John Kamara 1
Kevin Boateng 1

Dashboards

Extract objects within dashboards

#Get a list of all objects in dashboards
url<-paste0(baseurl,"api/dashboards.json?fields=name,id,dashboardItems&paging=false")
dash<-fromJSON(content(GET(url),type="text", encoding="UTF-8"))

dash_stats<-dash %>% 
  pluck("dashboards") %>% 
  unnest_longer(dashboardItems) %>% 
  jsonlite::flatten() %>% 
  as_tibble() %>% 
  complete() %>% 
  select("dash_name"=name,"dash_id"=id, dashboardItems.created,dashboardItems.lastUpdated,
         dashboardItems.eventChart.id, dashboardItems.eventReport.id, 
         dashboardItems.map.id, dashboardItems.visualization.id) %>% 
  unite(col="dashItem_viz_id",dashboardItems.visualization.id:dashboardItems.eventReport.id, na.rm=T)

# we can also measure if a dashboard object has been updated or created recently

# dash_stats  %>% 
#   mutate(updated=if_else(ymd_hms(dashboardItems.created)==ymd_hms(dashboardItems.lastUpdated), 0, 1)) %>% View()
#   count(updated)

viz_users_dash<-left_join(viz_users,dash_stats %>% select(dash_name,dash_id,dashItem_viz_id), 
                          by=c("id"="dashItem_viz_id"))

#Now we can see which dashboards each viz is a part of (considering dashboards the login user can access)
viz_users_dash_merged<-viz_users_dash %>% 
        complete() %>% 
        group_by(across(.cols=name:int_count)) %>% 
        mutate(dash=if_else(is.na(dash_name),0,1)) %>% 
        summarize(dash_count=sum(dash),
                  dash_list=paste(dash_name,collapse=" | ")) %>% 
        ungroup()

There are 22 total dashboards containing 419 total visualization objects.

Dashboard Views

#post the datastatisticsevent sql view and fetch data

view_name<-"dataStatisticEvent_"
view_id<-"R6iWYMIDiUt"

sqlView<-list(
  sqlViews=list(
    list(name= view_name,
      id= view_id,
      sqlQuery= "select * from datastatisticsevent",
      type= "MATERIALIZED_VIEW",
      cacheStrategy= "NO_CACHE"
)))


payload<-jsonlite::toJSON(sqlView, auto_unbox = TRUE, pretty=TRUE)

url<-paste0(baseurl,"api/metadata.json")

r<-POST(url, body=payload, content_type_json())
#check
# content(r)

## Update sharing settings
url<-paste0(baseurl,"api/sharing?type=sqlView&id=",view_id)

view_sharing<-list(object=
                list(publicAccess="rwr------",
                  externalAccess=FALSE,
                  user=list(),
                  userGroupAccesses=list()
                )     )

r<-POST(url, body=payload, content_type_json())
#check
#content(r)

#Execute it
url<-paste0(baseurl,"api/sqlViews/",view_id,"/execute")
r<-POST(url)

#finally extract datastat event table between dates
url<-paste0(baseurl,"api/sqlViews/",view_id,"/data.csv?filter=timestamp:ge:",startdate,"&filter=timestamp:le:",enddate)

r<-httr::GET(url, httr::authenticate(username,password),httr::timeout(60))
output<-content(r)
views_dta<-read_csv(output)


# views_dta %>% 
#   filter(!is.na(favoriteuid)) %>% 
#   left_join(viz_users_dash %>% select(dash_name,dash_id), by=c("favoriteuid"="dash_id")) %>% 
#   left_join(viz_users_dash,  by=c("favoriteuid"="dash_id"))

# interpretations

# views_dta

Now analyze the dashboard view data

dashboards<-dash_stats %>% 
  filter(!is.na(dashItem_viz_id)) %>% 
  count(dash_id, dash_name, na.rm=T, name="dash_viz_objects") %>% 
  select(dash_id, dash_name, dash_viz_objects) %>% 
  na.omit() %>% 
  distinct()

dash_views<-views_dta %>% 
  filter(str_detect(eventtype,"DASH") & !is.na(favoriteuid)) %>% 
  left_join(dashboards, by=c("favoriteuid"="dash_id")) %>% 
  mutate(dash_name=if_else(is.na(dash_name),paste0("unnamed_uid_",favoriteuid),dash_name)) %>% 
  mutate(date=as.Date(ymd_hms((timestamp))),
         day=wday(date, label=TRUE, abbr=FALSE))

In total, there are 342 dashboard views across 27 existing dashboards, by 4 users.

dash_views %>% 
  mutate(timestamp=as.Date(timestamp)) %>% 
  group_by(dash_name, dash_viz_objects) %>% 
  summarize(views=n(),
            distinct_users=n_distinct(username,na.rm=T),
            days_viewed=n_distinct(timestamp,na.rm=T),
            distinct_user_days=n_distinct(paste0(username,timestamp))) %>% 
  kable(caption="Comparison of dashboards by user views")
Comparison of dashboards by user views
dash_name dash_viz_objects views distinct_users days_viewed distinct_user_days
Antenatal Care 11 95 4 29 35
Cases Malaria 8 22 2 13 16
Delivery 11 17 2 10 12
Disease Surveillance 4 10 2 6 7
EE maps 5 26 2 9 10
Immunization 17 23 2 13 16
Immunization data 10 15 2 11 12
Info Videos 5 15 2 6 6
Inpatient BMI, Weight and Height 8 11 2 7 8
Inpatient Discharge 9 13 2 7 8
Inpatient Morbidity Mortality 14 15 2 9 9
Inpatient Visit Overview 3 10 2 5 5
Key Indicators 6 8 2 4 4
Malnutrition 7 2 1 1 1
Measles (user org unit) 6 4 2 3 3
Mother and Child Health 17 3 1 1 1
Nutrition 6 3 2 3 3
Reporting Rates 8 6 1 2 2
Reporting Reproductive Health 11 9 2 4 4
Staffing 2 6 2 3 3
Top Contacts 3 6 2 4 4
unnamed_uid_cgck9Fa3uZn NA 1 1 1 1
unnamed_uid_fJ0q2N36IE1 NA 1 1 1 1
unnamed_uid_hSS0wt6gbUK NA 3 1 2 2
unnamed_uid_rmPiJIPFL4U NA 9 1 2 2
unnamed_uid_Tvro10HbSUp NA 3 1 3 3
Visits ANC 3 6 2 3 3

Over time, average views by hour of each day

Might be helpful to know how patterns of dashboard views have changed over time.

dash_views %>% 
  filter(date>floor_date(as.Date(Sys.Date()-months(12)), unit="month")) %>% 
  mutate(year=year(date),
         week=as.integer(week(date))) %>% 
  count(year,week) %>% 
  group_by(year) %>%
  complete(week=seq(from=1,to=52), fill=list(n=0)) %>% 
  ggplot() +
  geom_col(aes(x=week,y=n)) +
  facet_wrap(~year, nrow=1) +
  labs(title="Dashboard Views by Week, last 12 months")

# Dashboard viewers by time of day 
dash_tod<-dash_views %>% 
  mutate(hour=hour(timestamp)) %>% 
  group_by(date, hour) %>% 
  summarize(views_date_hour=n()) %>% 
  ungroup() %>% 
  complete(date=seq.Date(from=min(date), to=max(date),by="days")) %>% 
  group_by(date) %>% 
  complete(hour=seq(from=0,to=23),fill=list(views_date_hour=0)) %>% 
  mutate(day=wday(date, label=TRUE, abbr=FALSE)) %>% 
  group_by(day,hour) %>% 
  summarize(mean_views=mean(views_date_hour))


dash_tod %>% 
  ggplot(aes(x=hour,y=mean_views,color=day)) +
  geom_line() +
  facet_grid(~day) +
  labs(title="Mean Dashboard Views By Day-Hour") +
  theme(legend.position = "none")

dash_views %>% 
  distinct(username,date) %>% 
  count(username, sort=T) %>% 
  head(10) %>% 
  kable(caption="Most days viewing dashboard(s), by user")
Most days viewing dashboard(s), by user
username n
system 32
admin 14
analytics 2
analyticstest 1

Interpretations + Comments

  • Interpretations – Total+comments, total users, count for top 20 users, visualizations with an interpretation/comment
#fetch all interpretations within start/end date
#total interpretations by user
#total visualizations with an interpretation
#average char. length of interpretations

#Get a list of all interpretations and comments
url<-paste0(baseurl,
            "api/interpretations?fields=id,created,text,likes,type,user[id]",
            ",visualization,eventReport,map,eventChart,comments[text,user,created]",
            "&paging=false")
ints<-fromJSON(content(GET(url),type="text", encoding="UTF-8"))

# Skip this if there are no interpretations
if (!is_null(ints$interpretations)){
  
interpretations<-ints %>% 
  pluck("interpretations") %>% 
  unnest_longer(comments) %>% 
    jsonlite::flatten() %>% 
  # select(name,id,type,createdBy,interpretations) %>%
  as_tibble() %>% 
  complete() %>%
  select("int_id"=id,type,likes,text,user.id,created,
         comments.text,comments.user.id,comments.created,
         ends_with(".id")) %>% 
  unite(col="viz_item_id",visualization.id:eventReport.id,na.rm=T) %>% 
  pivot_longer(cols=c(text,comments.text),names_to="text_type",values_to="text") %>% 
  filter(!is.na(text)) %>% 
  mutate(user=if_else(text_type=="text",user.id,comments.user.id),
         created=if_else(text_type=="text",created,comments.created),
         length=str_length(text)) %>% 
  select(everything(),-comments.created,-comments.user.id,-user.id) %>% distinct()

## Selectively fetch the users who have written interpretations
int_users<-paste0(unique(interpretations$user),collapse=",")
url<-paste0(baseurl,"api/users.csv?paging=false&fields=id,name&filter=id:in:[",int_users,"]")
int_users<-read_csv(content(GET(url),type="text", encoding="UTF-8"))

int_table<-interpretations %>%
  mutate(date=as.Date(created)) %>% 
  left_join(int_users, by=c("user"="id")) %>% 
  group_by(name, user) %>%
  summarize("total interpretations"=n(),
    "unique items with interpretation"=n_distinct(viz_item_id),
    "mean length in characters"=round(mean(length),1),
    "total days with interpretation "=n_distinct(date)) %>% 
  arrange(desc(`total interpretations`)) %>% 
  head(10) %>% 
  kable(caption="Total Interpretations and Comments, Top 10 users")

total_int_comments<-nrow(interpretations)
total_int_users<-length(unique(interpretations$user))


}else{
  print("No Interpretations found")
  total_int_comments<-0
  total_int_users<-0
  int_table<-NULL %>% as_tibble()
  interpretations<-NULL
}

int_table 
Total Interpretations and Comments, Top 10 users
name user total interpretations unique items with interpretation mean length in characters total days with interpretation
Tom Wakiki GOLswS44mh8 30 19 73.4 23
John Traore xE7jOejl9FI 10 4 54.6 7
John Kamara N3PZBUlN8vq 8 5 210.1 5
Didier Konan I9fMsY4pRKk 5 5 142.8 3
NA gEnZri18JsV 5 3 221.8 2
NA EZtxytGsq8F 3 2 429.7 2
Kevin Boateng OYLGMiazHtW 1 1 129.0 1
Seydou Keita Onf73mPD6sL 1 1 201.0 1
Suleimane Diawara awtnYWiVEd5 1 1 123.0 1

Overall, 64 total interpretations and comments were left by 9 users.

Viz Profiles

Print out the visualization with stats about it.

A usage report for each visualization could look like this, with one page per visualization in the system.

viz_focus<-params$viz_focus

url<-paste0(baseurl, "api/visualizations/",viz_focus,"/data.png")
# resp<-GET(url)

r<-suppressWarnings(GET(url, 
    write_disk("test.png", overwrite = TRUE)))
knitr::include_graphics('./test.png')

viz_users %>% 
  filter(id==viz_focus) %>% 
  select(name,type,createdBy.name,created) %>% 
  t() %>%
  kable(caption="Visualization Details")
Visualization Details
name ANC: 1st and 3rd trends Monthly
type LINE
createdBy.name Tom Wakiki
created 2012-11-05T09:00:29.592
viz_users_dash %>% 
    filter(id==viz_focus) %>% select(dash_id) %>% 
    left_join(dash_views, by=c("dash_id"="favoriteuid")) %>% 
    count(dash_name, sort=T) %>% 
    kable(caption="Total Views of dashboards with this Visualization")
Total Views of dashboards with this Visualization
dash_name n
Mother and Child Health 3
interpretations %>% 
  filter(viz_item_id==viz_focus) %>% 
  count(text_type) %>% 
  kable(caption="Total interpretations and comments on Viz")
Total interpretations and comments on Viz
text_type n
comments.text 1
text 1
# url<-paste0(baseurl,"api/svg.png")
# resp<-POST(url, body=upload_file("pic_request.txt"), type="application/x-www-form-urlencoded;charset=UTF-8")
# 
# httr::content(resp)
# obj<-read_file("pic_request.txt")
# class(obj)

Save

CSV files written to the project’s “outputs” directory

outputs<-list(
  "interpretations"=interpretations,
  "dashboard_views"=dash_views,
  "all_viz_dash_views"=views_dta,
  "visualizations"=viz_users_dash
)

## If folder for outputs doesnt exist create one
if (!dir.exists(here("outputs"))){
  dir.create("outputs")
}

outputs %>% 
  names(.) %>%
  map(~ write_csv(outputs[[.]], here("outputs", paste0(., ".csv"))))
## [[1]]
## # A tibble: 64 × 9
##    int_id      type   likes created  viz_item_id text_type text     user  length
##    <chr>       <chr>  <int> <chr>    <chr>       <chr>     <chr>    <chr>  <int>
##  1 A9Gztnu9n3l VISUA…     0 2020-04… pRBQ77mhEJ8 text      We can … N3PZ…    365
##  2 A9Gztnu9n3l VISUA…     0 2012-07… pRBQ77mhEJ8 comments… Yes it … N3PZ…     86
##  3 AfuXQZm3ybv VISUA…     0 2020-03… Kt3GsRHXkaU text      This ch… I9fM…    226
##  4 Ax6kLh6VZOy VISUA…     0 2021-03… OAeeTRB4Y9E text      A large… GOLs…     65
##  5 BR11Oy1Q4yR VISUA…     0 2021-10… R9A0rvAydpn text      This ch… xE7j…     61
##  6 BR11Oy1Q4yR VISUA…     0 2014-10… R9A0rvAydpn comments… It migh… xE7j…     46
##  7 BR11Oy1Q4yR VISUA…     0 2014-10… R9A0rvAydpn comments… Yes I b… xE7j…     16
##  8 br7V5OdxEmI VISUA…     0 2020-11… nRtApqye0HW text      This pi… GOLs…    189
##  9 c4IU6PJf1Eb EVENT…     0 2021-05… qd2jBEvoRPx text      This ch… GOLs…     81
## 10 cjG99uolq7c VISUA…     0 2020-03… Emq3LEyWb15 text      We can … N3PZ…    206
## # … with 54 more rows
## 
## [[2]]
## # A tibble: 342 × 9
##    eventid eventtype      timestamp           username favoriteuid dash_name    
##      <dbl> <chr>          <dttm>              <chr>    <chr>       <chr>        
##  1  858844 DASHBOARD_VIEW 2016-06-22 18:00:42 system   nghVC4wtyzi Antenatal Ca…
##  2  858845 DASHBOARD_VIEW 2016-06-22 18:00:55 system   iMnYyBfSxmM Delivery     
##  3  858846 DASHBOARD_VIEW 2016-06-22 18:01:04 system   nghVC4wtyzi Antenatal Ca…
##  4  858847 DASHBOARD_VIEW 2016-06-22 18:01:13 system   nghVC4wtyzi Antenatal Ca…
##  5  858848 DASHBOARD_VIEW 2016-06-22 18:01:19 system   nTTLMwiwoys Inpatient Vi…
##  6  858849 DASHBOARD_VIEW 2016-06-22 18:01:38 system   eZSIccgeq94 Inpatient Di…
##  7  858850 DASHBOARD_VIEW 2016-06-22 18:01:40 system   JW7RlN5xafN Cases Malaria
##  8  858851 DASHBOARD_VIEW 2016-06-22 18:01:43 system   eZSIccgeq94 Inpatient Di…
##  9  858852 DASHBOARD_VIEW 2016-06-22 18:01:44 system   uGSg3NSw6TZ Inpatient BM…
## 10  858853 DASHBOARD_VIEW 2016-06-22 18:01:46 system   MBUMbG6zJIj Reporting Re…
## # … with 332 more rows, and 3 more variables: dash_viz_objects <int>,
## #   date <date>, day <ord>
## 
## [[3]]
## # A tibble: 2,625 × 5
##    eventid eventtype      timestamp           username favoriteuid
##      <dbl> <chr>          <dttm>              <chr>    <chr>      
##  1  624539 DASHBOARD_VIEW 2016-04-18 13:11:54 system   <NA>       
##  2  624540 DASHBOARD_VIEW 2016-04-18 13:19:28 system   <NA>       
##  3  624541 DASHBOARD_VIEW 2016-04-18 14:13:49 system   <NA>       
##  4  624542 DASHBOARD_VIEW 2016-04-18 14:14:25 system   <NA>       
##  5  624543 DASHBOARD_VIEW 2016-04-18 14:46:09 system   <NA>       
##  6  624544 DASHBOARD_VIEW 2016-04-18 14:47:19 system   <NA>       
##  7  624545 DASHBOARD_VIEW 2016-04-18 15:02:07 system   <NA>       
##  8  624546 DASHBOARD_VIEW 2016-04-18 15:02:59 system   <NA>       
##  9  624547 DASHBOARD_VIEW 2016-04-18 15:03:00 system   <NA>       
## 10  624548 DASHBOARD_VIEW 2016-04-18 15:30:26 system   <NA>       
## # … with 2,615 more rows
## 
## [[4]]
## # A tibble: 427 × 10
##    name      id     int_count obj_name created createdBy.name createdBy.id type 
##    <chr>     <chr>      <int> <chr>    <chr>   <chr>          <chr>        <chr>
##  1 Child he… YZzuV…         0 eventRe… 2017-0… Tom Wakiki     GOLswS44mh8  EVEN…
##  2 Child he… sAqSL…         0 eventRe… 2019-0… Tom Wakiki     GOLswS44mh8  EVEN…
##  3 Child he… NTOUv…         0 eventRe… 2017-0… Tom Wakiki     GOLswS44mh8  EVEN…
##  4 Inpatien… aDrb9…         0 eventRe… 2015-0… Tom Wakiki     GOLswS44mh8  EVEN…
##  5 Inpatien… TIuOz…         0 eventRe… 2014-0… John Traore    xE7jOejl9FI  EVEN…
##  6 Inpatien… p8tmW…         0 eventRe… 2017-0… Tom Wakiki     GOLswS44mh8  EVEN…
##  7 Inpatien… fmvL1…         0 eventRe… 2017-0… Tom Wakiki     GOLswS44mh8  EVEN…
##  8 Inpatien… itNBw…         0 eventRe… 2014-0… John Traore    xE7jOejl9FI  EVEN…
##  9 Inpatien… R4wAb…         0 eventRe… 2014-0… John Traore    xE7jOejl9FI  EVEN…
## 10 Inpatien… pLJAn…         0 eventRe… 2014-0… John Traore    xE7jOejl9FI  EVEN…
## # … with 417 more rows, and 2 more variables: dash_name <chr>, dash_id <chr>