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

Health EconomicsClinical Epidemiology ResearchMethodology and Research Design TH
การเลือกแบบจำลองเพื่อการตัดสินใจ: ให้เส้นทางทางคลินิกกำหนดโครงสร้าง
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. แจกแจงกิ่ง

    \[ 1-0.8=0.2 \]

    ยากินได้ผลด้วยโอกาส 0.8 และให้วันที่ไม่มีอาการ 10 วัน ผู้ป่วยถูกรับไว้ด้วยโอกาสที่เหลือ คือ 0.2 และได้ 2 วัน

  2. ถ่วงแต่ละกิ่ง

    \[ 0.8\times 10=8 \]

    \[ 0.2\times 2=0.4 \]

    กิ่งที่ยาได้ผลให้ 8 วัน ส่วนกิ่งที่ต้องรับไว้ให้ 0.4 วัน

  3. รวมกิ่งที่ถ่วงแล้ว

    \[ 8+0.4=8.4 \]

    ผลของสองกิ่งรวมกันเป็นค่าเฉลี่ยของแผนต่อผู้ป่วยหนึ่งคน

ผลลัพธ์: ยากินที่บ้านให้วันที่ไม่มีอาการเฉลี่ย 8.4 วันต่อผู้ป่วยหนึ่งคนในสองสัปดาห์

ชื่อเรียก: ต้นไม้การตัดสินใจและการย้อนคำนวณ

ภาพแบบนี้เรียกว่าต้นไม้การตัดสินใจ (decision tree) มีสี่เหลี่ยมแทนการเลือก วงกลมแทนจุดที่โอกาสเป็นผู้กำหนด และจำนวนวันที่ปลายกิ่ง การคำนวณจากปลายกิ่งย้อนกลับมาที่สี่เหลี่ยมแบบขั้นตอนข้างบนเรียกว่าการย้อนคำนวณต้นไม้ (rolling back) ผลที่ได้ 8.4 วันคือค่าคาดหมาย (expected value) ของแผน หรือค่าเฉลี่ยต่อผู้ป่วยหนึ่งคน แผนรับไว้ในโรงพยาบาลก็ย้อนคำนวณแบบเดียวกันด้วยโอกาสและจำนวนวันของตัวเอง บทความนี้ติดตามเฉพาะแผนยากิน ส่วนการเทียบแผนทั้งชุดอยู่ในบทความตอนหลังของชุดนี้

ไล่เส้นสีน้ำเงินจากสี่เหลี่ยม วงกลมแยกเป็นโอกาส 0.8 ได้ 10 วัน และ 0.2 ได้ 2 วัน กล่องด้านล่างรวมสองกิ่งที่ถ่วงแล้ว คือ 0.8 × 10 กับ 0.2 × 2 เป็น 8.4 วัน แผนรับไว้ที่เป็นเส้นประย้อนคำนวณแบบเดียวกัน การเลือกจึงเป็นการเทียบค่าเฉลี่ยสองค่าแบบนี้
โค้ด R example.R
# 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")
ผลลัพธ์จากการรัน example.log
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")
สังเกตวันที่ถ่วงแล้ว 8 และ 0.4 กิ่งที่ต้องรับไว้เพิ่มไม่ถึงครึ่งวัน เพราะทั้งเกิดได้ยากและได้วันน้อย

เมื่อโรคกลับเป็นซ้ำ ให้ใช้ภาวะ

ทีนี้เปลี่ยนคำถาม ผู้ป่วยจำนวนมากกลับมาเป็นเซลลูไลติสซ้ำ และโรงพยาบาลถามว่าผู้ป่วยที่หายแล้ว ควรกินยาปฏิชีวนะป้องกันนานหนึ่งปีหรือไม่ หนึ่งปีที่การติดเชื้อกลับมาได้ทุกเดือนใส่ในต้นไม้สั้น ๆ ไม่ได้ ความเสี่ยงรายเดือนจากนี้ไปเป็นตัวเลขสมมติเพื่อการสอน แบบจำลองจริงต้องนำมาจากการศึกษา

สมมติว่าการป่วยครั้งใหม่เริ่มได้ในทุกเดือน ต้นไม้วนกลับไปกิ่งก่อนหน้าไม่ได้ จึงต้องแยกกิ่งทุกเดือนเป็นป่วยครั้งใหม่หรือไม่ป่วย ปลายกิ่งจึงเพิ่มเป็นสองเท่า คือ 2 หลังหนึ่งเดือน 4 หลังสองเดือน 8 หลังสามเดือน และ 4,096 หลัง 12 เดือน ปลายกิ่งแต่ละปลายยังต้องมีจำนวนวันและต้นทุนของตัวเอง ซึ่งไม่มีทีมใดกรอกด้วยมือได้

แบบจำลองภาวะเลี่ยงการขยายตัวนี้ได้ แบบจำลองนี้แบ่งผู้ป่วยเป็นภาวะไม่กี่ภาวะ ผู้ป่วยแต่ละคนอยู่ในภาวะเดียวในแต่ละเวลา ในที่นี้คือสบายดีกับกำลังติดเชื้อ แล้วย้ายผู้ป่วยระหว่างภาวะทุกหนึ่งรอบ (cycle) ซึ่งเป็นช่วงเวลาคงที่ ในที่นี้คือหนึ่งเดือน ในผู้ป่วย 1,000 คนที่สบายดีเดือนนี้ ด้วยความเสี่ยงต่อเดือน 0.03 จะมี 30 คนเริ่มป่วยครั้งใหม่ในเดือนหน้า และ 970 คนยังสบายดี สองภาวะเดิมถูกใช้ซ้ำทุกเดือน ไม่ว่าช่วงเวลาที่นับผลจะยาวเท่าไร

การติดตามทั้งกลุ่มแบบนี้ในรูปสัดส่วนที่กระจายอยู่ตามภาวะต่าง ๆ เรียกว่าแบบจำลองการเปลี่ยนภาวะของกลุ่มประชากร (cohort state-transition model) แบบจำลองนี้ต้องการความเสี่ยงต่อเดือนที่จะป่วยครั้งใหม่และโอกาสหายต่อเดือน ไม่ต้องมีค่าแยกสำหรับเส้นทางทั้ง 4,096 เส้น

เทียบสองช่อง ต้นไม้ทางซ้ายเพิ่มกิ่งอีกชั้นทุกเดือนจนมี 4,096 ปลายกิ่งเมื่อครบ 12 เดือน ส่วนช่องขวาใช้ 2 ภาวะเดิมซ้ำ โรคที่กลับเป็นซ้ำเรื่อย ๆ จึงวาดเป็นภาวะ ไม่ใช่ต้นไม้ที่ยาวขึ้น
ตัวควบคุมเริ่มที่ต้นไม้ในบทความ คือ 0.8 และ 10 กับ 2 วัน ได้ 8.4 วันที่ไม่มีอาการ ลองเลื่อนจำนวนเดือนไปที่ 10 แล้วดูแท่งทางขวา ต้นไม้ต้องมี 1,024 ปลายกิ่ง ขณะที่แบบจำลองภาวะยังใช้ 2 ภาวะเดิม นี่คือสัญญาณให้เปลี่ยนโครงสร้าง
โค้ด R recur.R
# 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")
ผลลัพธ์จากการรัน recur.log
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")
สังเกตว่าปลายกิ่งกระโดดจาก 8 ที่ 3 เดือน เป็น 1,024 ที่ 10 เดือน ขณะที่แบบจำลองภาวะยังใช้ 2 ภาวะ

เมื่อความเสี่ยงจำอดีต ให้แยกภาวะ

แบบจำลองสองภาวะแบบพื้นฐานไม่มีความจำ แบบจำลองนี้สมมติว่าโอกาสย้ายภาวะครั้งถัดไปขึ้นกับภาวะที่ผู้ป่วยอยู่ตอนนี้เท่านั้น ไม่ขึ้นกับว่ามาถึงภาวะนี้อย่างไร ข้อสมมตินี้เรียกในบทความนี้ว่ากฎไม่จำอดีต (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 ไม่ใช่แค่ค่าเฉลี่ย

โค้ด R history.R
# 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")
ผลลัพธ์จากการรัน history.log
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")
สังเกตว่า 15 กับ 15 รวมเป็น 30 เท่ากับเมื่อใช้ภาวะเดียว การแยกภาวะเปลี่ยนว่าใครเสี่ยง ไม่ได้เปลี่ยนจำนวนรวมของเดือนนี้

ชื่อที่ใช้กันทั่วไปของกฎไม่จำอดีต: สมมติฐานมาร์คอฟ (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) ซึ่งใช้ความเสี่ยงชุดเดียวกัน แต่บันทึกตามประวัติของผู้ป่วยแต่ละคน

ดูลูกศรด้านบน ลูกศรหนาจากภาวะสบายดีหลังเคยกลับเป็นซ้ำมีความเสี่ยง 0.06 ต่อเดือน เทียบกับ 0.02 การป้องกันที่มุ่งไปที่กล่องนี้จึงลดได้ 7.5 ครั้ง ไม่ใช่ 3.75 ด้านล่าง แท่งลดจาก 0.10 เป็น 0.05 และ 0.03 ตามเดือนในภาวะอุโมงค์ แบบจำลองจึงนับการกลับมาป่วยช่วงแรก 145 คนได้
โค้ด R tunnel.R
# 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")
ผลลัพธ์จากการรัน tunnel.log
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")
สังเกตบรรทัดสุดท้าย ภาวะอุโมงค์ให้การกลับมาป่วย 145 คน ขณะที่ความเสี่ยงคงที่ทำนายไว้เพียง 59.1 คน

เมื่อผู้ป่วยส่งผลต่อกัน

บางคำถามต้องการมากกว่าความจำ ถ้าการฉีดวัคซีนให้คนหนึ่งลดความเสี่ยงไข้หวัดใหญ่ของอีกคน ความเสี่ยงของแต่ละคนจะขึ้นกับจำนวนคนอื่นที่ติดเชื้อ และแบบจำลองต้องเชื่อมความเสี่ยงเหล่านี้เข้าด้วยกัน กำลังบริการที่ใช้ร่วมกันก็เช่นกัน เมื่อเตียงในหอผู้ป่วยเต็ม การรับผู้ป่วยเซลลูไลติสหนึ่งคนทำให้คนถัดไปต้องรอ ต้นไม้และแบบจำลองภาวะมองผู้ป่วยแต่ละคนแยกกัน คำถามแบบนี้จึงต้องใช้แบบจำลองการแพร่เชื้อหรือแบบจำลองคิว ซึ่งสร้างจากรูปแบบการสัมผัส หรือจากการมาถึงและเวลารอ

เซลลูไลติสไม่ได้แพร่ระหว่างผู้ป่วยแบบนี้ แบบจำลองจึงตั้งใจตัดปฏิสัมพันธ์ออกและเขียนบอกไว้ ความแออัดของเตียงอาจมีผลถ้าแผนรับไว้ทำให้หอผู้ป่วยเต็ม ทีมจึงบันทึกเรื่องนี้เป็นข้อจำกัดที่รู้อยู่

โครงสร้างแต่ละแบบต้องการหลักฐานต่างกัน

โครงสร้างเป็นตัวกำหนดว่าทีมต้องหาตัวเลขอะไรบ้าง และตารางนี้แจกแจงไว้สำหรับเส้นทางการดูแลแต่ละแบบ ค่า 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

แอปเริ่มจากค่าตัวอย่างของแอปเอง ตัวเลขในแอปจึงไม่ตรงกับบทความนี้

เอกสารอ้างอิง

  1. 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
  2. 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
  3. 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

ลำดับการเรียนในชุดนี้

  1. คู่มือชุดบทความการสร้างแบบจำลองเศรษฐศาสตร์สุขภาพ: จากหลักฐานสู่การตัดสินใจ
  2. การเลือกแบบจำลองเพื่อการตัดสินใจ: ให้เส้นทางทางคลินิกกำหนดโครงสร้าง (บทความนี้)
  3. ข้อมูลนำเข้าของแบบจำลองที่ตรวจสอบได้: สร้างตารางพารามิเตอร์ที่สืบย้อนถึงที่มา
  4. การค้นหาข้อมูลนำเข้าของแบบจำลองจากวรรณกรรม: เลือกค่าประมาณให้ตรงกับคำถาม
  5. อัตรา ความน่าจะเป็น และความน่าจะเป็นของการเปลี่ยนสถานะ: คำนวณโดยไม่หลงหน่วยเวลา
  6. สร้างแผนภูมิต้นไม้การตัดสินใจทีละขั้น: ตามรอยผลลัพธ์ ต้นทุน และสุขภาพ
  7. สร้างแบบจำลองมาร์คอฟแบบกลุ่มประชากรทีละขั้น: ติดตามประชากรผ่านเวลา
  8. การวิเคราะห์ผลกระทบด้านงบประมาณในทางปฏิบัติ: นับคนให้ชัดก่อนคำนวณเงิน
  9. ICER และผลประโยชน์สุทธิในรูปตัวเงินเมื่อมีหลายทางเลือก: หาขอบเขตทางเลือกที่มีประสิทธิภาพ
  10. การวิเคราะห์ความไวแบบอาศัยความน่าจะเป็น: จากการแจกแจงพารามิเตอร์สู่ CEAC
  11. การประเมินความสมเหตุสมผลและตรวจสอบแบบจำลอง: ทดสอบคำถาม สมการ และโค้ด
  12. มูลค่าคาดหมายของข้อมูลสมบูรณ์: หลักฐานที่ดีขึ้นอาจมีมูลค่าเพียงใด

ประเด็นสำคัญ

  • เขียนคำถามก่อน ผู้ป่วย แผนการดูแลทั้งชุด ช่วงเวลาที่นับผล และมุมมอง เป็นตัวกำหนดโครงสร้างก่อนโปรแกรมใด
  • การป่วยครั้งเดียวที่มีจุดจบใช้ต้นไม้ก็พอ คือ 0.8 × 10 + 0.2 × 2 = 8.4 วันที่ไม่มีอาการในสองสัปดาห์
  • เมื่อโรคกลับเป็นซ้ำ ให้ใช้ภาวะ หนึ่งปีที่กลับมาได้ทุกเดือนต้องใช้ต้นไม้ 4,096 ปลายกิ่ง แต่ใช้เพียง 2 ภาวะซ้ำ
  • เมื่อความเสี่ยงจำอดีต ให้แยกภาวะ เมื่อใช้ภาวะที่เก็บประวัติ การป้องกันหลังกลับเป็นซ้ำลดได้ 7.5 ครั้งต่อเดือน ขณะที่ภาวะสบายดีภาวะเดียวแสดงเพียง 3.75
  • โครงสร้างแต่ละแบบต้องใช้หลักฐานของตัวเอง และเลขคณิตตรวจได้แค่ผลรวม ไม่ได้บอกว่าโครงสร้างเข้ากับโรคหรือไม่

อ่านต่อในวิกิ: รูปแบบการศึกษา แบบจำลองทางสถิติ และเป้าหมายการประมาณค่า: แต่ละรูปแบบการศึกษาประมาณค่าอะไรได้จริง · ต้นไม้การตัดสินใจ แบบจำลองมาร์คอฟ และการวิเคราะห์ความไวเชิงความน่าจะเป็น: แบบจำลองแปลงหลักฐานเป็นการตัดสินใจได้อย่างไร

0
ถึงนักอ่านชาวไทยและต่างชาติทำความเข้าใจบริบททางการแพทย์ของผมอ่านต่อ →ถึงนักอ่านชาวไทยและต่างชาติทำความเข้าใจเนื้อหาของผมที่นอกเหนือจากการแพทย์อ่านต่อ →

ความคิดเห็น

ยังไม่มีความคิดเห็น มาเป็นคนแรกกันเลย

เข้าสู่ระบบเพื่อแสดงความคิดเห็น