<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>empirical bayes | On clinical microbiology and data</title>
    <link>http://mtk.one/tag/empirical-bayes/</link>
      <atom:link href="http://mtk.one/tag/empirical-bayes/index.xml" rel="self" type="application/rss+xml" />
    <description>empirical bayes</description>
    <generator>Wowchemy (https://wowchemy.com)</generator><language>en-us</language><lastBuildDate>Mon, 21 Oct 2019 00:00:00 +0000</lastBuildDate>
    <image>
      <url>http://mtk.one/media/icon_hua2ec155b4296a9c9791d015323e16eb5_11927_512x512_fill_lanczos_center_3.png</url>
      <title>empirical bayes</title>
      <link>http://mtk.one/tag/empirical-bayes/</link>
    </image>
    
    <item>
      <title>HAIBA and me</title>
      <link>http://mtk.one/post/haiba/haiba-and-me/</link>
      <pubDate>Mon, 21 Oct 2019 00:00:00 +0000</pubDate>
      <guid>http://mtk.one/post/haiba/haiba-and-me/</guid>
      <description>


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;So. There’s this thing called &lt;a href=&#34;http://end2019.esundhed.dk/sundhedskvalitet/HAIBA/Sider/haiba_rapport.aspx&#34;&gt;HAIBA&lt;/a&gt;. It is the danish Hospital-Acquired Infections database.&lt;/p&gt;
&lt;p&gt;The database is built on the proud danish tradition of databasing &lt;em&gt;everything&lt;/em&gt;, it works by crossreferencing the national patient registry (LPR) and the national microbiological database (MiBa). LPR provides times of admission to hospital and transfers between departments. MiBa provides samples taken and sample results from clinical microbiology labs.&lt;/p&gt;
&lt;p&gt;The database is great, and it is not so great.&lt;/p&gt;
&lt;p&gt;Monitoring hospital-acquired infections is obviously a great goal and the crossreferencing of two massive databases is a gargantuan task. But as a &lt;a href=&#34;http://www.rigsrevisionen.dk/publikationer/2017/52017/&#34;&gt;report&lt;/a&gt; from the Danish National audit (rigsrevisionen) details, almost no departments actually use the database to improve.&lt;/p&gt;
&lt;p&gt;I wanted to analyse differences over time and between departments in the database.&lt;/p&gt;
&lt;p&gt;From the database i downloaded 93 datasets - corresponding to one from every department in the region of central Denmark, it took a while. If you want to follow along you can download a &lt;a href=&#34;haiba.csv&#34;&gt;csv version&lt;/a&gt; of the dataset i made.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)
library(furrr)
plan(multisession)
library(brms)
library(here)
library(ebbr) #devtools::install_github(&amp;quot;dgrtwo/ebbr&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;loading&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Loading&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;files &amp;lt;- list.files(here(&amp;quot;content&amp;quot;, &amp;quot;post&amp;quot;, &amp;quot;haiba&amp;quot;, &amp;quot;2019-10-21-haiba-and-me&amp;quot;, &amp;quot;data_uvi&amp;quot;), recursive = TRUE, full.names = TRUE, pattern = &amp;quot;.csv&amp;quot;)

read_haiba &amp;lt;- function(file) {
    blank_lines &amp;lt;- which(grepl(&amp;quot;^$&amp;quot;, readLines(file)))
    meta &amp;lt;- read_csv(file,
                     skip = blank_lines[length(blank_lines) - 1] - 1,
                     show_col_types = FALSE) %&amp;gt;%
        mutate_all( ~ str_split(.x, &amp;quot;: &amp;quot;) %&amp;gt;% map_chr(2))
    colnames(meta) &amp;lt;- c(&amp;quot;sidste_opdatering&amp;quot;,
                        &amp;quot;rapport_fra&amp;quot;,
                        &amp;quot;region&amp;quot;,
                        &amp;quot;ejer&amp;quot;,
                        &amp;quot;hospital&amp;quot;, 
                        &amp;quot;afdeling&amp;quot;)
    raw &amp;lt;- read_csv(file, 
                    skip = 3, 
                    n_max = blank_lines[2] - blank_lines[1] - 2, 
                    locale = locale(decimal_mark = &amp;quot;,&amp;quot;),
                    show_col_types = FALSE)
    clean &amp;lt;- raw %&amp;gt;% 
        select(Year:Denominator2) %&amp;gt;% 
        janitor::clean_names() %&amp;gt;% 
        rename(week = month) %&amp;gt;% 
        mutate(yearweek = sprintf(&amp;quot;%i-W%02i&amp;quot;, year, week),
               sort_date = paste0(yearweek, &amp;quot;-5&amp;quot;) %&amp;gt;% ISOweek::ISOweek2date(),
               date_rank = rank(sort_date)) %&amp;gt;% 
        filter(sort_date &amp;lt; lubridate::dmy(meta$sidste_opdatering)[1]) 
    cbind(clean, select(meta, hospital, afdeling))
}    

afd_type &amp;lt;- read_csv(&amp;quot;typer.csv&amp;quot;, show_col_types = FALSE)
haiba &amp;lt;- future_map_dfr(files, read_haiba) %&amp;gt;% 
    left_join(afd_type) %&amp;gt;% 
    mutate_at(vars(contains(&amp;quot;nominator&amp;quot;)), as.integer)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Okay, so that’s loading done. Let’s do some basic checks. It appears that the web-version of HAIBA reports use the columns nominator1 and denominator1.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;exploration&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Exploration&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;head(haiba)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##   year week nominator1 incidence1 denominator1 nominator4 incidence3
## 1 2019    4          1     317.04           32          1     317.04
## 2 2019    3          0       0.00           25          0       0.00
## 3 2019    2          0       0.00           15          0       0.00
## 4 2019    1          0       0.00           12          0       0.00
## 5 2018   52          0       0.00           15          0       0.00
## 6 2018   51          0       0.00           13          0       0.00
##   denominator2 yearweek  sort_date date_rank                    hospital
## 1           32 2019-W04 2019-01-25       265 Aarhus Universitetshospital
## 2           25 2019-W03 2019-01-18       264 Aarhus Universitetshospital
## 3           15 2019-W02 2019-01-11       263 Aarhus Universitetshospital
## 4           12 2019-W01 2019-01-04       262 Aarhus Universitetshospital
## 5           15 2018-W52 2018-12-28       261 Aarhus Universitetshospital
## 6           13 2018-W51 2018-12-21       260 Aarhus Universitetshospital
##                  afdeling afd_type
## 1 Akutafdeling Akutafsnit     akut
## 2 Akutafdeling Akutafsnit     akut
## 3 Akutafdeling Akutafsnit     akut
## 4 Akutafdeling Akutafsnit     akut
## 5 Akutafdeling Akutafsnit     akut
## 6 Akutafdeling Akutafsnit     akut&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mean(haiba$denominator1 &amp;lt; 1) %&amp;gt;% scales::percent()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;16%&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;with(haiba, mean(nominator1 &amp;gt; denominator1)) %&amp;gt;% scales::percent()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;0%&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;16% of observations are 0 and some observations seem to show more cases than persondays, which is weird to say the least.&lt;/p&gt;
&lt;p&gt;Let’s do a little visualisation&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;quarters &amp;lt;- data.frame(week = 1:53, quarter = c(rep(1:4, each = 13), 4))

haiba %&amp;gt;% 
    left_join(quarters) %&amp;gt;% 
    mutate(yearq = paste(year, quarter, sep = &amp;quot;-&amp;quot;)) %&amp;gt;% 
    group_by(afd_type, yearq) %&amp;gt;% 
    summarise(nominator = sum(nominator1),
              denominator = sum(denominator1)) %&amp;gt;% 
    ungroup %&amp;gt;% 
    filter(denominator &amp;gt; 0) %&amp;gt;% 
    mutate(date_rank = dense_rank(yearq)) %&amp;gt;% #Dangerous, but seems to work
    group_by(afd_type) %&amp;gt;% 
    group_modify(~ add_ebb_estimate(.x, nominator, denominator)) -&amp;gt; afd_type_quarter&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Joining, by = &amp;quot;week&amp;quot;
## `summarise()` has grouped output by &amp;#39;afd_type&amp;#39;. You can override using the
## `.groups` argument.&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Warning: `data_frame()` was deprecated in tibble 1.1.0.
## Please use `tibble()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(afd_type_quarter, aes(date_rank, .fitted*1e4, colour = afd_type)) + 
    geom_smooth(method = &amp;quot;lm&amp;quot;, se = FALSE) +
    geom_point() + 
    facet_wrap(~afd_type, scales = &amp;quot;free_y&amp;quot;) + 
    expand_limits(y = 0) +
    scale_colour_viridis_d() +
    theme(legend.position = &amp;quot;none&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## `geom_smooth()` using formula &amp;#39;y ~ x&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://mtk.one/post/haiba/haiba-and-me/index.en_files/figure-html/afd_type_quarter_vis-1-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Let’s gussy that up a bit.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(afd_type_quarter, aes(date_rank, .raw*1e4, colour = afd_type)) + 
    geom_ribbon(aes(ymin = .low*1e4, ymax = .high*1e4), fill = &amp;quot;gray&amp;quot;, colour = &amp;quot;gray&amp;quot;) + 
    geom_smooth(method = &amp;quot;lm&amp;quot;, se = FALSE) +
    geom_point() + 
    facet_wrap(~afd_type, scales = &amp;quot;free_y&amp;quot;, labeller = labeller(afd_type = Hmisc::capitalize), nrow = 2) + 
    expand_limits(y = 0) +
    scale_colour_viridis_d() +
    scale_x_continuous(breaks = c(seq(0, 20, by = 4))) +
    labs(x = &amp;quot;kvartal fra start&amp;quot;, 
         y = &amp;quot;incidens pr 10^4 patientdøgn&amp;quot;, 
         caption = &amp;quot;Data fra HAIBA\n95% Konfidensintervaller baseret på empirical bayes\nLineær regression vist uden konfidensintervaller&amp;quot;,
         title = &amp;quot;Hospitalserhvervede urinvejsinfektioner i region midt&amp;quot;) +
    theme(legend.position = &amp;quot;none&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## `geom_smooth()` using formula &amp;#39;y ~ x&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://mtk.one/post/haiba/haiba-and-me/index.en_files/figure-html/afd_type_quarter_vis-2-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;p&gt;There are some interesting things going on in this visualisation. Most department types seem to be have decreasing UTI incidence. But, what is going on with pediatric and acute departments?&lt;/p&gt;
&lt;p&gt;Some insight may be gleaned from the diference between the linear regression on incidence and the grayed out ribbons. Remember, the ribbons display empirical bayes estimates, these are calculated WITHOUT knowledge of the time effects.&lt;/p&gt;
&lt;p&gt;For acute departments there appears to be a somewhat seasonal effect, perhaps patients dont stay on the service for long enough to become cases in summer.&lt;/p&gt;
&lt;p&gt;Pediatric departments seem more erratic, and it would seem fair to assume that what we’re seeing is merely random variation.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;modeling&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Modeling&lt;/h1&gt;
&lt;p&gt;If i want an actual answer to whether incidences are decreasing, there’s probably no way around some modeling work.&lt;/p&gt;
&lt;p&gt;Seeing as we’re working on count data with large observation times, it would seem reasonable to model the outcome as poisson distributed.&lt;/p&gt;
&lt;p&gt;I want to be able to compare individual departments on their initial incidence, their progress over time, and their incidence at the end. I could feasibly fit a normal &lt;code&gt;glm&lt;/code&gt; model with &lt;code&gt;offset = log(denominator1)&lt;/code&gt; and fixed effects for departments, but some departments are much smaller than others and their mere size would bias the analysis so that large departments would look closer to average, just from having less random variation.&lt;/p&gt;
&lt;p&gt;So, what i actually want is a bayesian model with partial pooling on departments for both intercept and slope, fixed effects for department type. Let’s see if i can figure that out&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;halfyear &amp;lt;- data.frame(week = 1:53, halfyear = c(rep(1:2, each = 26), 2))

null_departments &amp;lt;- haiba %&amp;gt;% # Some departments have 0 cases in total. Thats great, but not very informative.
    group_by(afdeling) %&amp;gt;% 
    summarise(nominator = sum(nominator1),
              denominator = sum(denominator1)) %&amp;gt;% 
    filter(nominator == 0) 

haiba %&amp;gt;% 
    anti_join(null_departments, by = &amp;quot;afdeling&amp;quot;) %&amp;gt;% # Potentielt kontroversielt, men i praksis nok mere data-cleaning
    left_join(halfyear) %&amp;gt;% 
    mutate(yearh = paste(year, halfyear, sep = &amp;quot;-&amp;quot;)) %&amp;gt;% 
    group_by(afdeling, yearh) %&amp;gt;% 
    summarise(nominator = sum(nominator1),
              denominator = sum(denominator1), 
              afd_type = unique(afd_type)) %&amp;gt;% 
    ungroup %&amp;gt;% 
    filter(denominator &amp;gt; 0) %&amp;gt;% 
    mutate(date_rank = dense_rank(yearh)) -&amp;gt; afdeling_halfyear&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Joining, by = &amp;quot;week&amp;quot;
## `summarise()` has grouped output by &amp;#39;afdeling&amp;#39;. You can override using the
## `.groups` argument.&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mm_data_afd &amp;lt;- afdeling_halfyear %&amp;gt;% 
    mutate_at(vars(contains(&amp;quot;nominator&amp;quot;)), as.integer) %&amp;gt;% 
    mutate_at(vars(contains(&amp;quot;afd&amp;quot;)), as.factor)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;brms-model&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;brms model&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;n_cores &amp;lt;- parallel::detectCores()
model &amp;lt;- brm(nominator ~ 0 + offset(log(denominator)) + date_rank + afd_type + (1 + date_rank | afdeling),
          data = mm_data_afd,
          family = &amp;quot;poisson&amp;quot;,
          chains = n_cores, cores = n_cores, file = here(&amp;quot;content&amp;quot;, &amp;quot;post&amp;quot;, &amp;quot;haiba&amp;quot;, &amp;quot;2019-10-21-haiba-and-me&amp;quot;, &amp;quot;model&amp;quot;)) &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;model-checks&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Model checks&lt;/h1&gt;
&lt;p&gt;Did the chains converge?&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;plot(model)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://mtk.one/post/haiba/haiba-and-me/index.en_files/figure-html/convergence-1.png&#34; width=&#34;672&#34; /&gt;&lt;img src=&#34;http://mtk.one/post/haiba/haiba-and-me/index.en_files/figure-html/convergence-2.png&#34; width=&#34;672&#34; /&gt;&lt;img src=&#34;http://mtk.one/post/haiba/haiba-and-me/index.en_files/figure-html/convergence-3.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Seems reasonable enough.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;model&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##  Family: poisson 
##   Links: mu = log 
## Formula: nominator ~ 0 + offset(log(denominator)) + date_rank + afd_type + (1 + date_rank | afdeling) 
##    Data: mm_data_afd (Number of observations: 822) 
##   Draws: 6 chains, each with iter = 2000; warmup = 1000; thin = 1;
##          total post-warmup draws = 6000
## 
## Group-Level Effects: 
## ~afdeling (Number of levels: 80) 
##                          Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
## sd(Intercept)                0.71      0.07     0.58     0.87 1.01     1420
## sd(date_rank)                0.03      0.01     0.02     0.04 1.00     2150
## cor(Intercept,date_rank)    -0.41      0.19    -0.73     0.02 1.00     2630
##                          Tail_ESS
## sd(Intercept)                2875
## sd(date_rank)                3391
## cor(Intercept,date_rank)     4044
## 
## Population-Level Effects: 
##                  Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## date_rank           -0.02      0.01    -0.03    -0.01 1.00     2836     3828
## afd_typeakut        -5.54      0.33    -6.20    -4.88 1.00     3854     4202
## afd_typeandet       -5.88      0.24    -6.35    -5.41 1.00     1969     2427
## afd_typebørn        -6.88      0.38    -7.62    -6.15 1.00     3958     4450
## afd_typeintensiv    -3.88      0.69    -5.22    -2.49 1.00     5174     4229
## afd_typekirurgi     -5.86      0.12    -6.11    -5.63 1.00     1017     1925
## afd_typekræft       -5.92      0.40    -6.70    -5.16 1.00     2634     3600
## afd_typemedicin     -5.30      0.15    -5.59    -5.01 1.00      803     1294
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No dire warnings here either. Effective sample sizes could be higher.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;hypothesis-1-infection-control-is-improving&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Hypothesis 1: Infection control is improving&lt;/h1&gt;
&lt;p&gt;Lets test the hypothesis that number of cases is falling over time&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;hypothesis(model, &amp;quot;date_rank &amp;lt; 0&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Hypothesis Tests for class b:
##        Hypothesis Estimate Est.Error CI.Lower CI.Upper Evid.Ratio Post.Prob
## 1 (date_rank) &amp;lt; 0    -0.02      0.01    -0.03    -0.01        299         1
##   Star
## 1    *
## ---
## &amp;#39;CI&amp;#39;: 90%-CI for one-sided and 95%-CI for two-sided hypotheses.
## &amp;#39;*&amp;#39;: For one-sided hypotheses, the posterior probability exceeds 95%;
## for two-sided hypotheses, the value tested against lies outside the 95%-CI.
## Posterior probabilities of point hypotheses assume equal prior probabilities.&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;marginal_effects(model, &amp;quot;date_rank&amp;quot;, spaghetti = TRUE, nsamples = 1e3, conditions = data.frame(denominator = 1e4))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Warning: Method &amp;#39;marginal_effects&amp;#39; is deprecated. Please use
## &amp;#39;conditional_effects&amp;#39; instead.&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Warning: Argument &amp;#39;nsamples&amp;#39; is deprecated. Please use argument &amp;#39;ndraws&amp;#39;
## instead.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://mtk.one/post/haiba/haiba-and-me/index.en_files/figure-html/marginal-date_rank-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;p&gt;It would appear beyond reasonable doubt that there is indeed a falling incidence of HA-UTI. What is the magnitude of this fall?&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;broom.mixed::tidy(model) %&amp;gt;% 
  filter(term == &amp;quot;date_rank&amp;quot;) %&amp;gt;% 
  select(-std.error) %&amp;gt;% 
  mutate_at(vars(estimate:conf.high), ~ 1 - exp(. * (mm_data_afd$date_rank %&amp;gt;% range %&amp;gt;% diff))) %&amp;gt;% 
  mutate_at(vars(estimate:conf.high), scales::percent) %&amp;gt;% 
  glue::glue_data(&amp;quot;The overall reduction from the beginning of HAIBA (2014 week 1) to the latest point in our dataset (2019 week 4) is {estimate} [95% CI: {conf.high}; {conf.low}]&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Warning in tidy.brmsfit(model): some parameter names contain underscores: term
## naming may be unreliable!&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## The overall reduction from the beginning of HAIBA (2014 week 1) to the latest point in our dataset (2019 week 4) is 16% [95% CI: 5%; 25%]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Are any departments falling way out of line with the overall trend?&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;hypothesis(model, &amp;quot;date_rank = 0&amp;quot;, group = &amp;quot;afdeling&amp;quot;, scope = &amp;quot;ranef&amp;quot;) %&amp;gt;% 
  .$hypothesis %&amp;gt;% 
  filter(Star == &amp;quot;*&amp;quot;) -&amp;gt; differently_changed

mm_data_afd %&amp;gt;% 
    semi_join(differently_changed, by = c(&amp;quot;afdeling&amp;quot; = &amp;quot;Group&amp;quot;)) %&amp;gt;% 
    ggplot(aes(date_rank, nominator/(denominator/1e4), colour = afdeling)) +
    geom_point() +
    scale_colour_viridis_d(option = &amp;quot;A&amp;quot;) +
    geom_smooth(method = &amp;quot;lm&amp;quot;, se = FALSE) + 
    expand_limits(y = 0)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## `geom_smooth()` using formula &amp;#39;y ~ x&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://mtk.one/post/haiba/haiba-and-me/index.en_files/figure-html/random-slopes-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;It would appear that both departments have made massive improvements.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;hypothesis-2-departments-are-very-different&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Hypothesis 2: Departments are (very) different&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;conditional_effects(model, &amp;quot;afd_type&amp;quot;, conditions = data.frame(denominator = 1e4))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://mtk.one/post/haiba/haiba-and-me/index.en_files/figure-html/department_type-vis-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;last_plot() + coord_flip()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://mtk.one/post/haiba/haiba-and-me/index.en_files/figure-html/department_type-vis-2.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Okay, so intensive care units have more cases. That’s probably not a big surprise to anyone. Many of the “cases” are probably misclassifications due to more frequent urinary sampling and the increased difficulty in ascertaining symptoms from patients in intensive care.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;hypothesis(model, &amp;quot;Intercept = 0&amp;quot;, group = &amp;quot;afdeling&amp;quot;, scope = &amp;quot;ranef&amp;quot;) %&amp;gt;%
    .$hypothesis %&amp;gt;% 
    filter(Star == &amp;quot;*&amp;quot;) -&amp;gt; differently_started

differently_started %&amp;gt;% 
    mutate(Group = forcats::fct_reorder(Group, Estimate)) %&amp;gt;% 
    ggplot(aes(Group, exp(Estimate), colour = Estimate)) + 
    geom_ribbon(aes(ymin = exp(CI.Lower), ymax = exp(CI.Upper))) +
    geom_point() + 
    scale_colour_viridis_c(option = &amp;quot;C&amp;quot;) + 
    theme(legend.position = &amp;quot;none&amp;quot;) + 
    coord_flip() +
    labs(y = &amp;quot;Rate ratio ifht afdelingstype&amp;quot;, x = NULL,
         caption = &amp;quot;Data fra HAIBA\nVist med 95% konfidensintervaller&amp;quot;) &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://mtk.one/post/haiba/haiba-and-me/index.en_files/figure-html/differently_started-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;A few surprises here, but overall as expected. Some of the departments seem to have been picked up due to insufficient correction in the “Other” department type.&lt;/p&gt;
&lt;p&gt;That’s the intercept done with. But where do these departments end up? Do they come into line with the pack?&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;new_from_differently_started &amp;lt;- mm_data_afd %&amp;gt;% 
  semi_join(differently_started, by = c(&amp;quot;afdeling&amp;quot; = &amp;quot;Group&amp;quot;)) %&amp;gt;% 
  select(afdeling, afd_type) %&amp;gt;% 
  distinct() %&amp;gt;% 
  mutate(date_rank = 12,
         denominator = 1e4)

quick_clean &amp;lt;- . %&amp;gt;% 
  as_tibble() %&amp;gt;% 
  janitor::clean_names()

predictions &amp;lt;- predict(model, newdata = new_from_differently_started) %&amp;gt;% 
  quick_clean %&amp;gt;% 
  bind_cols(new_from_differently_started) %&amp;gt;% 
  mutate(condition = &amp;quot;At end&amp;quot;)

unknown_departments &amp;lt;- mm_data_afd %&amp;gt;% 
  distinct(afd_type) %&amp;gt;% 
  mutate(afdeling = wakefield::name(n()),
         date_rank = 12,
         denominator = 1e4)

predicted_beginnings &amp;lt;- predict(model, newdata = new_from_differently_started %&amp;gt;% mutate(date_rank = 1)) %&amp;gt;% 
  quick_clean() %&amp;gt;% 
  bind_cols(new_from_differently_started %&amp;gt;% select(afdeling)) %&amp;gt;% 
  mutate(condition = &amp;quot;At beginning&amp;quot;)

predictions_for_unknown &amp;lt;- predict(model, newdata = unknown_departments, allow_new_levels = TRUE) %&amp;gt;% 
  as_tibble() %&amp;gt;% 
  janitor::clean_names() %&amp;gt;% 
  bind_cols(unknown_departments) %&amp;gt;% 
  mutate(condition = &amp;quot;Unknown department&amp;quot;)

different_started_by_the_end &amp;lt;- predictions %&amp;gt;% 
  left_join(predictions_for_unknown, by = &amp;quot;afd_type&amp;quot;) %&amp;gt;% 
  left_join(predicted_beginnings, by = c(&amp;quot;afdeling.x&amp;quot; = &amp;quot;afdeling&amp;quot;), suffix = c(&amp;quot;&amp;quot;, &amp;quot;.z&amp;quot;))

bind_rows(predicted_beginnings, predictions) %&amp;gt;% 
  left_join(predictions_for_unknown, by = &amp;quot;afd_type&amp;quot;, suffix = c(&amp;quot;&amp;quot;, &amp;quot;.y&amp;quot;)) %&amp;gt;% 
  mutate(afdeling = forcats::fct_reorder(afdeling, estimate, .fun = first)) %&amp;gt;% 
  ggplot(aes(afdeling, estimate, colour = condition)) +
  geom_ribbon(aes(afdeling, ymin = q2_5, ymax = q97_5), data = ~ filter(.x, condition == &amp;quot;At end&amp;quot;), colour = &amp;quot;gray&amp;quot;) +
  geom_point() +
  geom_point(aes(afdeling, estimate.y, colour = &amp;quot;Department type&amp;quot;), show.legend = TRUE) + 
  coord_flip() + 
  scale_colour_brewer(palette = &amp;quot;Set2&amp;quot;, direction = -1) + 
  theme(legend.position = &amp;quot;bottom&amp;quot;) + 
  labs(x = &amp;quot;Department&amp;quot;, 
       y = &amp;quot;Cases pr. 10000 persondays&amp;quot;, 
       colour = &amp;quot;Prediction case&amp;quot;, 
       caption = &amp;quot;Data from HAIBA&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Warning: Removed 34 rows containing missing values (geom_point).&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://mtk.one/post/haiba/haiba-and-me/index.en_files/figure-html/differently_ended-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;honorable-mention-to-the-departments-without-any-cases&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Honorable mention to the departments without any cases&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;null_departments %&amp;gt;% arrange(desc(denominator))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tibble: 13 × 3
##    afdeling                                       nominator denominator
##    &amp;lt;chr&amp;gt;                                              &amp;lt;int&amp;gt;       &amp;lt;int&amp;gt;
##  1 Livsstilscenter Brædstrup, Sengeafdeling - BRÆ         0       31597
##  2 Fokuseret Neurorehabilitering Hammel                   0       13759
##  3 Tand-, Mund- og Kæbekirurgi Sengeafdeling              0        2493
##  4 Hånd Stamafdeling Ortopædkirurgi                       0        2475
##  5 Skulder Stamafdeling Ortopædkirurgi                    0        1677
##  6 Idræt Stamafdeling Ortopædkirurgi                      0        1220
##  7 Brystkirurgi Stationær                                 0         678
##  8 Øre-, Næse- og Halssygdomme - Randers                  0         290
##  9 Infektion Stamafdeling Ortopædkirurgi                  0          28
## 10 Akutmodtagelse Q - Randers                             0          21
## 11 Øjenafdeling Dagkirurgi Stationær J                    0          16
## 12 Neurokirurgisk Dagkirurgi Stationær NK                 0          15
## 13 Kirurgisk Dagkirurgi P Stationær Afdeling              0           6&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>
    </item>
    
  </channel>
</rss>
