Skip to content

Commit 3e0978f

Browse files
authored
Merge pull request #1470 from MIT-LCP/kdigo_fixes
KDIGO improvements
2 parents 30c7bcc + 5504c41 commit 3e0978f

File tree

2 files changed

+119
-63
lines changed

2 files changed

+119
-63
lines changed

mimic-iv/concepts/organfailure/kdigo_stages.sql

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,15 @@ WITH cr_stg AS
4343
WHEN uo.uo_rt_6hr IS NULL THEN NULL
4444
-- require patient to be in ICU for at least 6 hours to stage UO
4545
WHEN uo.charttime <= DATETIME_ADD(ie.intime, INTERVAL '6' HOUR) THEN 0
46-
-- require the UO rate to be calculated over half the period
47-
-- i.e. for uo rate over 24 hours, require documentation at least 12 hr apart
48-
WHEN uo.uo_tm_24hr >= 11 AND uo.uo_rt_24hr < 0.3 THEN 3
49-
WHEN uo.uo_tm_12hr >= 5 AND uo.uo_rt_12hr = 0 THEN 3
50-
WHEN uo.uo_tm_12hr >= 5 AND uo.uo_rt_12hr < 0.5 THEN 2
51-
WHEN uo.uo_tm_6hr >= 2 AND uo.uo_rt_6hr < 0.5 THEN 1
46+
-- require the UO rate to be calculated over duration specified in KDIGO
47+
-- Stage 3: <0.3 ml/kg/h for >=24 hours
48+
WHEN uo.uo_tm_24hr >= 24 AND uo.uo_rt_24hr < 0.3 THEN 3
49+
-- *or* anuria for >= 12 hours
50+
WHEN uo.uo_tm_12hr >= 12 AND uo.uo_rt_12hr = 0 THEN 3
51+
-- Stage 2: <0.5 ml/kg/h for >= 12 hours
52+
WHEN uo.uo_tm_12hr >= 12 AND uo.uo_rt_12hr < 0.5 THEN 2
53+
-- Stage 1: <0.5 ml/kg/h for 6–12 hours
54+
WHEN uo.uo_tm_6hr >= 6 AND uo.uo_rt_6hr < 0.5 THEN 1
5255
ELSE 0 END AS aki_stage_uo
5356
FROM `physionet-data.mimiciv_derived.kdigo_uo` uo
5457
INNER JOIN `physionet-data.mimiciv_icu.icustays` ie
@@ -62,7 +65,8 @@ crrt_stg AS (
6265
CASE
6366
WHEN charttime IS NOT NULL THEN 3
6467
ELSE NULL END AS aki_stage_crrt
65-
FROM `physionet-data.mimic_derived.crrt`
68+
FROM `physionet-data.mimiciv_derived.crrt`
69+
WHERE crrt_mode IS NOT NULL
6670
)
6771
-- get all charttimes documented
6872
, tm_stg AS
@@ -78,7 +82,6 @@ FROM `physionet-data.mimic_derived.crrt`
7882
SELECT
7983
stay_id, charttime
8084
FROM crrt_stg
81-
8285
)
8386
SELECT
8487
ie.subject_id
@@ -100,6 +103,33 @@ SELECT
100103
COALESCE(uo.aki_stage_uo,0),
101104
COALESCE(crrt.aki_stage_crrt,0)
102105
) AS aki_stage
106+
107+
-- We intend to combine together the scores from creatinine/UO by left joining
108+
-- from the above temporary table which has all possible charttime.
109+
-- This will guarantee we include all creatinine/UO measurements.
110+
111+
-- However, we have times where urine output is measured, but not creatinine.
112+
-- Thus we end up with NULLs for the creatinine column(s). Naively calculating
113+
-- the highest stage across the columns will often only consider one stage.
114+
-- For example, consider the following rows:
115+
-- stay_id=123, time=10:00, cr_low_7day=4.0, uo_rt_6hr=NULL will give stage 3
116+
-- stay_id=123, time=10:30, cr_low_7day=NULL, uo_rt_6hr=0.3 will give stage 1
117+
-- This results in the stage alternating from low/high across rows.
118+
119+
-- To overcome this, we create a new column which carries forward the highest
120+
-- KDIGO stage from the last 6 hours. In most cases, this smooths out any discontinuity.
121+
, MAX(
122+
GREATEST(
123+
COALESCE(cr.aki_stage_creat,0),
124+
COALESCE(uo.aki_stage_uo,0),
125+
COALESCE(crrt.aki_stage_crrt,0)
126+
)
127+
) OVER
128+
(
129+
PARTITION BY ie.subject_id
130+
ORDER BY DATETIME_DIFF(tm.charttime, ie.intime, SECOND)
131+
RANGE BETWEEN 21600 PRECEDING AND CURRENT ROW
132+
) AS aki_stage_smoothed
103133
FROM `physionet-data.mimiciv_icu.icustays` ie
104134
-- get all possible charttimes as listed in tm_stg
105135
LEFT JOIN tm_stg tm

mimic-iv/concepts/organfailure/kdigo_uo.sql

Lines changed: 81 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,69 @@
1-
with ur_stg as
1+
WITH uo_stg1 AS
22
(
3-
select io.stay_id, io.charttime
4-
-- we have joined each row to all rows preceding within 24 hours
5-
-- we can now sum these rows to get total UO over the last 24 hours
6-
-- we can use case statements to restrict it to only the last 6/12 hours
7-
-- therefore we have three sums:
8-
-- 1) over a 6 hour period
9-
-- 2) over a 12 hour period
10-
-- 3) over a 24 hour period
11-
-- note that we assume data charted at charttime corresponds to 1 hour of UO
12-
-- therefore we use '5' and '11' to restrict the period, rather than 6/12
13-
-- this assumption may overestimate UO rate when documentation is done less than hourly
3+
SELECT ie.stay_id, uo.charttime
4+
, DATETIME_DIFF(charttime, intime, SECOND) AS seconds_since_admit
5+
, COALESCE(
6+
DATETIME_DIFF(charttime, LAG(charttime) OVER (PARTITION BY ie.stay_id ORDER BY charttime), SECOND)/3600.0,
7+
1
8+
) AS hours_since_previous_row
9+
, urineoutput
10+
FROM `physionet-data.mimiciv_icu.icustays` ie
11+
INNER JOIN `physionet-data.mimiciv_derived.urine_output` uo
12+
ON ie.stay_id = uo.stay_id
13+
)
14+
, uo_stg2 as
15+
(
16+
select stay_id, charttime
17+
, hours_since_previous_row
18+
, urineoutput
19+
-- Use the RANGE partition to limit the summation to the last X hours.
20+
-- RANGE operates using numeric, so we convert the charttime into seconds
21+
-- since admission, and then filter to X seconds prior to the current row.
22+
-- where X can be 21600 (6 hours), 43200 (12 hours), or 86400 (24 hours).
23+
, SUM(urineoutput) OVER
24+
(
25+
PARTITION BY stay_id
26+
ORDER BY seconds_since_admit
27+
RANGE BETWEEN 21600 PRECEDING AND CURRENT ROW
28+
) AS urineoutput_6hr
29+
30+
, SUM(urineoutput) OVER
31+
(
32+
PARTITION BY stay_id
33+
ORDER BY seconds_since_admit
34+
RANGE BETWEEN 43200 PRECEDING AND CURRENT ROW
35+
) AS urineoutput_12hr
36+
37+
, SUM(urineoutput) OVER
38+
(
39+
PARTITION BY stay_id
40+
ORDER BY seconds_since_admit
41+
RANGE BETWEEN 86400 PRECEDING AND CURRENT ROW
42+
) AS urineoutput_24hr
1443

15-
-- 6 hours
16-
, sum(case when iosum.charttime >= DATETIME_SUB(io.charttime, interval '5' hour)
17-
then iosum.urineoutput
18-
else null end) as UrineOutput_6hr
19-
-- 12 hours
20-
, sum(case when iosum.charttime >= DATETIME_SUB(io.charttime, interval '11' hour)
21-
then iosum.urineoutput
22-
else null end) as UrineOutput_12hr
23-
-- 24 hours
24-
, sum(iosum.urineoutput) as UrineOutput_24hr
25-
26-
-- calculate the number of hours over which we've tabulated UO
27-
, ROUND(CAST(
28-
DATETIME_DIFF(io.charttime,
29-
-- below MIN() gets the earliest time that was used in the summation
30-
MIN(case when iosum.charttime >= DATETIME_SUB(io.charttime, interval '5' hour)
31-
then iosum.charttime
32-
else null end),
33-
SECOND) AS NUMERIC)/3600.0, 4)
34-
AS uo_tm_6hr
35-
-- repeat extraction for 12 hours and 24 hours
36-
, ROUND(CAST(
37-
DATETIME_DIFF(io.charttime,
38-
MIN(case when iosum.charttime >= DATETIME_SUB(io.charttime, interval '11' hour)
39-
then iosum.charttime
40-
else null end),
41-
SECOND) AS NUMERIC)/3600.0, 4)
42-
AS uo_tm_12hr
43-
, ROUND(CAST(
44-
DATETIME_DIFF(io.charttime, MIN(iosum.charttime), SECOND)
45-
AS NUMERIC)/3600.0, 4) AS uo_tm_24hr
46-
from `physionet-data.mimiciv_derived.urine_output` io
47-
-- this join gives all UO measurements over the 24 hours preceding this row
48-
left join `physionet-data.mimiciv_derived.urine_output` iosum
49-
on io.stay_id = iosum.stay_id
50-
and iosum.charttime <= io.charttime
51-
and iosum.charttime >= DATETIME_SUB(io.charttime, interval '23' hour)
52-
group by io.stay_id, io.charttime
44+
-- repeat the summations using the hours_since_previous_row column
45+
-- this gives us the amount of time the UO was calculated over
46+
, SUM(hours_since_previous_row) OVER
47+
(
48+
PARTITION BY stay_id
49+
ORDER BY seconds_since_admit
50+
RANGE BETWEEN 21600 PRECEDING AND CURRENT ROW
51+
) AS uo_tm_6hr
52+
53+
, SUM(hours_since_previous_row) OVER
54+
(
55+
PARTITION BY stay_id
56+
ORDER BY seconds_since_admit
57+
RANGE BETWEEN 43200 PRECEDING AND CURRENT ROW
58+
) AS uo_tm_12hr
59+
60+
, SUM(hours_since_previous_row) OVER
61+
(
62+
PARTITION BY stay_id
63+
ORDER BY seconds_since_admit
64+
RANGE BETWEEN 86400 PRECEDING AND CURRENT ROW
65+
) AS uo_tm_24hr
66+
from uo_stg1
5367
)
5468
select
5569
ur.stay_id
@@ -58,15 +72,27 @@ select
5872
, ur.urineoutput_6hr
5973
, ur.urineoutput_12hr
6074
, ur.urineoutput_24hr
61-
-- calculate rates - adding 1 hour as we assume data charted at 10:00 corresponds to previous hour
62-
, ROUND(CAST((ur.UrineOutput_6hr/wd.weight/(uo_tm_6hr+1)) AS NUMERIC), 4) AS uo_rt_6hr
63-
, ROUND(CAST((ur.UrineOutput_12hr/wd.weight/(uo_tm_12hr+1)) AS NUMERIC), 4) AS uo_rt_12hr
64-
, ROUND(CAST((ur.UrineOutput_24hr/wd.weight/(uo_tm_24hr+1)) AS NUMERIC), 4) AS uo_rt_24hr
75+
76+
-- calculate rates while requiring UO documentation over at least N hours
77+
-- as specified in KDIGO guidelines 2012 pg19
78+
, CASE
79+
WHEN uo_tm_6hr >= 6 AND uo_tm_6hr < 12
80+
THEN ROUND(CAST((ur.urineoutput_6hr/wd.weight/uo_tm_6hr) AS NUMERIC), 4)
81+
ELSE NULL END AS uo_rt_6hr
82+
, CASE
83+
WHEN uo_tm_12hr >= 12
84+
THEN ROUND(CAST((ur.urineoutput_12hr/wd.weight/uo_tm_12hr) AS NUMERIC), 4)
85+
ELSE NULL END AS uo_rt_12hr
86+
, CASE
87+
WHEN uo_tm_24hr >= 24
88+
THEN ROUND(CAST((ur.urineoutput_24hr/wd.weight/uo_tm_24hr) AS NUMERIC), 4)
89+
ELSE NULL END AS uo_rt_24hr
90+
6591
-- number of hours between current UO time and earliest charted UO within the X hour window
6692
, uo_tm_6hr
6793
, uo_tm_12hr
6894
, uo_tm_24hr
69-
from ur_stg ur
95+
from uo_stg2 ur
7096
left join `physionet-data.mimiciv_derived.weight_durations` wd
7197
on ur.stay_id = wd.stay_id
7298
and ur.charttime >= wd.starttime

0 commit comments

Comments
 (0)