-
Notifications
You must be signed in to change notification settings - Fork 3
/
06-AttributeData.Rmd
executable file
·155 lines (106 loc) · 6.78 KB
/
06-AttributeData.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# Control charts for count, proportion, or rate data {#attribute}
| If your data involve... | use a ... | based on the ... distribution. |
| -------------------------------------- | --------- | ------------------------ |
| Rates | *u* chart | Poisson |
| Counts (with equal sampling units) | *c* chart | Poisson |
| Proportions | *p* chart | binomial |
| Proportions (with equal denominators) | *np* chart | binomial |
| Rare events | *g* chart | geometric |
- For count, rate, or proportion data, carefully define your numerator and denominator. Evaluate each separately over time to see whether there are any unusual features or patterns. Sometimes patterns can occur in one or the other, then disappear or are obscured when coalesced into a rate or proportion.
- For count data, prefer *u*-charts to *c*-charts. In most cases, we do not have a constant denominator, so c-charts would not be appropriate. Even when we do, using a *u*-chart helps reduce audience confusion because you are explicitly stating the "per *x*".
- For proportion data, prefer *p*-charts to *np*-charts. Again, we almost never have a constant denominator, so *np*-charts would not be appropriate. Even when we do, using a *p*-chart helps reduce audience confusion by explicitly stating the "per *x*".
- Rare events can be evaluated either by *g*-charts (this chapter) for discrete events/time steps, or *t*-charts ([next chapter](#tchart)) for continuous time.
## *u*-chart example
The majority of healthcare metrics of concern are rates, so the most common control chart is the *u*-chart.
Sometimes, a KPI is based on counts. This is obviously problematic for process monitoring in most healthcare situations because it ignores the risk exposure---for example, counting the number of infections over time is meaningless if you don't account for the change in the number of patients in that same time period. When KPIs are measuring counts with a denominator that is *truly fixed*, technically a *c*-chart can be used. This makes sense in manufacturing, but not so much in healthcare, where the definition of the denominator can be very important. You should always use a context-relevant denominator, so in basically all cases a *u*-chart should be preferred to a *c*-chart.
**Mean for rates (*u*):** $u = {\frac{\Sigma{c_i}}{{\Sigma{n_i}}}}$
**3$\sigma$ control limits for rates (*u*):** $3\sqrt{\frac{u}{n_i}}$
<br/>
*Infections per 1000 central line days*
``` {r uex}
# Generate fake infections data
set.seed(72)
dates = seq(as.Date("2013/10/1"), by = "day", length.out = 730)
linedays = sample(30:60,length(dates), replace = TRUE)
infections = rpois(length(dates), 2/1000*linedays)
months = as.Date(strftime(dates, "%Y-%m-01"))
dfi = data.frame(months, linedays, infections)
infections.agg = aggregate(dfi$infections, by = list(months), FUN = sum, na.rm = TRUE)$x
linedays.agg = aggregate(dfi$linedays, by = list(months), FUN = sum, na.rm = TRUE)$x
# Calculate u chart inputs
subgroup.u = unique(months)
point.u = infections.agg / linedays.agg * 1000
central.u = sum(infections.agg) / sum(linedays.agg) * 1000
sigma.u = sqrt(central.u / linedays.agg * 1000)
```
```{r uchart_example, fig.height = 3.5}
# Plot u chart
spc.plot(subgroup.u, point.u, central.u, sigma.u, k = 3, lcl.min = 0,
label.x = "Month", label.y = "Infections per 1000 line days")
```
See Appendix for details of the spc.plots() function.
<br/>
## *p*-chart example
When your metric is a true proportion (and not a rate, e.g., a count per 100), a *p*-chart is the appropriate control chart to use.
**Mean for proportions (*p*):** $p = {\frac{\Sigma{y_i}}{\Sigma{n_i}}}$
**3$\sigma$ control limits for proportions (*p*):** $3\sqrt{\frac {p (1 - p)}{n_i}}$
<br/>
*Proportion of patients readmitted*
``` {r pex, fig.height = 3.5}
# Generate sample data
discharges = sample(300:500, 24)
readmits = rbinom(24, discharges, .2)
dates = seq(as.Date("2013/10/1"), by = "month", length.out = 24)
# Calculate p chart inputs
subgroup.p = dates
point.p = readmits / discharges
central.p = sum(readmits) / sum(discharges)
sigma.p = sqrt(central.p*(1 - central.p) / discharges)
# Plot p chart
spc.plot(subgroup.p, point.p, central.p, sigma.p,
label.x = "Month", label.y = "Proportion readmitted")
```
<br/>
## Rare events (*g*-charts) {#gchart}
There are important KPIs in healthcare related to rare events, such as is common in patient safety and infection control. These commonly have 0 values for several subgroups within the process time-period. In these cases, you need to use *g*-charts for a discrete time scale (e.g., days between events) or *t*-charts for a continuous time scale (e.g., time between events). See [Chapter 10](#tchart)) for details on using *t*-charts to evaluate the time between events.
### *g*-chart example
**Mean for infrequent counts (*g*):** $g = {\frac{\Sigma{g_i}}{\Sigma{n_i}}}$
*where*
$g$ = units/opportunities between events
**3$\sigma$ limits for infrequent counts (*g*):** $3\sqrt{g (g + 1)}$
<br/>
*Days between infections*
``` {r gex}
# Generate fake data using u-chart example data
infections.index = which(infections > 0)[1:30]
dfind = data.frame(start = head(infections.index, length(infections.index) - 1) + 1,
end = tail(infections.index, length(infections.index) - 1))
linedays.btwn = matrix( , length(dfind$start))
for (i in 1:length(linedays.btwn)) {
sumover = seq(dfind$start[i], dfind$end[i])
linedays.btwn[i] = sum(linedays[sumover])
}
# Calculate g chart inputs
subgroup.g = seq(2, length(infections.index))
point.g = linedays.btwn
central.g = mean(point.g)
sigma.g = rep(sqrt(central.g*(central.g+1)), length(point.g))
```
```{r gchart_example, fig.height = 3.5}
# Plot g chart
spc.plot(subgroup.g, point.g, central.g, sigma.g, lcl.show = FALSE,
band.show = FALSE, rule.show = FALSE,
lcl.min = 0, k = 3, label.x = "Infection number",
label.y = "Line days between infections")
```
<br/>
## *c*- and *np*-chart details
Simply for completeness, means and control limits for *c*- and *np*-charts are presented here. To emphasize that *u*- and *p*-charts should be preferred (respectively), no examples are given.
**Mean for counts (*c*):** $\frac{\Sigma{c_i}}{n}$
**3$\sigma$ control limits for counts (*c*)(not shown):** $3\sqrt{c}$
**Mean for equal-opporuntity proportions (*np*):** $np = {\frac{\Sigma{y_i}}{n}}$
*where*
$n$ is a constant
**3$\sigma$ control limits for equal-opporuntity proportions (*np*):** $3\sqrt{np (1 - p)}$
*where*
$n$ is a constant