การเลือกแบบจำลองเพื่อการตัดสินใจ: ให้เส้นทางทางคลินิกกำหนดโครงสร้าง

On this page
Read the English version
บทคัดย่อ
แพทย์ห้องฉุกเฉินพบผู้ใหญ่ที่เป็นเซลลูไลติสที่ขา และต้องเลือกระหว่างยาปฏิชีวนะชนิดกินที่บ้าน กับการรับไว้ในโรงพยาบาลเพื่อให้ยาทางหลอดเลือดดำ ก่อนเปิดโปรแกรมใด คำถามเป็นตัวกำหนดแบบจำลอง คือผู้ป่วยกลุ่มไหน แผนการดูแลทั้งชุดแบบใด นับผลที่ตามมานานเท่าไร และนับต้นทุนของใคร ถ้าถามถึงการป่วยครั้งเดียวในสองสัปดาห์ ต้นไม้การตัดสินใจก็พอ สมมติว่ายากินได้ผลด้วยโอกาส 0.8 และให้วันที่ไม่มีอาการ 10 วัน ส่วนผู้ป่วยที่เหลือต้องรับไว้และได้ 2 วัน แผนนี้ได้เฉลี่ย 8.4 วัน แต่ถ้าถามถึงหนึ่งปีที่โรคกลับมาได้ทุกเดือน ต้นไม้จะเพิ่มเป็นสองเท่าทุกเดือนจนมี 4,096 ปลายกิ่ง ขณะที่สองภาวะที่ใช้ซ้ำได้ คือสบายดีกับกำลังติดเชื้อ ทำงานเดียวกันได้ แต่เมื่อความเสี่ยงขึ้นกับการป่วยครั้งก่อน ภาวะต้องจำอดีตนั้นไว้ หากละประวัติไป ประโยชน์ของการป้องกันหลังกลับเป็นซ้ำจะเหลือครึ่งเดียว จาก 7.5 เป็น 3.75 ครั้งที่ป้องกันได้ต่อเดือน จึงควรให้เส้นทางการดูแลเป็นผู้เลือกโครงสร้าง
ผู้ป่วยหนึ่งคน สองแผนการดูแล
ผู้ใหญ่คนหนึ่งมาที่ห้องฉุกเฉินของโรงพยาบาลชุมชนด้วยขาส่วนล่างที่แดง ร้อน และบวม คือเซลลูไลติส ซึ่งเป็นการติดเชื้อของผิวหนัง แพทย์เลือกได้ว่าจะให้ผู้ป่วยกลับบ้านพร้อมยาปฏิชีวนะชนิดกิน หรือรับไว้ในโรงพยาบาลเพื่อให้ยาทางหลอดเลือดดำ ค่าประมาณตัวอย่างของทีมคือยากินที่บ้านได้ผลในสัดส่วน 0.8 ของผู้ป่วยแบบนี้ ส่วนที่เหลือกลับมาและต้องรับไว้ ทีมนับวันที่ไม่มีอาการในสองสัปดาห์หลังมาโรงพยาบาล คือ 10 วันถ้ายาได้ผล และ 2 วันถ้าผู้ป่วยต้องถูกรับไว้ในที่สุด
ก่อนเลือกแบบจำลองใด ให้เขียนคำถามลงไปก่อน กลยุทธ์ (strategy) คือแผนการดูแลทั้งชุด ไม่ใช่แค่ชื่อยา ยากินที่บ้านจึงรวมการรับไว้ในโรงพยาบาลเมื่อยาไม่ได้ผลด้วย ช่วงเวลาที่นับผล (time horizon) คือระยะเวลาที่นับผลที่ตามมา ในที่นี้คือสองสัปดาห์ เพราะคำถามคือจะรักษาการป่วยครั้งนี้อย่างไร มุมมอง (perspective) บอกว่านับต้นทุนและผลลัพธ์ของใคร ในที่นี้คือมุมมองของโรงพยาบาลซึ่งนับเตียงและยา ส่วนมุมมองของสังคมที่กว้างกว่าจะนับวันที่ผู้ป่วยทำงานไม่ได้ด้วย (Briggs and colleagues)
จากนั้นร่างร่วมกับทีมแพทย์ว่าอะไรเกิดขึ้นได้บ้าง เหตุการณ์ (event) คือสิ่งที่เกิดขึ้นในชั่วขณะหนึ่ง เช่น ยากินไม่ได้ผล ภาวะ (state) คือสภาพที่ผู้ป่วยอยู่ต่อเนื่องช่วงหนึ่ง เช่น สบายดี หรือกำลังติดเชื้อ ถ้าปนสองอย่างนี้ อาจนับต้นทุนซ้ำได้ การรับไว้ในโรงพยาบาลเป็นเหตุการณ์ ส่วนวันที่นอนอยู่บนเตียงเป็นของภาวะ
ป่วยครั้งเดียว: ต้นไม้การตัดสินใจก็พอ
ในสองสัปดาห์ เส้นทางนี้มีจุดเริ่มและจุดจบชัดเจน ผู้ป่วยที่ได้ยากินแต่ละคนเดินไปตามกิ่งเดียวเท่านั้น คือยาได้ผล หรือยาไม่ได้ผลแล้วต้องรับไว้ สองกิ่งนี้เกิดพร้อมกันไม่ได้ และรวมกันครอบคลุมผู้ป่วยทุกคน โอกาสของสองกิ่งจึงรวมกันได้ 1 ค่าเฉลี่ยของแผนได้จากการถ่วงวันของแต่ละกิ่งด้วยโอกาสของกิ่งนั้น แล้วรวมกัน
ยากินที่บ้าน: ถ่วงแต่ละกิ่งแล้วรวมกัน
ตัวเลขสมมติของผู้ป่วยหนึ่งคนที่เริ่มยากินที่บ้าน นับในสองสัปดาห์
-
แจกแจงกิ่ง
\[ 1-0.8=0.2 \]
ยากินได้ผลด้วยโอกาส 0.8 และให้วันที่ไม่มีอาการ 10 วัน ผู้ป่วยถูกรับไว้ด้วยโอกาสที่เหลือ คือ 0.2 และได้ 2 วัน
-
ถ่วงแต่ละกิ่ง
\[ 0.8\times 10=8 \]
\[ 0.2\times 2=0.4 \]
กิ่งที่ยาได้ผลให้ 8 วัน ส่วนกิ่งที่ต้องรับไว้ให้ 0.4 วัน
-
รวมกิ่งที่ถ่วงแล้ว
\[ 8+0.4=8.4 \]
ผลของสองกิ่งรวมกันเป็นค่าเฉลี่ยของแผนต่อผู้ป่วยหนึ่งคน
ผลลัพธ์: ยากินที่บ้านให้วันที่ไม่มีอาการเฉลี่ย 8.4 วันต่อผู้ป่วยหนึ่งคนในสองสัปดาห์
ชื่อเรียก: ต้นไม้การตัดสินใจและการย้อนคำนวณ
ภาพแบบนี้เรียกว่าต้นไม้การตัดสินใจ (decision tree) มีสี่เหลี่ยมแทนการเลือก วงกลมแทนจุดที่โอกาสเป็นผู้กำหนด และจำนวนวันที่ปลายกิ่ง การคำนวณจากปลายกิ่งย้อนกลับมาที่สี่เหลี่ยมแบบขั้นตอนข้างบนเรียกว่าการย้อนคำนวณต้นไม้ (rolling back) ผลที่ได้ 8.4 วันคือค่าคาดหมาย (expected value) ของแผน หรือค่าเฉลี่ยต่อผู้ป่วยหนึ่งคน แผนรับไว้ในโรงพยาบาลก็ย้อนคำนวณแบบเดียวกันด้วยโอกาสและจำนวนวันของตัวเอง บทความนี้ติดตามเฉพาะแผนยากิน ส่วนการเทียบแผนทั้งชุดอยู่ในบทความตอนหลังของชุดนี้
# Illustrative symptom-free days for one leg cellulitis episode; synthetic numbers.
# Writes: nothing to disk; the results print in the console.
p_success <- 0.8
value_success <- 10
value_failure <- 2
p_failure <- 1 - p_success
weighted_success <- p_success * value_success
weighted_failure <- p_failure * value_failure
expected_days <- weighted_success + weighted_failure
cat("Success, failure probability:", p_success, p_failure, "\n")
cat("Weighted days, success and failure:", weighted_success, weighted_failure, "\n")
cat("Expected symptom-free days:", expected_days, "\n")
Success, failure probability: 0.8 0.2
Weighted days, success and failure: 8 0.4
Expected symptom-free days: 8.4
ต้องใช้ R ≥ 4.5.2 · tibble 3.3.1 · dplyr 1.2.1 · ggplot2 4.0.3 · ใช้ได้กับ R 4.6.1 · ดาวน์โหลด choosing-a-decision-analytic-model.R
สคริปต์ฉบับเต็ม
# Choosing a Decision-Analytic Model: Let the Clinical Pathway Decide
# Follow one leg cellulitis case from a two-week tree to monthly states with memory.
# ติดตามผู้ป่วยเซลลูไลติสที่ขาจากต้นไม้สองสัปดาห์ ไปสู่ภาวะรายเดือนที่จำอดีตได้
# Requires: R >= 4.5.2
# Tested: works in R 4.6.1
# tibble 3.3.1 (stable)
# dplyr 1.2.1 (stable)
# ggplot2 4.0.3 (stable)
# install.packages(c("tibble", "dplyr", "ggplot2"))
# update.packages(oldPkgs = c("tibble", "dplyr", "ggplot2"))
# remotes::install_version("tibble", "3.3.1")
# remotes::install_version("dplyr", "1.2.1")
# remotes::install_version("ggplot2", "4.0.3")
library(tibble) # Write the model inputs as explicit tables.
library(dplyr) # Calculate the weighted and split quantities.
library(ggplot2) # Display the tree size against the reused states without saving files.
stopifnot(getRversion() >= "4.5.2")
#%%@note 1. Define the illustrative inputs
# Every input is synthetic and written out once, in the order the article uses it.
# ค่าตั้งต้นทั้งหมดเป็นข้อมูลสมมติ เขียนไว้ครั้งเดียวตามลำดับที่บทความใช้
p_success <- 0.8
value_success <- 10
value_failure <- 2
periods <- c(1, 2, 3, 10, 12)
states <- c("well", "active cellulitis")
cohort <- 1000
risk_month <- 0.03
well_first <- 750
well_again <- 250
risk_first <- 0.02
risk_again <- 0.06
prevent_cut <- 0.5
recovered <- 1000
risk_month1 <- 0.10
risk_month2 <- 0.05
#%%@note 2. Roll back the two-week tree
# Weight each branch's symptom-free days by its chance, then add the two products.
# ถ่วงวันที่ไม่มีอาการของแต่ละกิ่งด้วยโอกาสของกิ่งนั้น แล้วรวมสองผลคูณ
branches <- tibble::tibble(
branch = c("tablets work", "admitted"), probability = c(p_success, 1 - p_success),
days = c(value_success, value_failure)
) |>
dplyr::mutate(weighted_days = probability * days)
stopifnot(abs(sum(branches$probability) - 1) < 1e-9)
p_failure <- 1 - p_success
weighted_success <- branches$weighted_days[1]
weighted_failure <- branches$weighted_days[2]
expected_days <- weighted_success + weighted_failure
#%%@note 3. Count tree endpoints and take one monthly state step
# A tree doubles its endpoints every month; a state model reuses the same two states.
# ต้นไม้เพิ่มปลายกิ่งเป็นสองเท่าทุกเดือน ส่วนแบบจำลองภาวะใช้สองภาวะเดิมซ้ำ
endpoints <- 2^periods
comma_format <- function(value) formatC(value, format = "f", digits = 0, big.mark = ",")
month_step <- cohort * c(1, risk_month, 1 - risk_month)
growth <- tibble::tibble(month = periods, tree_endpoints = endpoints,
states_reused = length(states))
#%%@note 4. Split the well state by history and by time since recovery
# History states keep 0.02 and 0.06 apart; tunnel states keep the first two months apart.
# ภาวะที่เก็บประวัติแยกความเสี่ยง 0.02 กับ 0.06 ส่วนภาวะอุโมงค์แยกสองเดือนแรกหลังหาย
groups <- tibble::tibble(group = c("no recurrence", "after a recurrence"),
people = c(well_first, well_again), risk = c(risk_first, risk_again)) |>
dplyr::mutate(new_episodes = people * risk)
new_first <- groups$new_episodes[1]
new_again <- groups$new_episodes[2]
average_risk <- (new_first + new_again) / (well_first + well_again)
tunnel_free <- recovered * (1 - risk_month1) * (1 - risk_month2)
flat_free <- recovered * (1 - risk_month)^2
flat_returns <- recovered - flat_free
tunnel_returns <- recovered - tunnel_free
one_decimal <- function(value) formatC(value, format = "f", digits = 1)
#%%@note 5. Display the model
# Plot tree endpoints against the reused states on a log scale; no graphics file is saved.
# แสดงจำนวนปลายกิ่งเทียบกับภาวะที่ใช้ซ้ำบนสเกลลอการิทึม โดยไม่บันทึกไฟล์ภาพ
print(ggplot2::ggplot(growth, ggplot2::aes(x = month)) +
ggplot2::geom_col(ggplot2::aes(y = tree_endpoints)) +
ggplot2::geom_point(ggplot2::aes(y = states_reused)) +
ggplot2::scale_y_log10() + ggplot2::labs(x = "Monthly periods", y = "Count (log scale)"))
#%%@note 6. Numbers the article quotes
# Print exactly the short boxes in their reading order.
# พิมพ์ผลลัพธ์ตรงกับกล่องตัวอย่างตามลำดับในบทความ
cat("Success, failure probability:", p_success, p_failure, "\n")
cat("Weighted days, success and failure:", weighted_success, weighted_failure, "\n")
cat("Expected symptom-free days:", expected_days, "\n")
cat("Monthly periods:", periods, "\n")
cat("Tree endpoints:", comma_format(endpoints), "\n")
cat("States reused every month:", length(states), "\n")
cat("Well now, new episodes, still well:", comma_format(month_step), "\n")
cat("New episodes next month, no recurrence and after one:", new_first, new_again, "\n")
cat("Average monthly risk in one well state:", average_risk, "\n")
cat("Episodes avoided a month, history states:", new_again * prevent_cut, "\n")
cat("Episodes avoided a month, one well state:", well_again * average_risk * prevent_cut, "\n")
cat("Free of a new episode after month 1, tunnel:", recovered * (1 - risk_month1), "\n")
cat("Free after month 2, tunnel and flat 0.03:", tunnel_free, one_decimal(flat_free), "\n")
cat("Returns within two months, tunnel and flat:", tunnel_returns, one_decimal(flat_returns), "\n")
เมื่อโรคกลับเป็นซ้ำ ให้ใช้ภาวะ
ทีนี้เปลี่ยนคำถาม ผู้ป่วยจำนวนมากกลับมาเป็นเซลลูไลติสซ้ำ และโรงพยาบาลถามว่าผู้ป่วยที่หายแล้ว ควรกินยาปฏิชีวนะป้องกันนานหนึ่งปีหรือไม่ หนึ่งปีที่การติดเชื้อกลับมาได้ทุกเดือนใส่ในต้นไม้สั้น ๆ ไม่ได้ ความเสี่ยงรายเดือนจากนี้ไปเป็นตัวเลขสมมติเพื่อการสอน แบบจำลองจริงต้องนำมาจากการศึกษา
สมมติว่าการป่วยครั้งใหม่เริ่มได้ในทุกเดือน ต้นไม้วนกลับไปกิ่งก่อนหน้าไม่ได้ จึงต้องแยกกิ่งทุกเดือนเป็นป่วยครั้งใหม่หรือไม่ป่วย ปลายกิ่งจึงเพิ่มเป็นสองเท่า คือ 2 หลังหนึ่งเดือน 4 หลังสองเดือน 8 หลังสามเดือน และ 4,096 หลัง 12 เดือน ปลายกิ่งแต่ละปลายยังต้องมีจำนวนวันและต้นทุนของตัวเอง ซึ่งไม่มีทีมใดกรอกด้วยมือได้
แบบจำลองภาวะเลี่ยงการขยายตัวนี้ได้ แบบจำลองนี้แบ่งผู้ป่วยเป็นภาวะไม่กี่ภาวะ ผู้ป่วยแต่ละคนอยู่ในภาวะเดียวในแต่ละเวลา ในที่นี้คือสบายดีกับกำลังติดเชื้อ แล้วย้ายผู้ป่วยระหว่างภาวะทุกหนึ่งรอบ (cycle) ซึ่งเป็นช่วงเวลาคงที่ ในที่นี้คือหนึ่งเดือน ในผู้ป่วย 1,000 คนที่สบายดีเดือนนี้ ด้วยความเสี่ยงต่อเดือน 0.03 จะมี 30 คนเริ่มป่วยครั้งใหม่ในเดือนหน้า และ 970 คนยังสบายดี สองภาวะเดิมถูกใช้ซ้ำทุกเดือน ไม่ว่าช่วงเวลาที่นับผลจะยาวเท่าไร
การติดตามทั้งกลุ่มแบบนี้ในรูปสัดส่วนที่กระจายอยู่ตามภาวะต่าง ๆ เรียกว่าแบบจำลองการเปลี่ยนภาวะของกลุ่มประชากร (cohort state-transition model) แบบจำลองนี้ต้องการความเสี่ยงต่อเดือนที่จะป่วยครั้งใหม่และโอกาสหายต่อเดือน ไม่ต้องมีค่าแยกสำหรับเส้นทางทั้ง 4,096 เส้น
# Illustrative tree size and one monthly state step when cellulitis can return; synthetic numbers.
# Writes: nothing to disk; the results print in the console.
periods <- c(1, 2, 3, 10, 12)
states <- c("well", "active cellulitis")
cohort <- 1000
risk_month <- 0.03
endpoints <- 2^periods
month_step <- cohort * c(1, risk_month, 1 - risk_month)
comma_format <- function(value) formatC(value, format = "f", digits = 0, big.mark = ",")
cat("Monthly periods:", periods, "\n")
cat("Tree endpoints:", comma_format(endpoints), "\n")
cat("States reused every month:", length(states), "\n")
cat("Well now, new episodes, still well:", comma_format(month_step), "\n")
Monthly periods: 1 2 3 10 12
Tree endpoints: 2 4 8 1,024 4,096
States reused every month: 2
Well now, new episodes, still well: 1,000 30 970
ต้องใช้ R ≥ 4.5.2 · tibble 3.3.1 · dplyr 1.2.1 · ggplot2 4.0.3 · ใช้ได้กับ R 4.6.1 · ดาวน์โหลด choosing-a-decision-analytic-model.R
สคริปต์ฉบับเต็ม
# Choosing a Decision-Analytic Model: Let the Clinical Pathway Decide
# Follow one leg cellulitis case from a two-week tree to monthly states with memory.
# ติดตามผู้ป่วยเซลลูไลติสที่ขาจากต้นไม้สองสัปดาห์ ไปสู่ภาวะรายเดือนที่จำอดีตได้
# Requires: R >= 4.5.2
# Tested: works in R 4.6.1
# tibble 3.3.1 (stable)
# dplyr 1.2.1 (stable)
# ggplot2 4.0.3 (stable)
# install.packages(c("tibble", "dplyr", "ggplot2"))
# update.packages(oldPkgs = c("tibble", "dplyr", "ggplot2"))
# remotes::install_version("tibble", "3.3.1")
# remotes::install_version("dplyr", "1.2.1")
# remotes::install_version("ggplot2", "4.0.3")
library(tibble) # Write the model inputs as explicit tables.
library(dplyr) # Calculate the weighted and split quantities.
library(ggplot2) # Display the tree size against the reused states without saving files.
stopifnot(getRversion() >= "4.5.2")
#%%@note 1. Define the illustrative inputs
# Every input is synthetic and written out once, in the order the article uses it.
# ค่าตั้งต้นทั้งหมดเป็นข้อมูลสมมติ เขียนไว้ครั้งเดียวตามลำดับที่บทความใช้
p_success <- 0.8
value_success <- 10
value_failure <- 2
periods <- c(1, 2, 3, 10, 12)
states <- c("well", "active cellulitis")
cohort <- 1000
risk_month <- 0.03
well_first <- 750
well_again <- 250
risk_first <- 0.02
risk_again <- 0.06
prevent_cut <- 0.5
recovered <- 1000
risk_month1 <- 0.10
risk_month2 <- 0.05
#%%@note 2. Roll back the two-week tree
# Weight each branch's symptom-free days by its chance, then add the two products.
# ถ่วงวันที่ไม่มีอาการของแต่ละกิ่งด้วยโอกาสของกิ่งนั้น แล้วรวมสองผลคูณ
branches <- tibble::tibble(
branch = c("tablets work", "admitted"), probability = c(p_success, 1 - p_success),
days = c(value_success, value_failure)
) |>
dplyr::mutate(weighted_days = probability * days)
stopifnot(abs(sum(branches$probability) - 1) < 1e-9)
p_failure <- 1 - p_success
weighted_success <- branches$weighted_days[1]
weighted_failure <- branches$weighted_days[2]
expected_days <- weighted_success + weighted_failure
#%%@note 3. Count tree endpoints and take one monthly state step
# A tree doubles its endpoints every month; a state model reuses the same two states.
# ต้นไม้เพิ่มปลายกิ่งเป็นสองเท่าทุกเดือน ส่วนแบบจำลองภาวะใช้สองภาวะเดิมซ้ำ
endpoints <- 2^periods
comma_format <- function(value) formatC(value, format = "f", digits = 0, big.mark = ",")
month_step <- cohort * c(1, risk_month, 1 - risk_month)
growth <- tibble::tibble(month = periods, tree_endpoints = endpoints,
states_reused = length(states))
#%%@note 4. Split the well state by history and by time since recovery
# History states keep 0.02 and 0.06 apart; tunnel states keep the first two months apart.
# ภาวะที่เก็บประวัติแยกความเสี่ยง 0.02 กับ 0.06 ส่วนภาวะอุโมงค์แยกสองเดือนแรกหลังหาย
groups <- tibble::tibble(group = c("no recurrence", "after a recurrence"),
people = c(well_first, well_again), risk = c(risk_first, risk_again)) |>
dplyr::mutate(new_episodes = people * risk)
new_first <- groups$new_episodes[1]
new_again <- groups$new_episodes[2]
average_risk <- (new_first + new_again) / (well_first + well_again)
tunnel_free <- recovered * (1 - risk_month1) * (1 - risk_month2)
flat_free <- recovered * (1 - risk_month)^2
flat_returns <- recovered - flat_free
tunnel_returns <- recovered - tunnel_free
one_decimal <- function(value) formatC(value, format = "f", digits = 1)
#%%@note 5. Display the model
# Plot tree endpoints against the reused states on a log scale; no graphics file is saved.
# แสดงจำนวนปลายกิ่งเทียบกับภาวะที่ใช้ซ้ำบนสเกลลอการิทึม โดยไม่บันทึกไฟล์ภาพ
print(ggplot2::ggplot(growth, ggplot2::aes(x = month)) +
ggplot2::geom_col(ggplot2::aes(y = tree_endpoints)) +
ggplot2::geom_point(ggplot2::aes(y = states_reused)) +
ggplot2::scale_y_log10() + ggplot2::labs(x = "Monthly periods", y = "Count (log scale)"))
#%%@note 6. Numbers the article quotes
# Print exactly the short boxes in their reading order.
# พิมพ์ผลลัพธ์ตรงกับกล่องตัวอย่างตามลำดับในบทความ
cat("Success, failure probability:", p_success, p_failure, "\n")
cat("Weighted days, success and failure:", weighted_success, weighted_failure, "\n")
cat("Expected symptom-free days:", expected_days, "\n")
cat("Monthly periods:", periods, "\n")
cat("Tree endpoints:", comma_format(endpoints), "\n")
cat("States reused every month:", length(states), "\n")
cat("Well now, new episodes, still well:", comma_format(month_step), "\n")
cat("New episodes next month, no recurrence and after one:", new_first, new_again, "\n")
cat("Average monthly risk in one well state:", average_risk, "\n")
cat("Episodes avoided a month, history states:", new_again * prevent_cut, "\n")
cat("Episodes avoided a month, one well state:", well_again * average_risk * prevent_cut, "\n")
cat("Free of a new episode after month 1, tunnel:", recovered * (1 - risk_month1), "\n")
cat("Free after month 2, tunnel and flat 0.03:", tunnel_free, one_decimal(flat_free), "\n")
cat("Returns within two months, tunnel and flat:", tunnel_returns, one_decimal(flat_returns), "\n")
เมื่อความเสี่ยงจำอดีต ให้แยกภาวะ
แบบจำลองสองภาวะแบบพื้นฐานไม่มีความจำ แบบจำลองนี้สมมติว่าโอกาสย้ายภาวะครั้งถัดไปขึ้นกับภาวะที่ผู้ป่วยอยู่ตอนนี้เท่านั้น ไม่ขึ้นกับว่ามาถึงภาวะนี้อย่างไร ข้อสมมตินี้เรียกในบทความนี้ว่ากฎไม่จำอดีต (Siebert and colleagues) นี่เป็นทางเลือกของผู้สร้างแบบจำลอง ไม่ใช่ข้อเท็จจริงของเซลลูไลติส การป่วยแต่ละครั้งอาจทำลายการระบายน้ำเหลืองของขา ผู้ป่วยที่เคยกลับเป็นซ้ำมาแล้วจึงมีโอกาสเป็นอีกมากกว่า
สมมติว่ามีผู้ป่วยที่สบายดี 1,000 คน ในจำนวนนี้ 750 คนไม่เคยกลับเป็นซ้ำ มีความเสี่ยงต่อเดือน 0.02 และ 250 คนเคยกลับเป็นซ้ำแล้ว มีความเสี่ยง 0.06 เดือนหน้าจะเริ่มป่วยครั้งใหม่ 750 × 0.02 = 15 คน และ 250 × 0.06 = 15 คน รวม 30 คน คิดเป็นความเสี่ยงเฉลี่ย 0.03 ภาวะสบายดีภาวะเดียวที่ 0.03 จึงคำนวณเดือนนี้ได้ถูก
ปัญหาเริ่มเมื่อการตัดสินใจขึ้นกับประวัตินั้น สมมติว่ายาปฏิชีวนะป้องกันลดความเสี่ยงลงครึ่งหนึ่ง และให้เฉพาะผู้ป่วย 250 คนที่เคยกลับเป็นซ้ำ ด้วยความเสี่ยงของกลุ่มนี้เอง 0.06 จะมีผู้ป่วยใหม่ 15 คนต่อเดือน การลดความเสี่ยงครึ่งหนึ่งจึงป้องกันได้ 7.5 ครั้ง แต่ภาวะสบายดีภาวะเดียวให้ได้แค่ค่าเฉลี่ย กลุ่มนี้จึงมีผู้ป่วยใหม่ 250 × 0.03 = 7.5 ครั้งต่อเดือน เมื่อลดครึ่งหนึ่งจึงดูเหมือนป้องกันได้เพียง 3.75 ครั้ง ซึ่งเป็นครึ่งเดียวของประโยชน์จริง
การแยกภาวะตามสิ่งที่เคยเกิดมาก่อนเรียกว่าการใช้ภาวะที่เก็บประวัติ (history states) ในที่นี้คือสบายดีโดยไม่เคยกลับเป็นซ้ำ และสบายดีหลังเคยกลับเป็นซ้ำ แต่ละภาวะมีความเสี่ยงของตัวเอง ตอนนี้แบบจำลองบอกได้ว่าใครได้รับการป้องกัน และต้องการหลักฐานความเสี่ยงแยกตามการป่วยครั้งก่อน คือ 0.02 และ 0.06 ไม่ใช่แค่ค่าเฉลี่ย
# Illustrative monthly risk of a new episode split by past recurrence; synthetic numbers.
# Writes: nothing to disk; the results print in the console.
well_first <- 750
well_again <- 250
risk_first <- 0.02
risk_again <- 0.06
prevent_cut <- 0.5
new_first <- well_first * risk_first
new_again <- well_again * risk_again
average_risk <- (new_first + new_again) / (well_first + well_again)
cat("New episodes next month, no recurrence and after one:", new_first, new_again, "\n")
cat("Average monthly risk in one well state:", average_risk, "\n")
cat("Episodes avoided a month, history states:", new_again * prevent_cut, "\n")
cat("Episodes avoided a month, one well state:", well_again * average_risk * prevent_cut, "\n")
New episodes next month, no recurrence and after one: 15 15
Average monthly risk in one well state: 0.03
Episodes avoided a month, history states: 7.5
Episodes avoided a month, one well state: 3.75
ต้องใช้ R ≥ 4.5.2 · tibble 3.3.1 · dplyr 1.2.1 · ggplot2 4.0.3 · ใช้ได้กับ R 4.6.1 · ดาวน์โหลด choosing-a-decision-analytic-model.R
สคริปต์ฉบับเต็ม
# Choosing a Decision-Analytic Model: Let the Clinical Pathway Decide
# Follow one leg cellulitis case from a two-week tree to monthly states with memory.
# ติดตามผู้ป่วยเซลลูไลติสที่ขาจากต้นไม้สองสัปดาห์ ไปสู่ภาวะรายเดือนที่จำอดีตได้
# Requires: R >= 4.5.2
# Tested: works in R 4.6.1
# tibble 3.3.1 (stable)
# dplyr 1.2.1 (stable)
# ggplot2 4.0.3 (stable)
# install.packages(c("tibble", "dplyr", "ggplot2"))
# update.packages(oldPkgs = c("tibble", "dplyr", "ggplot2"))
# remotes::install_version("tibble", "3.3.1")
# remotes::install_version("dplyr", "1.2.1")
# remotes::install_version("ggplot2", "4.0.3")
library(tibble) # Write the model inputs as explicit tables.
library(dplyr) # Calculate the weighted and split quantities.
library(ggplot2) # Display the tree size against the reused states without saving files.
stopifnot(getRversion() >= "4.5.2")
#%%@note 1. Define the illustrative inputs
# Every input is synthetic and written out once, in the order the article uses it.
# ค่าตั้งต้นทั้งหมดเป็นข้อมูลสมมติ เขียนไว้ครั้งเดียวตามลำดับที่บทความใช้
p_success <- 0.8
value_success <- 10
value_failure <- 2
periods <- c(1, 2, 3, 10, 12)
states <- c("well", "active cellulitis")
cohort <- 1000
risk_month <- 0.03
well_first <- 750
well_again <- 250
risk_first <- 0.02
risk_again <- 0.06
prevent_cut <- 0.5
recovered <- 1000
risk_month1 <- 0.10
risk_month2 <- 0.05
#%%@note 2. Roll back the two-week tree
# Weight each branch's symptom-free days by its chance, then add the two products.
# ถ่วงวันที่ไม่มีอาการของแต่ละกิ่งด้วยโอกาสของกิ่งนั้น แล้วรวมสองผลคูณ
branches <- tibble::tibble(
branch = c("tablets work", "admitted"), probability = c(p_success, 1 - p_success),
days = c(value_success, value_failure)
) |>
dplyr::mutate(weighted_days = probability * days)
stopifnot(abs(sum(branches$probability) - 1) < 1e-9)
p_failure <- 1 - p_success
weighted_success <- branches$weighted_days[1]
weighted_failure <- branches$weighted_days[2]
expected_days <- weighted_success + weighted_failure
#%%@note 3. Count tree endpoints and take one monthly state step
# A tree doubles its endpoints every month; a state model reuses the same two states.
# ต้นไม้เพิ่มปลายกิ่งเป็นสองเท่าทุกเดือน ส่วนแบบจำลองภาวะใช้สองภาวะเดิมซ้ำ
endpoints <- 2^periods
comma_format <- function(value) formatC(value, format = "f", digits = 0, big.mark = ",")
month_step <- cohort * c(1, risk_month, 1 - risk_month)
growth <- tibble::tibble(month = periods, tree_endpoints = endpoints,
states_reused = length(states))
#%%@note 4. Split the well state by history and by time since recovery
# History states keep 0.02 and 0.06 apart; tunnel states keep the first two months apart.
# ภาวะที่เก็บประวัติแยกความเสี่ยง 0.02 กับ 0.06 ส่วนภาวะอุโมงค์แยกสองเดือนแรกหลังหาย
groups <- tibble::tibble(group = c("no recurrence", "after a recurrence"),
people = c(well_first, well_again), risk = c(risk_first, risk_again)) |>
dplyr::mutate(new_episodes = people * risk)
new_first <- groups$new_episodes[1]
new_again <- groups$new_episodes[2]
average_risk <- (new_first + new_again) / (well_first + well_again)
tunnel_free <- recovered * (1 - risk_month1) * (1 - risk_month2)
flat_free <- recovered * (1 - risk_month)^2
flat_returns <- recovered - flat_free
tunnel_returns <- recovered - tunnel_free
one_decimal <- function(value) formatC(value, format = "f", digits = 1)
#%%@note 5. Display the model
# Plot tree endpoints against the reused states on a log scale; no graphics file is saved.
# แสดงจำนวนปลายกิ่งเทียบกับภาวะที่ใช้ซ้ำบนสเกลลอการิทึม โดยไม่บันทึกไฟล์ภาพ
print(ggplot2::ggplot(growth, ggplot2::aes(x = month)) +
ggplot2::geom_col(ggplot2::aes(y = tree_endpoints)) +
ggplot2::geom_point(ggplot2::aes(y = states_reused)) +
ggplot2::scale_y_log10() + ggplot2::labs(x = "Monthly periods", y = "Count (log scale)"))
#%%@note 6. Numbers the article quotes
# Print exactly the short boxes in their reading order.
# พิมพ์ผลลัพธ์ตรงกับกล่องตัวอย่างตามลำดับในบทความ
cat("Success, failure probability:", p_success, p_failure, "\n")
cat("Weighted days, success and failure:", weighted_success, weighted_failure, "\n")
cat("Expected symptom-free days:", expected_days, "\n")
cat("Monthly periods:", periods, "\n")
cat("Tree endpoints:", comma_format(endpoints), "\n")
cat("States reused every month:", length(states), "\n")
cat("Well now, new episodes, still well:", comma_format(month_step), "\n")
cat("New episodes next month, no recurrence and after one:", new_first, new_again, "\n")
cat("Average monthly risk in one well state:", average_risk, "\n")
cat("Episodes avoided a month, history states:", new_again * prevent_cut, "\n")
cat("Episodes avoided a month, one well state:", well_again * average_risk * prevent_cut, "\n")
cat("Free of a new episode after month 1, tunnel:", recovered * (1 - risk_month1), "\n")
cat("Free after month 2, tunnel and flat 0.03:", tunnel_free, one_decimal(flat_free), "\n")
cat("Returns within two months, tunnel and flat:", tunnel_returns, one_decimal(flat_returns), "\n")
ชื่อที่ใช้กันทั่วไปของกฎไม่จำอดีต: สมมติฐานมาร์คอฟ (Markov assumption)
ชื่อในหัวข้อนี้คือชื่อของกฎไม่จำอดีตที่อธิบายข้างบน ภาวะที่เก็บประวัติไม่ได้ละเมิดกฎนี้ แต่ย้ายความจำเข้าไปไว้ในตัวภาวะเอง การย้ายครั้งถัดไปจึงยังขึ้นกับภาวะที่ผู้ป่วยอยู่ตอนนี้เท่านั้น บทความตอนหลังของชุดนี้สร้างแบบจำลองแบบนี้ทีละรอบ
ความจำเรื่องเวลา: ภาวะอุโมงค์
ความจำเรื่องเวลาทำงานแบบเดียวกัน หลังการป่วยหายไป ความเสี่ยงที่จะป่วยอีกสูงที่สุดในช่วงแรก สมมติว่าเป็น 0.10 ในเดือนแรก 0.05 ในเดือนที่สอง แล้วคงที่ที่ 0.03 ต่อเดือนตั้งแต่เดือนที่ 3 ภาวะอุโมงค์ (tunnel states) คือชุดภาวะสบายดีชั่วคราวที่เรียงต่อกันตายตัว หนึ่งภาวะต่อหนึ่งเดือนหลังหาย และแต่ละภาวะมีความเสี่ยงของตัวเอง ผู้ป่วยผ่านภาวะเหล่านี้ตามลำดับ แล้วจึงเข้าสู่ภาวะสบายดีตามปกติ
ในผู้ป่วย 1,000 คนที่เพิ่งหาย 1,000 × (1 − 0.10) = 900 คนยังไม่ป่วยครั้งใหม่หลังเดือนที่ 1 และ 900 × (1 − 0.05) = 855 คนหลังเดือนที่ 2 จึงมี 145 คนกลับมาป่วยภายในสองเดือน ภาวะสบายดีภาวะเดียวที่ 0.03 ทำนายว่า 1,000 × (1 − 0.03) × (1 − 0.03) = 940.9 คนยังไม่ป่วย กลับมาป่วยเพียง 59.1 คน จึงพลาดการกลับมาป่วยช่วงแรกไปมากกว่าครึ่ง
เมื่อความจำที่ต้องใช้ละเอียดเกินกว่าจะใส่ในภาวะได้ เช่น ต้องรู้ทั้งจำนวนครั้งที่เคยป่วยและจำนวนเดือนนับจากครั้งล่าสุด ให้ติดตามผู้ป่วยทีละคนแทน วิธีนี้เรียกว่าการจำลองรายบุคคล (individual simulation) ซึ่งใช้ความเสี่ยงชุดเดียวกัน แต่บันทึกตามประวัติของผู้ป่วยแต่ละคน
# Illustrative risk of a new episode in the months after recovery; synthetic numbers.
# Writes: nothing to disk; the results print in the console.
recovered <- 1000
risk_month1 <- 0.10
risk_month2 <- 0.05
risk_month <- 0.03
tunnel_free <- recovered * (1 - risk_month1) * (1 - risk_month2)
flat_free <- recovered * (1 - risk_month)^2
flat_returns <- recovered - flat_free
tunnel_returns <- recovered - tunnel_free
one_decimal <- function(value) formatC(value, format = "f", digits = 1)
cat("Free of a new episode after month 1, tunnel:", recovered * (1 - risk_month1), "\n")
cat("Free after month 2, tunnel and flat 0.03:", tunnel_free, one_decimal(flat_free), "\n")
cat("Returns within two months, tunnel and flat:", tunnel_returns, one_decimal(flat_returns), "\n")
Free of a new episode after month 1, tunnel: 900
Free after month 2, tunnel and flat 0.03: 855 940.9
Returns within two months, tunnel and flat: 145 59.1
ต้องใช้ R ≥ 4.5.2 · tibble 3.3.1 · dplyr 1.2.1 · ggplot2 4.0.3 · ใช้ได้กับ R 4.6.1 · ดาวน์โหลด choosing-a-decision-analytic-model.R
สคริปต์ฉบับเต็ม
# Choosing a Decision-Analytic Model: Let the Clinical Pathway Decide
# Follow one leg cellulitis case from a two-week tree to monthly states with memory.
# ติดตามผู้ป่วยเซลลูไลติสที่ขาจากต้นไม้สองสัปดาห์ ไปสู่ภาวะรายเดือนที่จำอดีตได้
# Requires: R >= 4.5.2
# Tested: works in R 4.6.1
# tibble 3.3.1 (stable)
# dplyr 1.2.1 (stable)
# ggplot2 4.0.3 (stable)
# install.packages(c("tibble", "dplyr", "ggplot2"))
# update.packages(oldPkgs = c("tibble", "dplyr", "ggplot2"))
# remotes::install_version("tibble", "3.3.1")
# remotes::install_version("dplyr", "1.2.1")
# remotes::install_version("ggplot2", "4.0.3")
library(tibble) # Write the model inputs as explicit tables.
library(dplyr) # Calculate the weighted and split quantities.
library(ggplot2) # Display the tree size against the reused states without saving files.
stopifnot(getRversion() >= "4.5.2")
#%%@note 1. Define the illustrative inputs
# Every input is synthetic and written out once, in the order the article uses it.
# ค่าตั้งต้นทั้งหมดเป็นข้อมูลสมมติ เขียนไว้ครั้งเดียวตามลำดับที่บทความใช้
p_success <- 0.8
value_success <- 10
value_failure <- 2
periods <- c(1, 2, 3, 10, 12)
states <- c("well", "active cellulitis")
cohort <- 1000
risk_month <- 0.03
well_first <- 750
well_again <- 250
risk_first <- 0.02
risk_again <- 0.06
prevent_cut <- 0.5
recovered <- 1000
risk_month1 <- 0.10
risk_month2 <- 0.05
#%%@note 2. Roll back the two-week tree
# Weight each branch's symptom-free days by its chance, then add the two products.
# ถ่วงวันที่ไม่มีอาการของแต่ละกิ่งด้วยโอกาสของกิ่งนั้น แล้วรวมสองผลคูณ
branches <- tibble::tibble(
branch = c("tablets work", "admitted"), probability = c(p_success, 1 - p_success),
days = c(value_success, value_failure)
) |>
dplyr::mutate(weighted_days = probability * days)
stopifnot(abs(sum(branches$probability) - 1) < 1e-9)
p_failure <- 1 - p_success
weighted_success <- branches$weighted_days[1]
weighted_failure <- branches$weighted_days[2]
expected_days <- weighted_success + weighted_failure
#%%@note 3. Count tree endpoints and take one monthly state step
# A tree doubles its endpoints every month; a state model reuses the same two states.
# ต้นไม้เพิ่มปลายกิ่งเป็นสองเท่าทุกเดือน ส่วนแบบจำลองภาวะใช้สองภาวะเดิมซ้ำ
endpoints <- 2^periods
comma_format <- function(value) formatC(value, format = "f", digits = 0, big.mark = ",")
month_step <- cohort * c(1, risk_month, 1 - risk_month)
growth <- tibble::tibble(month = periods, tree_endpoints = endpoints,
states_reused = length(states))
#%%@note 4. Split the well state by history and by time since recovery
# History states keep 0.02 and 0.06 apart; tunnel states keep the first two months apart.
# ภาวะที่เก็บประวัติแยกความเสี่ยง 0.02 กับ 0.06 ส่วนภาวะอุโมงค์แยกสองเดือนแรกหลังหาย
groups <- tibble::tibble(group = c("no recurrence", "after a recurrence"),
people = c(well_first, well_again), risk = c(risk_first, risk_again)) |>
dplyr::mutate(new_episodes = people * risk)
new_first <- groups$new_episodes[1]
new_again <- groups$new_episodes[2]
average_risk <- (new_first + new_again) / (well_first + well_again)
tunnel_free <- recovered * (1 - risk_month1) * (1 - risk_month2)
flat_free <- recovered * (1 - risk_month)^2
flat_returns <- recovered - flat_free
tunnel_returns <- recovered - tunnel_free
one_decimal <- function(value) formatC(value, format = "f", digits = 1)
#%%@note 5. Display the model
# Plot tree endpoints against the reused states on a log scale; no graphics file is saved.
# แสดงจำนวนปลายกิ่งเทียบกับภาวะที่ใช้ซ้ำบนสเกลลอการิทึม โดยไม่บันทึกไฟล์ภาพ
print(ggplot2::ggplot(growth, ggplot2::aes(x = month)) +
ggplot2::geom_col(ggplot2::aes(y = tree_endpoints)) +
ggplot2::geom_point(ggplot2::aes(y = states_reused)) +
ggplot2::scale_y_log10() + ggplot2::labs(x = "Monthly periods", y = "Count (log scale)"))
#%%@note 6. Numbers the article quotes
# Print exactly the short boxes in their reading order.
# พิมพ์ผลลัพธ์ตรงกับกล่องตัวอย่างตามลำดับในบทความ
cat("Success, failure probability:", p_success, p_failure, "\n")
cat("Weighted days, success and failure:", weighted_success, weighted_failure, "\n")
cat("Expected symptom-free days:", expected_days, "\n")
cat("Monthly periods:", periods, "\n")
cat("Tree endpoints:", comma_format(endpoints), "\n")
cat("States reused every month:", length(states), "\n")
cat("Well now, new episodes, still well:", comma_format(month_step), "\n")
cat("New episodes next month, no recurrence and after one:", new_first, new_again, "\n")
cat("Average monthly risk in one well state:", average_risk, "\n")
cat("Episodes avoided a month, history states:", new_again * prevent_cut, "\n")
cat("Episodes avoided a month, one well state:", well_again * average_risk * prevent_cut, "\n")
cat("Free of a new episode after month 1, tunnel:", recovered * (1 - risk_month1), "\n")
cat("Free after month 2, tunnel and flat 0.03:", tunnel_free, one_decimal(flat_free), "\n")
cat("Returns within two months, tunnel and flat:", tunnel_returns, one_decimal(flat_returns), "\n")
เมื่อผู้ป่วยส่งผลต่อกัน
บางคำถามต้องการมากกว่าความจำ ถ้าการฉีดวัคซีนให้คนหนึ่งลดความเสี่ยงไข้หวัดใหญ่ของอีกคน ความเสี่ยงของแต่ละคนจะขึ้นกับจำนวนคนอื่นที่ติดเชื้อ และแบบจำลองต้องเชื่อมความเสี่ยงเหล่านี้เข้าด้วยกัน กำลังบริการที่ใช้ร่วมกันก็เช่นกัน เมื่อเตียงในหอผู้ป่วยเต็ม การรับผู้ป่วยเซลลูไลติสหนึ่งคนทำให้คนถัดไปต้องรอ ต้นไม้และแบบจำลองภาวะมองผู้ป่วยแต่ละคนแยกกัน คำถามแบบนี้จึงต้องใช้แบบจำลองการแพร่เชื้อหรือแบบจำลองคิว ซึ่งสร้างจากรูปแบบการสัมผัส หรือจากการมาถึงและเวลารอ
เซลลูไลติสไม่ได้แพร่ระหว่างผู้ป่วยแบบนี้ แบบจำลองจึงตั้งใจตัดปฏิสัมพันธ์ออกและเขียนบอกไว้ ความแออัดของเตียงอาจมีผลถ้าแผนรับไว้ทำให้หอผู้ป่วยเต็ม ทีมจึงบันทึกเรื่องนี้เป็นข้อจำกัดที่รู้อยู่
โครงสร้างแต่ละแบบต้องการหลักฐานต่างกัน
โครงสร้างเป็นตัวกำหนดว่าทีมต้องหาตัวเลขอะไรบ้าง และตารางนี้แจกแจงไว้สำหรับเส้นทางการดูแลแต่ละแบบ ค่า 0.02 และ 0.06 ที่ภาวะที่เก็บประวัติต้องใช้ ได้จากการศึกษาที่รายงานการกลับเป็นซ้ำแยกตามการป่วยครั้งก่อนเท่านั้น จึงควรเลือกโครงสร้างจากเส้นทางการดูแลก่อน แล้วจึงค้นหาหลักฐานที่เข้ากับโครงสร้างนั้น แบบจำลองที่ซับซ้อนกว่าไม่ได้ดีกว่าในตัวเอง เพียงแต่ต้องการหลักฐานมากกว่า
จับคู่เส้นทางการดูแลกับโครงสร้างและหลักฐาน
| เส้นทางการดูแลเป็นแบบไหน | โครงสร้าง | หลักฐานที่ต้องใช้ | ในกรณีเซลลูไลติส |
|---|---|---|---|
| ป่วยครั้งเดียวแล้วจบ ไม่มีการกลับเป็นซ้ำที่มีผล | ต้นไม้การตัดสินใจ | โอกาสของแต่ละกิ่ง และจำนวนวันหรือต้นทุนที่ปลายกิ่ง | 0.8 กับ 10 และ 2 วัน |
| การป่วยกลับมาซ้ำตามเวลา | ภาวะที่ย้ายทุกหนึ่งรอบ | ความเสี่ยงต่อเดือนที่จะย้ายภาวะ และจำนวนวันหรือต้นทุนของแต่ละภาวะ | 0.03 ต่อเดือน |
| ความเสี่ยงขึ้นกับการป่วยครั้งก่อน | ภาวะที่เก็บประวัติ หรือการจำลองรายบุคคล | ความเสี่ยงแยกตามประวัติ | 0.02 และ 0.06 |
| ความเสี่ยงขึ้นกับเวลาหลังป่วย | ภาวะอุโมงค์ | ความเสี่ยงรายเดือนหลังหาย | 0.10 แล้ว 0.05 |
| ผู้ป่วยส่งผลต่อกัน หรือใช้เตียงร่วมกัน | แบบจำลองการแพร่เชื้อหรือแบบจำลองคิว | รูปแบบการสัมผัส หรือการมาถึงและเวลารอ | ตัดออก และบันทึกเป็นข้อจำกัด |
เลขคณิตเลือกโครงสร้างแทนเราไม่ได้
ผล 8.4 วันตรวจได้แค่เลขคณิตของต้นไม้ ไม่ได้บอกว่าตัดการกลับเป็นซ้ำ การเสียชีวิต หรือผลเสียระยะยาวออกได้อย่างปลอดภัย การตัดออกยอมรับได้ในที่นี้เพียงเพราะคำถามครอบคลุมการป่วยครั้งเดียวในสองสัปดาห์ คำถามเรื่องการป้องกันนานหนึ่งปีต้องใช้ภาวะ และปลายกิ่ง 4,096 ปลายแสดงเหตุผลนั้น
ขอให้แพทย์ไล่เส้นทางของผู้ป่วยที่ไม่เข้ากับภาพ เช่น ผู้ป่วยที่การติดเชื้อกลับมาหนึ่งสัปดาห์หลังกินยาครบ แล้วถามว่าการเพิ่มเส้นทางนั้นอาจเปลี่ยนการเลือกระหว่างยากินกับการรับไว้หรือไม่ บันทึกคำตอบและเหตุผลของทุกสิ่งที่ตัดออก เพื่อให้ผู้อื่นตรวจและทดสอบแบบจำลองได้ (Eddy and colleagues)
คำศัพท์ที่เราใช้
- Strategy (กลยุทธ์)
- แผนการดูแลทั้งชุดที่นำมาเปรียบเทียบ เช่น ยากินที่บ้านซึ่งรวมการรับไว้หากยาไม่ได้ผล
- Time horizon (ช่วงเวลาที่นับผล)
- ระยะเวลาที่นับผลที่ตามมา สองสัปดาห์สำหรับการป่วยครั้งเดียว หนึ่งปีสำหรับการป้องกัน
- Perspective (มุมมอง)
- การกำหนดว่านับต้นทุนและผลลัพธ์ของใคร เช่น ของโรงพยาบาลหรือของสังคม
- Event (เหตุการณ์)
- สิ่งที่เกิดขึ้นในชั่วขณะหนึ่ง เช่น ยากินไม่ได้ผล
- State (ภาวะ)
- สภาพที่ผู้ป่วยอยู่ต่อเนื่องช่วงหนึ่ง เช่น สบายดีหรือกำลังติดเชื้อ ผู้ป่วยแต่ละคนอยู่ในภาวะเดียวในแต่ละเวลา
- Cycle (รอบ)
- ช่วงเวลาคงที่ที่แบบจำลองภาวะย้ายผู้ป่วย ในที่นี้คือหนึ่งเดือน
- Decision tree (ต้นไม้การตัดสินใจ)
- กิ่งที่แตกจากการเลือก ผ่านจุดที่โอกาสกำหนด ไปถึงจำนวนวันหรือต้นทุนที่ปลายกิ่ง โดยวนกลับตามเวลาไม่ได้
- Expected value (ค่าคาดหมาย)
- จำนวนวันที่ปลายกิ่งแต่ละค่าคูณโอกาสของกิ่งนั้นแล้วรวมกัน คือ 0.8 × 10 + 0.2 × 2 = 8.4 วัน
- No-memory rule (กฎไม่จำอดีต)
- การย้ายครั้งถัดไปขึ้นกับภาวะปัจจุบันเท่านั้น ไม่ขึ้นกับประวัติก่อนหน้า
- History state (ภาวะที่เก็บประวัติ)
- ภาวะที่แยกตามสิ่งที่เคยเกิดมาก่อน เช่น สบายดีหลังเคยกลับเป็นซ้ำ ที่ความเสี่ยง 0.06 ต่อเดือน
- Tunnel state (ภาวะอุโมงค์)
- ภาวะชั่วคราวในชุดที่เรียงต่อกันตายตัว ใช้บันทึกเวลาหลังเหตุการณ์ เช่น เดือนแรกหลังหาย ที่ความเสี่ยง 0.10
- Individual simulation (การจำลองรายบุคคล)
- การติดตามผู้ป่วยทีละคน เพื่อให้แต่ละคนมีประวัติของตัวเอง
เชื่อมกับบทความพื้นฐาน
บทความพื้นฐานเรื่องรูปแบบการศึกษา เป้าหมายการประมาณค่า และมาตรวัดผลแสดงวิธีเขียนคำถามก่อนตัวเลข ส่วนบทความเรื่องต้นไม้การตัดสินใจและแบบจำลองกลุ่มประชากรทบทวนโครงสร้างทั้งสองแบบจากมุมเศรษฐศาสตร์ บทความตอนหลังของชุดนี้สร้างต้นไม้ทีละขั้น แล้วจึงสร้างแบบจำลองภาวะรายเดือน
ลองใช้ในแอป
เปิดแอปแผนภูมิต้นไม้การตัดสินใจของเราเพื่อลองเปลี่ยนค่าข้อมูลนำเข้าและดูผลลัพธ์เปลี่ยนตาม ต้องเข้าสู่ระบบและใช้แผน Pro หรือ Max
แอปเริ่มจากค่าตัวอย่างของแอปเอง ตัวเลขในแอปจึงไม่ตรงกับบทความนี้
เอกสารอ้างอิง
- Andrew Briggs, Karl Claxton, Mark Sculpher. Decision Modelling for Health Economic Evaluation (Handbooks for Health Economic Evaluation). Oxford University Press; 2006. ISBN 9780198526629. https://openlibrary.org/isbn/9780198526629
- Siebert Uwe, Alagoz Oguzhan, Bayoumi Ahmed M., Jahn Beate, Owens Douglas K., Cohen David J., Kuntz Karen M.. State-Transition Modeling: A Report of the ISPOR-SMDM Modeling Good Research Practices Task Force-3. Value in Health. 2012;15(6):812-820. doi:10.1016/j.jval.2012.06.014. https://doi.org/10.1016/j.jval.2012.06.014
- Eddy David M., Hollingworth William, Caro J. Jaime, Tsevat Joel, McDonald Kathryn M., Wong John B.. Model Transparency and Validation: A Report of the ISPOR-SMDM Modeling Good Research Practices Task Force-7. Value in Health. 2012;15(6):843-850. doi:10.1016/j.jval.2012.04.012. https://doi.org/10.1016/j.jval.2012.04.012
ลำดับการเรียนในชุดนี้
- คู่มือชุดบทความการสร้างแบบจำลองเศรษฐศาสตร์สุขภาพ: จากหลักฐานสู่การตัดสินใจ
- การเลือกแบบจำลองเพื่อการตัดสินใจ: ให้เส้นทางทางคลินิกกำหนดโครงสร้าง (บทความนี้)
- ข้อมูลนำเข้าของแบบจำลองที่ตรวจสอบได้: สร้างตารางพารามิเตอร์ที่สืบย้อนถึงที่มา
- การค้นหาข้อมูลนำเข้าของแบบจำลองจากวรรณกรรม: เลือกค่าประมาณให้ตรงกับคำถาม
- อัตรา ความน่าจะเป็น และความน่าจะเป็นของการเปลี่ยนสถานะ: คำนวณโดยไม่หลงหน่วยเวลา
- สร้างแผนภูมิต้นไม้การตัดสินใจทีละขั้น: ตามรอยผลลัพธ์ ต้นทุน และสุขภาพ
- สร้างแบบจำลองมาร์คอฟแบบกลุ่มประชากรทีละขั้น: ติดตามประชากรผ่านเวลา
- การวิเคราะห์ผลกระทบด้านงบประมาณในทางปฏิบัติ: นับคนให้ชัดก่อนคำนวณเงิน
- ICER และผลประโยชน์สุทธิในรูปตัวเงินเมื่อมีหลายทางเลือก: หาขอบเขตทางเลือกที่มีประสิทธิภาพ
- การวิเคราะห์ความไวแบบอาศัยความน่าจะเป็น: จากการแจกแจงพารามิเตอร์สู่ CEAC
- การประเมินความสมเหตุสมผลและตรวจสอบแบบจำลอง: ทดสอบคำถาม สมการ และโค้ด
- มูลค่าคาดหมายของข้อมูลสมบูรณ์: หลักฐานที่ดีขึ้นอาจมีมูลค่าเพียงใด
ประเด็นสำคัญ
- เขียนคำถามก่อน ผู้ป่วย แผนการดูแลทั้งชุด ช่วงเวลาที่นับผล และมุมมอง เป็นตัวกำหนดโครงสร้างก่อนโปรแกรมใด
- การป่วยครั้งเดียวที่มีจุดจบใช้ต้นไม้ก็พอ คือ 0.8 × 10 + 0.2 × 2 = 8.4 วันที่ไม่มีอาการในสองสัปดาห์
- เมื่อโรคกลับเป็นซ้ำ ให้ใช้ภาวะ หนึ่งปีที่กลับมาได้ทุกเดือนต้องใช้ต้นไม้ 4,096 ปลายกิ่ง แต่ใช้เพียง 2 ภาวะซ้ำ
- เมื่อความเสี่ยงจำอดีต ให้แยกภาวะ เมื่อใช้ภาวะที่เก็บประวัติ การป้องกันหลังกลับเป็นซ้ำลดได้ 7.5 ครั้งต่อเดือน ขณะที่ภาวะสบายดีภาวะเดียวแสดงเพียง 3.75
- โครงสร้างแต่ละแบบต้องใช้หลักฐานของตัวเอง และเลขคณิตตรวจได้แค่ผลรวม ไม่ได้บอกว่าโครงสร้างเข้ากับโรคหรือไม่
อ่านต่อในวิกิ: รูปแบบการศึกษา แบบจำลองทางสถิติ และเป้าหมายการประมาณค่า: แต่ละรูปแบบการศึกษาประมาณค่าอะไรได้จริง · ต้นไม้การตัดสินใจ แบบจำลองมาร์คอฟ และการวิเคราะห์ความไวเชิงความน่าจะเป็น: แบบจำลองแปลงหลักฐานเป็นการตัดสินใจได้อย่างไร