ICER และผลประโยชน์สุทธิในรูปตัวเงินเมื่อมีหลายทางเลือก: หาขอบเขตทางเลือกที่มีประสิทธิภาพ

On this page
Read the English version
บทคัดย่อ
ทีมโรคหัวใจของโรงพยาบาลประจำภูมิภาคแห่งหนึ่งต้องเลือกแผนติดตามเพียงแผนเดียวสำหรับผู้ป่วยทุกคนที่ออกจากโรงพยาบาลหลังกล้ามเนื้อหัวใจขาดเลือดเฉียบพลัน เมื่อเทียบกับการนัดตรวจที่คลินิกตามปกติ (A) การที่พยาบาลโทรติดตามทุกเดือน (B) เพิ่มต้นทุน 8,000 บาทและเพิ่มปีสุขภาพสมบูรณ์ 0.08 ปีต่อผู้ป่วย การฟื้นฟูหัวใจที่บ้าน (C) เพิ่ม 16,000 บาทและ 0.18 ปี และการฟื้นฟูหัวใจที่โรงพยาบาล (D) เพิ่ม 19,000 บาทและ 0.17 ปี เมื่อเทียบกับการนัดตรวจตามปกติอย่างเดียว ทุกแผนใหม่มีต้นทุนต่อปีสุขภาพสมบูรณ์ที่เพิ่มต่ำกว่า 160,000 บาทที่กองทุนยอมจ่าย ทางลัดนี้จึงเลือกแผนไม่ได้ วิธีแก้มีสามขั้น ขั้นแรก กัน D ออก เพราะ C ถูกกว่าและได้มากกว่า ขั้นต่อไป เทียบแต่ละแผนกับแผนที่อยู่ถัดลงมาในด้านสุขภาพ ขั้นจาก B ไป C ซื้อสุขภาพได้ถูกกว่าขั้นจาก A ไป B ส่วนผสมของ A กับ C จึงชนะ B ขั้นสุดท้าย ขั้นจาก A ไป C ใช้ 88,888.89 บาทต่อปีสุขภาพสมบูรณ์ ซึ่งต่ำกว่า 160,000 บาท การตีค่าสุขภาพที่ 160,000 บาทแล้วหักต้นทุนก็เลือก C เช่นกัน
ทีมโรคหัวใจที่ต้องเลือกหนึ่งแผนจากสี่แผน
ทีมโรคหัวใจของโรงพยาบาลประจำภูมิภาคแห่งหนึ่งติดตามผู้ใหญ่ทุกคนที่ออกจากโรงพยาบาลหลังกล้ามเนื้อหัวใจขาดเลือดเฉียบพลัน ทีมต้องเลือกแผนติดตามหนึ่งแผนเป็นแนวทางมาตรฐาน เพราะทุกแผนใช้พยาบาลและเวลาคลินิกชุดเดียวกัน แผน A คือการนัดตรวจที่คลินิกตามปกติ แผน B เพิ่มการที่พยาบาลโทรติดตามทุกเดือน แผน C เพิ่มโปรแกรมฟื้นฟูสมรรถภาพหัวใจที่บ้าน และแผน D จัดโปรแกรมเดียวกันที่ห้องออกกำลังกายของโรงพยาบาล
การเทียบแผนต้องมีหน่วยสุขภาพหน่วยเดียวที่นับได้ทั้งความยืนยาวและคุณภาพชีวิต ปีสุขภาวะ (quality-adjusted life year, QALY) คือปีชีวิตที่ถ่วงน้ำหนักด้วยคุณภาพ ตั้งแต่ 1 สำหรับสุขภาพสมบูรณ์ถึง 0 สำหรับการเสียชีวิต การอยู่ 10 ปีในสภาวะที่มีค่า 0.70 เท่ากับ 7.0 QALY การมีสุขภาพสมบูรณ์ตลอดช่วงเวลานั้นจึงได้เพิ่ม 3.0 QALY อ่านบทเรียนเต็มได้ที่บทความพื้นฐานเรื่องปีสุขภาวะ
ตัวเลขทั้งหมดต่อจากนี้คิดต่อผู้ป่วยหนึ่งคน และเป็นส่วนที่เพิ่มจากแผน A แผน A จึงอยู่ที่ 0 บาทและ 0 QALY การโทรติดตามของพยาบาล (B) เพิ่ม 8,000 บาทและ 0.08 QALY การฟื้นฟูที่บ้าน (C) เพิ่ม 16,000 บาทและ 0.18 QALY ส่วนการฟื้นฟูที่โรงพยาบาล (D) เพิ่ม 19,000 บาทและ 0.17 QALY เพราะค่าบุคลากรและค่าเดินทางสูงกว่า และผู้ป่วยทำโปรแกรมจนครบน้อยกว่า
กองทุนที่จ่ายค่าบริการของทีมยอมจ่ายได้สูงสุด 160,000 บาทต่อหนึ่ง QALY ซึ่งเป็นเกณฑ์สมมติของชุดบทความนี้ ตัวเลขทั้งหมดในบทความนี้สมมติขึ้นเพื่อการสอน ไม่ใช่หลักฐานเรื่องการฟื้นฟูสมรรถภาพหัวใจหรือเกณฑ์ของผู้จ่ายในประเทศไทย
สี่แผนต่อผู้ป่วยหนึ่งคน เมื่อเทียบกับแผน A
| แผน | ต้นทุนที่เพิ่ม (บาท) | QALY ที่เพิ่ม |
|---|---|---|
| A: นัดตรวจที่คลินิกตามปกติ | 0 | 0 |
| B: พยาบาลโทรติดตามทุกเดือน | 8,000 | 0.08 |
| C: ฟื้นฟูหัวใจที่บ้าน | 16,000 | 0.18 |
| D: ฟื้นฟูหัวใจที่โรงพยาบาล | 19,000 | 0.17 |
ทางลัด: เทียบทุกแผนกับการนัดตรวจตามปกติ
เมื่อมีทางเลือกใหม่หนึ่งทางกับตัวเปรียบเทียบหนึ่งตัว เครื่องมือที่ใช้กันคืออัตราส่วน อัตราส่วนต้นทุนประสิทธิผลส่วนเพิ่ม (incremental cost-effectiveness ratio, ICER) คือต้นทุนที่เพิ่มหารด้วยสุขภาพที่ได้เพิ่ม เมื่อเทียบกับทางเลือกที่อยู่ถัดลงมา ในตัวอย่างร่วมของชุดบทความ ทางเลือกที่แพงกว่า 150,000 บาทและได้เพิ่ม 1.00 QALY มี ICER 150,000 บาทต่อ QALY ซึ่งต่ำกว่าเกณฑ์ 160,000 บาทต่อ QALY อ่านบทเรียนเต็มได้ที่บทความพื้นฐานเรื่องICER และเกณฑ์
ทางลัดที่ชวนให้ใช้คือการหารต้นทุนที่เพิ่มของแต่ละแผนด้วย QALY ที่เพิ่มเมื่อเทียบกับแผน A แผน B ได้ 8,000 / 0.08 = 100,000 บาทต่อ QALY แผน C ได้ 88,888.89 บาท และแผน D ได้ 111,764.71 บาท ทั้งสามแผนต่ำกว่า 160,000 บาท ทางลัดจึงบอกว่าทุกแผนคุ้มที่จะซื้อ แต่บอกไม่ได้ว่าควรเลือกแผนใด และยังให้แผน D ผ่าน ทั้งที่ D ไม่เคยเป็นคำตอบที่ถูกในกรณีนี้
นี่คือความเข้าใจผิดที่บทความนี้แก้ การผ่านเกณฑ์เมื่อเทียบกับการดูแลตามปกติ ยังไม่ได้แปลว่าแผนนั้นเป็นตัวเลือกที่ดี แต่ละแผนต้องเทียบกับแผนที่ถูกกว่าถัดลงมา หลังจากตัดแผนที่แพ้ออกแล้ว Drummond และคณะ และ Briggs, Claxton และ Sculpher อธิบายการเปรียบเทียบตามลำดับนี้ไว้ในตำราของตน
ตรวจทางลัดด้วย R
# The heart team's four follow-up plans: extra cost and extra health per patient over plan A.
# Order A, B, C, D. Health is in quality-weighted years. All values are illustrative.
cost <- c(0, 8000, 16000, 19000)
effect <- c(0, 0.08, 0.18, 0.17)
lambda <- 160000
big <- function(value) prettyNum(round(value, 2), big.mark = ",", digits = 10, scientific = FALSE)
cat("10 years at 0.70 =", formatC(10 * 0.70, format = "f", digits = 1),
"| full health over those years adds", formatC(10 * 0.30, format = "f", digits = 1), "\n")
cat("Series example: 150000 / 1.00 =", big(150000 / 1.00), "THB | threshold:", big(lambda), "\n")
cat("Each plan against A, THB per unit of health (B, C, D):", big(cost[-1] / effect[-1]), "\n")
cat("Below the threshold (B, C, D):", cost[-1] / effect[-1] < lambda, "\n")
10 years at 0.70 = 7.0 | full health over those years adds 3.0
Series example: 150000 / 1.00 = 150,000 THB | threshold: 160,000
Each plan against A, THB per unit of health (B, C, D): 100,000 88,888.89 111,764.71
Below the threshold (B, C, D): TRUE TRUE TRUE
ต้องใช้ R ≥ 4.5.2 · tibble 3.3.1 · dplyr 1.2.1 · ggplot2 4.0.3 · dampack 1.0.2.1000 · ใช้ได้กับ R 4.6.1 · ดาวน์โหลด icer-and-net-monetary-benefit-across-strategies.R
สคริปต์ฉบับเต็ม
# Four follow-up plans after a heart attack: set aside the beaten plans, then find the best buy
# แผนติดตามผู้ป่วยหลังกล้ามเนื้อหัวใจขาดเลือดสี่แบบ: กันแผนที่แพ้ออก แล้วหาแผนที่คุ้มที่สุด
# 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)
# dampack 1.0.2.1000 (stable)
# install.packages(c("tibble", "dplyr", "ggplot2", "dampack"))
# update.packages(oldPkgs = c("tibble", "dplyr", "ggplot2", "dampack"))
# remotes::install_version("tibble", "3.3.1")
# remotes::install_version("dplyr", "1.2.1")
# remotes::install_version("ggplot2", "4.0.3")
# remotes::install_version("dampack", "1.0.2.1000")
library(tibble) # Write the four plans as an explicit input table.
library(dplyr) # Add each plan's net gain to the table.
library(ggplot2) # Display the plans without saving files.
library(dampack) # Cross-check which plans drop out with an independent routine.
stopifnot(getRversion() >= "4.5.2")
#%%@note 1. The four plans, as extra cost and extra health over plan A
# Order A, B, C, D. Cost is THB per patient and health is quality-weighted years per patient.
# All values are illustrative, not cardiac rehabilitation evidence or a payer's rule.
# เรียงเป็น A, B, C, D ต้นทุนเป็นบาทต่อผู้ป่วย สุขภาพเป็นปีที่ถ่วงด้วยคุณภาพต่อผู้ป่วย
# ค่าทั้งหมดเป็นตัวอย่างสมมติ ไม่ใช่หลักฐานเรื่องการฟื้นฟูหัวใจหรือเกณฑ์ของผู้จ่าย
cost <- c(0, 8000, 16000, 19000)
effect <- c(0, 0.08, 0.18, 0.17)
lambda <- 160000
strategy <- c("A", "B", "C", "D")
big <- function(value) prettyNum(round(value, 2), big.mark = ",", digits = 10, scientific = FALSE)
two <- function(value) formatC(value, format = "f", digits = 2)
plans <- tibble::tibble(strategy = strategy, cost = cost, effect = effect)
#%%@note 2. Set aside the plan beaten outright, then compare neighbours
# D costs more than C and gives less health, so it leaves first. The steps then run A to B to C.
# D แพงกว่า C และได้สุขภาพน้อยกว่า จึงออกก่อน แล้วจึงไล่ขั้นจาก A ไป B ไป C
stopifnot(cost[4] > cost[3], effect[4] < effect[3])
step_cost <- diff(cost[1:3])
step_effect <- diff(effect[1:3])
stopifnot(step_cost[1] / step_effect[1] > step_cost[2] / step_effect[2])
checked <- dampack::calculate_icers(cost = cost, effect = effect, strategies = strategy)
stopifnot(identical(checked$Status[match(strategy, checked$Strategy)], c("ND", "ED", "ND", "D")))
#%%@note 3. Price the mix of A and C, then the step from A to C
# The mix gives C to a share of patients and A to the rest, so its average health equals B's.
# ส่วนผสมให้ C แก่ผู้ป่วยส่วนหนึ่งและให้ A แก่ที่เหลือ สุขภาพเฉลี่ยจึงเท่ากับของ B
share_c <- (effect[2] - effect[1]) / (effect[3] - effect[1])
mix_cost <- (1 - share_c) * cost[1] + share_c * cost[3]
mix_effect <- (1 - share_c) * effect[1] + share_c * effect[3]
ratio <- (cost[3] - cost[1]) / (effect[3] - effect[1])
stopifnot(mix_cost < cost[2], abs(mix_effect - effect[2]) < 1e-9, ratio < lambda)
#%%@note 4. Value health at the threshold and subtract cost
# Each plan's extra health is priced at the threshold, then its extra cost is taken away.
# ตีค่าสุขภาพที่เพิ่มของแต่ละแผนด้วยเกณฑ์ แล้วหักต้นทุนที่เพิ่มออก
valued <- lambda * effect
net <- valued - cost
plans <- plans |>
dplyr::mutate(net = lambda * effect - cost)
stopifnot(strategy[which.max(net)] == "C", all(abs(plans$net - net) < 1e-9))
#%%@note 5. Display the four plans
# Plot extra cost against extra health per patient, with the line from A to C. No file is saved.
# แสดงต้นทุนที่เพิ่มเทียบกับสุขภาพที่เพิ่มต่อผู้ป่วย พร้อมเส้นจาก A ไป C โดยไม่บันทึกไฟล์ภาพ
print(ggplot2::ggplot(plans, ggplot2::aes(x = effect, y = cost, label = strategy)) +
ggplot2::geom_point() + ggplot2::geom_text(nudge_y = 700) +
ggplot2::geom_line(data = dplyr::filter(plans, strategy %in% c("A", "C"))) +
ggplot2::labs(x = "Extra QALYs per patient", y = "Extra cost per patient (THB)"))
#%%@note 6. Numbers the article quotes
# Print the short boxes' lines in their reading order.
# พิมพ์ผลลัพธ์ตรงกับกล่องโค้ดสั้นตามลำดับในบทความ
cat("10 years at 0.70 =", formatC(10 * 0.70, format = "f", digits = 1),
"| full health over those years adds", formatC(10 * 0.30, format = "f", digits = 1), "\n")
cat("Series example: 150000 / 1.00 =", big(150000 / 1.00), "THB | threshold:", big(lambda), "\n")
cat("Each plan against A, THB per unit of health (B, C, D):", big(cost[-1] / effect[-1]), "\n")
cat("Below the threshold (B, C, D):", cost[-1] / effect[-1] < lambda, "\n")
cat("Series: 270000 - 250000 =", big(270000 - 250000), "| 6.00 - 5.90 =", two(6.00 - 5.90), "\n")
cat("C against D: saves", big(cost[4] - cost[3]), "THB | gains", two(effect[3] - effect[4]), "\n")
cat("D against C:", big(cost[4] - cost[3]), "/", two(effect[4] - effect[3]), "=",
big((cost[4] - cost[3]) / (effect[4] - effect[3])), "\n")
cat("Steps A to B, B to C: cost", big(step_cost), "THB | health", two(step_effect), "\n")
cat("THB per unit of health, A to B then B to C:", big(step_cost / step_effect), "\n")
cat("Share given C | given A:", paste0(two(100 * c(share_c, 1 - share_c)), "%"), "\n")
cat("Per 100 patients, on C:", two(100 * share_c), "\n")
cat("Health of the mix:", two(mix_effect), "| plan B:", two(effect[2]), "\n")
cat("Cost of the mix:", big(mix_cost), "THB | plan B:", big(cost[2]), "THB | saving:",
big(cost[2] - mix_cost), "THB\n")
cat("A to C: cost", big(cost[3] - cost[1]), "THB | health", two(effect[3] - effect[1]), "\n")
cat("A to C, THB per unit of health:", big(ratio), "\n")
cat("Below the threshold of", big(lambda), "THB:", ratio < lambda, "\n")
cat("Series example: 160000 x 1.00 - 150000 =", big(160000 * 1.00 - 150000), "THB\n")
cat("Health valued at the threshold (A, B, C, D):", big(valued), "THB\n")
cat("Net gain over A (A, B, C, D):", big(net), "THB | largest:", strategy[which.max(net)], "\n")
cat("A and C tie at", big(cost[3] / effect[3]), "| B beats A above", big(cost[2] / effect[2]),
"| B beats C below", big((cost[3] - cost[2]) / (effect[3] - effect[2])), "\n")
ขั้นแรก: กันแผนที่แพ้แผนอื่นทั้งสองด้านออก
เริ่มจากการตรวจที่ง่ายที่สุด คือมีแผนใดแพ้แผนอื่นทั้งด้านต้นทุนและด้านสุขภาพหรือไม่ การครอบงำ (dominance) คือกฎที่ตัดทางเลือกออกเมื่อมีอีกทางเลือกที่ถูกกว่าและให้สุขภาพไม่น้อยกว่า ในตัวอย่างของชุดบทความ ทางเลือกที่มีต้นทุน 270,000 บาทและได้ 5.90 QALY แพ้ทางเลือกที่มีต้นทุน 250,000 บาทและได้ 6.00 QALY เพราะแพงกว่า 20,000 บาท แต่ได้น้อยกว่า 0.10 QALY ทางเลือกที่ถูกกว่าจึงครอบงำทางเลือกนั้น อ่านบทเรียนเต็มได้ที่บทความพื้นฐานเรื่องการครอบงำ
ในกรณีของทีมโรคหัวใจ แผน D แพงกว่าแผน C อยู่ 3,000 บาท และได้น้อยกว่า 0.01 QALY ไม่ว่ากองทุนจะให้ค่าแต่ละ QALY เท่าใด C ก็ชนะ D เพราะถูกกว่าและได้มากกว่า จึงกล่าวว่า C ครอบงำ D และ D ออกจากการเปรียบเทียบ แผนที่ทั้งแพงกว่าและได้ผลน้อยกว่าอีกแผนหนึ่งเรียกว่าถูกครอบงำแบบเด็ดขาด (strictly dominated)
อย่าพยายามช่วย D ด้วยอัตราส่วน การเทียบ D กับ C ได้ 3,000 / -0.01 = -300,000 บาทต่อ QALY ซึ่งเป็นค่าติดลบที่ดูเหมือนคุ้ม อัตราส่วนที่ติดลบอาจแปลว่าถูกกว่าและดีกว่า หรือแพงกว่าและแย่กว่าอย่างในกรณีนี้ จึงต้องดูเครื่องหมายของผลต่างต้นทุนและผลต่างสุขภาพก่อนดูอัตราส่วน
ขั้นต่อไป: เทียบแต่ละแผนกับแผนข้างเคียง
เมื่อตัด D ออก ให้เรียงแผนที่เหลือตามสุขภาพ คือ A (0), B (0.08) และ C (0.18) แล้วเทียบแต่ละแผนกับแผนที่อยู่ถัดลงมาในด้านสุขภาพ ไม่ใช่กับ A ขั้นจาก A ไป B ใช้ 8,000 บาทเพื่อได้ 0.08 QALY คิดเป็น 100,000 บาทต่อ QALY ส่วนขั้นจาก B ไป C ใช้อีก 8,000 บาทเพื่อได้ 0.10 QALY คิดเป็นเพียง 80,000 บาทต่อ QALY
ขั้นที่สองซื้อสุขภาพได้ถูกกว่าขั้นแรก กองทุนที่ยอมจ่าย 100,000 บาทต่อ QALY เพื่อไปถึง B ย่อมยินดีจ่าย 80,000 บาทต่อ QALY เพื่อไปต่อถึง C ดังนั้น B จึงเป็นจุดหยุดที่ไม่ดี
ลองนึกว่าทีมแบ่งผู้ป่วยที่คล้ายกันออกเป็นสองกลุ่ม กลุ่มหนึ่งได้ C ที่เหลือได้ A เรียกว่าส่วนผสมของ A กับ C ส่วนผสมแบบนี้ปรับสัดส่วนให้สุขภาพเฉลี่ยของกลุ่มเท่ากับของ B ได้ การ์ดด้านล่างคำนวณว่าส่วนผสมนี้มีต้นทุนเท่าใด
ให้ได้สุขภาพเท่าแผน B ด้วยส่วนผสมของ A กับ C
-
สัดส่วนผู้ป่วยที่ได้ C
\[ \frac{0.08}{0.18} \times 100 = 44.44 \]
ให้ C แก่ผู้ป่วยในสัดส่วนที่พอดีให้สุขภาพเฉลี่ยของกลุ่มเท่ากับ 0.08 QALY ของ B ผู้ป่วยที่ได้ C แต่ละคนได้เพิ่ม 0.18 QALY สัดส่วนที่ให้ C จึงเท่ากับ 0.08 / 0.18 คือ 44.44 คนในทุก 100 คน หรือ 44.44% และอีก 55.56% อยู่ในแผน A
-
ต้นทุนของส่วนผสม
\[ \frac{0.08}{0.18} \times 16000 = 7111.11 \]
ผู้ป่วยที่ได้ C มีต้นทุนเพิ่ม 16,000 บาท ส่วนผู้ป่วยที่อยู่ในแผน A ไม่มีต้นทุนเพิ่ม ส่วนผสมจึงมีต้นทุนเฉลี่ยต่อผู้ป่วยเท่ากับสัดส่วนเดียวกันของ 16,000 บาท
-
เทียบกับแผน B
\[ 8000 - 7111.11 = 888.89 \]
ส่วนผสมได้ 0.08 QALY เท่ากับ B ด้วยเงิน 7,111.11 บาท แทนที่จะเป็น 8,000 บาท ประหยัดได้ 888.89 บาทต่อผู้ป่วย
ผลลัพธ์: ส่วนผสมของ A กับ C ได้ 0.08 QALY เท่ากับ B โดยถูกกว่า 888.89 บาทต่อผู้ป่วย B จึงไม่ใช่แผนที่ควรเลือก
แผนที่แพ้ส่วนผสม
ดังนั้น B แพ้ แต่ไม่ได้แพ้ A หรือ C เพียงแผนเดียว B แพ้ส่วนผสมของสองแผนนั้น B ได้สุขภาพมากกว่า A และถูกกว่า C จึงไม่มีแผนใดแผนเดียวที่ครอบงำ B การแพ้ส่วนผสมของสองแผนข้างเคียงเรียกว่าการครอบงำแบบขยาย (extended dominance) ซึ่งเกิดขึ้นทุกครั้งที่ต้นทุนต่อ QALY ที่เพิ่มลดลงจากขั้นหนึ่งไปอีกขั้น อย่างในกรณีนี้ที่ลดจาก 100,000 เป็น 80,000 บาท
ส่วนผสมนี้ใช้เป็นตัวเทียบ ไม่ใช่แผนที่ห้าที่ให้เลือก ส่วนผสมนี้ตอบคำถามว่าสุขภาพเท่า B จะมีต้นทุนเท่าใด ถ้าทีมแบ่งผู้ป่วยที่คล้ายกันไปแผน A และแผน C ได้ และไม่มีผู้ป่วยคนใดได้รับการรักษาเพียงบางส่วน แม้ทีมแบ่งผู้ป่วยไปสองแผนไม่ได้ การตรวจด้วยการแปลงสุขภาพเป็นเงินในตอนท้ายของบทความนี้ก็ไม่เลือก B เลย
ตรวจสองขั้นแรกด้วย R
# Step 1: remove the plan beaten outright. Step 2: compare each remaining plan with its neighbour.
# Neighbour steps run in health order over A, B, C. Values are per patient and illustrative.
cost <- c(0, 8000, 16000, 19000)
effect <- c(0, 0.08, 0.18, 0.17)
big <- function(value) prettyNum(round(value, 2), big.mark = ",", digits = 10, scientific = FALSE)
two <- function(value) formatC(value, format = "f", digits = 2)
step_cost <- diff(cost[1:3])
step_effect <- diff(effect[1:3])
cat("Series: 270000 - 250000 =", big(270000 - 250000), "| 6.00 - 5.90 =", two(6.00 - 5.90), "\n")
cat("C against D: saves", big(cost[4] - cost[3]), "THB | gains", two(effect[3] - effect[4]), "\n")
cat("D against C:", big(cost[4] - cost[3]), "/", two(effect[4] - effect[3]), "=",
big((cost[4] - cost[3]) / (effect[4] - effect[3])), "\n")
cat("Steps A to B, B to C: cost", big(step_cost), "THB | health", two(step_effect), "\n")
cat("THB per unit of health, A to B then B to C:", big(step_cost / step_effect), "\n")
Series: 270000 - 250000 = 20,000 | 6.00 - 5.90 = 0.10
C against D: saves 3,000 THB | gains 0.01
D against C: 3,000 / -0.01 = -300,000
Steps A to B, B to C: cost 8,000 8,000 THB | health 0.08 0.10
THB per unit of health, A to B then B to C: 100,000 80,000
ต้องใช้ R ≥ 4.5.2 · tibble 3.3.1 · dplyr 1.2.1 · ggplot2 4.0.3 · dampack 1.0.2.1000 · ใช้ได้กับ R 4.6.1 · ดาวน์โหลด icer-and-net-monetary-benefit-across-strategies.R
สคริปต์ฉบับเต็ม
# Four follow-up plans after a heart attack: set aside the beaten plans, then find the best buy
# แผนติดตามผู้ป่วยหลังกล้ามเนื้อหัวใจขาดเลือดสี่แบบ: กันแผนที่แพ้ออก แล้วหาแผนที่คุ้มที่สุด
# 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)
# dampack 1.0.2.1000 (stable)
# install.packages(c("tibble", "dplyr", "ggplot2", "dampack"))
# update.packages(oldPkgs = c("tibble", "dplyr", "ggplot2", "dampack"))
# remotes::install_version("tibble", "3.3.1")
# remotes::install_version("dplyr", "1.2.1")
# remotes::install_version("ggplot2", "4.0.3")
# remotes::install_version("dampack", "1.0.2.1000")
library(tibble) # Write the four plans as an explicit input table.
library(dplyr) # Add each plan's net gain to the table.
library(ggplot2) # Display the plans without saving files.
library(dampack) # Cross-check which plans drop out with an independent routine.
stopifnot(getRversion() >= "4.5.2")
#%%@note 1. The four plans, as extra cost and extra health over plan A
# Order A, B, C, D. Cost is THB per patient and health is quality-weighted years per patient.
# All values are illustrative, not cardiac rehabilitation evidence or a payer's rule.
# เรียงเป็น A, B, C, D ต้นทุนเป็นบาทต่อผู้ป่วย สุขภาพเป็นปีที่ถ่วงด้วยคุณภาพต่อผู้ป่วย
# ค่าทั้งหมดเป็นตัวอย่างสมมติ ไม่ใช่หลักฐานเรื่องการฟื้นฟูหัวใจหรือเกณฑ์ของผู้จ่าย
cost <- c(0, 8000, 16000, 19000)
effect <- c(0, 0.08, 0.18, 0.17)
lambda <- 160000
strategy <- c("A", "B", "C", "D")
big <- function(value) prettyNum(round(value, 2), big.mark = ",", digits = 10, scientific = FALSE)
two <- function(value) formatC(value, format = "f", digits = 2)
plans <- tibble::tibble(strategy = strategy, cost = cost, effect = effect)
#%%@note 2. Set aside the plan beaten outright, then compare neighbours
# D costs more than C and gives less health, so it leaves first. The steps then run A to B to C.
# D แพงกว่า C และได้สุขภาพน้อยกว่า จึงออกก่อน แล้วจึงไล่ขั้นจาก A ไป B ไป C
stopifnot(cost[4] > cost[3], effect[4] < effect[3])
step_cost <- diff(cost[1:3])
step_effect <- diff(effect[1:3])
stopifnot(step_cost[1] / step_effect[1] > step_cost[2] / step_effect[2])
checked <- dampack::calculate_icers(cost = cost, effect = effect, strategies = strategy)
stopifnot(identical(checked$Status[match(strategy, checked$Strategy)], c("ND", "ED", "ND", "D")))
#%%@note 3. Price the mix of A and C, then the step from A to C
# The mix gives C to a share of patients and A to the rest, so its average health equals B's.
# ส่วนผสมให้ C แก่ผู้ป่วยส่วนหนึ่งและให้ A แก่ที่เหลือ สุขภาพเฉลี่ยจึงเท่ากับของ B
share_c <- (effect[2] - effect[1]) / (effect[3] - effect[1])
mix_cost <- (1 - share_c) * cost[1] + share_c * cost[3]
mix_effect <- (1 - share_c) * effect[1] + share_c * effect[3]
ratio <- (cost[3] - cost[1]) / (effect[3] - effect[1])
stopifnot(mix_cost < cost[2], abs(mix_effect - effect[2]) < 1e-9, ratio < lambda)
#%%@note 4. Value health at the threshold and subtract cost
# Each plan's extra health is priced at the threshold, then its extra cost is taken away.
# ตีค่าสุขภาพที่เพิ่มของแต่ละแผนด้วยเกณฑ์ แล้วหักต้นทุนที่เพิ่มออก
valued <- lambda * effect
net <- valued - cost
plans <- plans |>
dplyr::mutate(net = lambda * effect - cost)
stopifnot(strategy[which.max(net)] == "C", all(abs(plans$net - net) < 1e-9))
#%%@note 5. Display the four plans
# Plot extra cost against extra health per patient, with the line from A to C. No file is saved.
# แสดงต้นทุนที่เพิ่มเทียบกับสุขภาพที่เพิ่มต่อผู้ป่วย พร้อมเส้นจาก A ไป C โดยไม่บันทึกไฟล์ภาพ
print(ggplot2::ggplot(plans, ggplot2::aes(x = effect, y = cost, label = strategy)) +
ggplot2::geom_point() + ggplot2::geom_text(nudge_y = 700) +
ggplot2::geom_line(data = dplyr::filter(plans, strategy %in% c("A", "C"))) +
ggplot2::labs(x = "Extra QALYs per patient", y = "Extra cost per patient (THB)"))
#%%@note 6. Numbers the article quotes
# Print the short boxes' lines in their reading order.
# พิมพ์ผลลัพธ์ตรงกับกล่องโค้ดสั้นตามลำดับในบทความ
cat("10 years at 0.70 =", formatC(10 * 0.70, format = "f", digits = 1),
"| full health over those years adds", formatC(10 * 0.30, format = "f", digits = 1), "\n")
cat("Series example: 150000 / 1.00 =", big(150000 / 1.00), "THB | threshold:", big(lambda), "\n")
cat("Each plan against A, THB per unit of health (B, C, D):", big(cost[-1] / effect[-1]), "\n")
cat("Below the threshold (B, C, D):", cost[-1] / effect[-1] < lambda, "\n")
cat("Series: 270000 - 250000 =", big(270000 - 250000), "| 6.00 - 5.90 =", two(6.00 - 5.90), "\n")
cat("C against D: saves", big(cost[4] - cost[3]), "THB | gains", two(effect[3] - effect[4]), "\n")
cat("D against C:", big(cost[4] - cost[3]), "/", two(effect[4] - effect[3]), "=",
big((cost[4] - cost[3]) / (effect[4] - effect[3])), "\n")
cat("Steps A to B, B to C: cost", big(step_cost), "THB | health", two(step_effect), "\n")
cat("THB per unit of health, A to B then B to C:", big(step_cost / step_effect), "\n")
cat("Share given C | given A:", paste0(two(100 * c(share_c, 1 - share_c)), "%"), "\n")
cat("Per 100 patients, on C:", two(100 * share_c), "\n")
cat("Health of the mix:", two(mix_effect), "| plan B:", two(effect[2]), "\n")
cat("Cost of the mix:", big(mix_cost), "THB | plan B:", big(cost[2]), "THB | saving:",
big(cost[2] - mix_cost), "THB\n")
cat("A to C: cost", big(cost[3] - cost[1]), "THB | health", two(effect[3] - effect[1]), "\n")
cat("A to C, THB per unit of health:", big(ratio), "\n")
cat("Below the threshold of", big(lambda), "THB:", ratio < lambda, "\n")
cat("Series example: 160000 x 1.00 - 150000 =", big(160000 * 1.00 - 150000), "THB\n")
cat("Health valued at the threshold (A, B, C, D):", big(valued), "THB\n")
cat("Net gain over A (A, B, C, D):", big(net), "THB | largest:", strategy[which.max(net)], "\n")
cat("A and C tie at", big(cost[3] / effect[3]), "| B beats A above", big(cost[2] / effect[2]),
"| B beats C below", big((cost[3] - cost[2]) / (effect[3] - effect[2])), "\n")
คำนวณต้นทุนของส่วนผสมด้วย R
# Price a mix of plans A and C that gives the patient group the same average health as plan B.
cost <- c(0, 8000, 16000, 19000)
effect <- c(0, 0.08, 0.18, 0.17)
big <- function(value) prettyNum(round(value, 2), big.mark = ",", digits = 10, scientific = FALSE)
two <- function(value) formatC(value, format = "f", digits = 2)
share_c <- (effect[2] - effect[1]) / (effect[3] - effect[1])
mix_cost <- (1 - share_c) * cost[1] + share_c * cost[3]
mix_effect <- (1 - share_c) * effect[1] + share_c * effect[3]
cat("Share given C | given A:", paste0(two(100 * c(share_c, 1 - share_c)), "%"), "\n")
cat("Per 100 patients, on C:", two(100 * share_c), "\n")
cat("Health of the mix:", two(mix_effect), "| plan B:", two(effect[2]), "\n")
cat("Cost of the mix:", big(mix_cost), "THB | plan B:", big(cost[2]), "THB | saving:",
big(cost[2] - mix_cost), "THB\n")
Share given C | given A: 44.44% 55.56%
Per 100 patients, on C: 44.44
Health of the mix: 0.08 | plan B: 0.08
Cost of the mix: 7,111.11 THB | plan B: 8,000 THB | saving: 888.89 THB
ต้องใช้ R ≥ 4.5.2 · tibble 3.3.1 · dplyr 1.2.1 · ggplot2 4.0.3 · dampack 1.0.2.1000 · ใช้ได้กับ R 4.6.1 · ดาวน์โหลด icer-and-net-monetary-benefit-across-strategies.R
สคริปต์ฉบับเต็ม
# Four follow-up plans after a heart attack: set aside the beaten plans, then find the best buy
# แผนติดตามผู้ป่วยหลังกล้ามเนื้อหัวใจขาดเลือดสี่แบบ: กันแผนที่แพ้ออก แล้วหาแผนที่คุ้มที่สุด
# 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)
# dampack 1.0.2.1000 (stable)
# install.packages(c("tibble", "dplyr", "ggplot2", "dampack"))
# update.packages(oldPkgs = c("tibble", "dplyr", "ggplot2", "dampack"))
# remotes::install_version("tibble", "3.3.1")
# remotes::install_version("dplyr", "1.2.1")
# remotes::install_version("ggplot2", "4.0.3")
# remotes::install_version("dampack", "1.0.2.1000")
library(tibble) # Write the four plans as an explicit input table.
library(dplyr) # Add each plan's net gain to the table.
library(ggplot2) # Display the plans without saving files.
library(dampack) # Cross-check which plans drop out with an independent routine.
stopifnot(getRversion() >= "4.5.2")
#%%@note 1. The four plans, as extra cost and extra health over plan A
# Order A, B, C, D. Cost is THB per patient and health is quality-weighted years per patient.
# All values are illustrative, not cardiac rehabilitation evidence or a payer's rule.
# เรียงเป็น A, B, C, D ต้นทุนเป็นบาทต่อผู้ป่วย สุขภาพเป็นปีที่ถ่วงด้วยคุณภาพต่อผู้ป่วย
# ค่าทั้งหมดเป็นตัวอย่างสมมติ ไม่ใช่หลักฐานเรื่องการฟื้นฟูหัวใจหรือเกณฑ์ของผู้จ่าย
cost <- c(0, 8000, 16000, 19000)
effect <- c(0, 0.08, 0.18, 0.17)
lambda <- 160000
strategy <- c("A", "B", "C", "D")
big <- function(value) prettyNum(round(value, 2), big.mark = ",", digits = 10, scientific = FALSE)
two <- function(value) formatC(value, format = "f", digits = 2)
plans <- tibble::tibble(strategy = strategy, cost = cost, effect = effect)
#%%@note 2. Set aside the plan beaten outright, then compare neighbours
# D costs more than C and gives less health, so it leaves first. The steps then run A to B to C.
# D แพงกว่า C และได้สุขภาพน้อยกว่า จึงออกก่อน แล้วจึงไล่ขั้นจาก A ไป B ไป C
stopifnot(cost[4] > cost[3], effect[4] < effect[3])
step_cost <- diff(cost[1:3])
step_effect <- diff(effect[1:3])
stopifnot(step_cost[1] / step_effect[1] > step_cost[2] / step_effect[2])
checked <- dampack::calculate_icers(cost = cost, effect = effect, strategies = strategy)
stopifnot(identical(checked$Status[match(strategy, checked$Strategy)], c("ND", "ED", "ND", "D")))
#%%@note 3. Price the mix of A and C, then the step from A to C
# The mix gives C to a share of patients and A to the rest, so its average health equals B's.
# ส่วนผสมให้ C แก่ผู้ป่วยส่วนหนึ่งและให้ A แก่ที่เหลือ สุขภาพเฉลี่ยจึงเท่ากับของ B
share_c <- (effect[2] - effect[1]) / (effect[3] - effect[1])
mix_cost <- (1 - share_c) * cost[1] + share_c * cost[3]
mix_effect <- (1 - share_c) * effect[1] + share_c * effect[3]
ratio <- (cost[3] - cost[1]) / (effect[3] - effect[1])
stopifnot(mix_cost < cost[2], abs(mix_effect - effect[2]) < 1e-9, ratio < lambda)
#%%@note 4. Value health at the threshold and subtract cost
# Each plan's extra health is priced at the threshold, then its extra cost is taken away.
# ตีค่าสุขภาพที่เพิ่มของแต่ละแผนด้วยเกณฑ์ แล้วหักต้นทุนที่เพิ่มออก
valued <- lambda * effect
net <- valued - cost
plans <- plans |>
dplyr::mutate(net = lambda * effect - cost)
stopifnot(strategy[which.max(net)] == "C", all(abs(plans$net - net) < 1e-9))
#%%@note 5. Display the four plans
# Plot extra cost against extra health per patient, with the line from A to C. No file is saved.
# แสดงต้นทุนที่เพิ่มเทียบกับสุขภาพที่เพิ่มต่อผู้ป่วย พร้อมเส้นจาก A ไป C โดยไม่บันทึกไฟล์ภาพ
print(ggplot2::ggplot(plans, ggplot2::aes(x = effect, y = cost, label = strategy)) +
ggplot2::geom_point() + ggplot2::geom_text(nudge_y = 700) +
ggplot2::geom_line(data = dplyr::filter(plans, strategy %in% c("A", "C"))) +
ggplot2::labs(x = "Extra QALYs per patient", y = "Extra cost per patient (THB)"))
#%%@note 6. Numbers the article quotes
# Print the short boxes' lines in their reading order.
# พิมพ์ผลลัพธ์ตรงกับกล่องโค้ดสั้นตามลำดับในบทความ
cat("10 years at 0.70 =", formatC(10 * 0.70, format = "f", digits = 1),
"| full health over those years adds", formatC(10 * 0.30, format = "f", digits = 1), "\n")
cat("Series example: 150000 / 1.00 =", big(150000 / 1.00), "THB | threshold:", big(lambda), "\n")
cat("Each plan against A, THB per unit of health (B, C, D):", big(cost[-1] / effect[-1]), "\n")
cat("Below the threshold (B, C, D):", cost[-1] / effect[-1] < lambda, "\n")
cat("Series: 270000 - 250000 =", big(270000 - 250000), "| 6.00 - 5.90 =", two(6.00 - 5.90), "\n")
cat("C against D: saves", big(cost[4] - cost[3]), "THB | gains", two(effect[3] - effect[4]), "\n")
cat("D against C:", big(cost[4] - cost[3]), "/", two(effect[4] - effect[3]), "=",
big((cost[4] - cost[3]) / (effect[4] - effect[3])), "\n")
cat("Steps A to B, B to C: cost", big(step_cost), "THB | health", two(step_effect), "\n")
cat("THB per unit of health, A to B then B to C:", big(step_cost / step_effect), "\n")
cat("Share given C | given A:", paste0(two(100 * c(share_c, 1 - share_c)), "%"), "\n")
cat("Per 100 patients, on C:", two(100 * share_c), "\n")
cat("Health of the mix:", two(mix_effect), "| plan B:", two(effect[2]), "\n")
cat("Cost of the mix:", big(mix_cost), "THB | plan B:", big(cost[2]), "THB | saving:",
big(cost[2] - mix_cost), "THB\n")
cat("A to C: cost", big(cost[3] - cost[1]), "THB | health", two(effect[3] - effect[1]), "\n")
cat("A to C, THB per unit of health:", big(ratio), "\n")
cat("Below the threshold of", big(lambda), "THB:", ratio < lambda, "\n")
cat("Series example: 160000 x 1.00 - 150000 =", big(160000 * 1.00 - 150000), "THB\n")
cat("Health valued at the threshold (A, B, C, D):", big(valued), "THB\n")
cat("Net gain over A (A, B, C, D):", big(net), "THB | largest:", strategy[which.max(net)], "\n")
cat("A and C tie at", big(cost[3] / effect[3]), "| B beats A above", big(cost[2] / effect[2]),
"| B beats C below", big((cost[3] - cost[2]) / (effect[3] - effect[2])), "\n")
จากนั้น: ไล่ตามเส้นประสิทธิภาพ
กัน B ออกด้วย แล้วเทียบ C กับ A โดยตรง ขั้นนี้ใช้ 16,000 บาทเพื่อได้ 0.18 QALY คิดเป็น 88,888.89 บาทต่อ QALY ซึ่งต่ำกว่า 160,000 บาท ทีมจึงควรขยับจาก A ไปถึง C
ลองวาดแต่ละแผนเป็นจุด โดยสุขภาพที่เพิ่มอยู่ทางขวาและต้นทุนที่เพิ่มอยู่ด้านบน ภาพนี้คือระนาบต้นทุนประสิทธิผล เส้นจาก A ไป C เป็นวิธีที่ถูกที่สุดในการซื้อสุขภาพแต่ละระดับด้วยแผนเหล่านี้ เพราะไม่มีแผนใดอยู่ใต้เส้นนี้ เส้นนี้เรียกว่าเส้นประสิทธิภาพ (efficient frontier) และมีเพียงการขยับไปตามเส้นนี้ที่ต้องคำนวณต้นทุนต่อ QALY ที่เพิ่ม
การอ่านเส้นประสิทธิภาพไม่ยาก เริ่มจากแผนที่ถูกที่สุด แล้วขยับตามเส้นไปเรื่อย ๆ ตราบที่แต่ละขั้นมีต้นทุนต่อ QALY ที่เพิ่มต่ำกว่าเกณฑ์ ในกรณีนี้มีขั้นเดียวคือ A ไป C ซึ่งใช้ 88,888.89 บาทต่อ QALY ต่ำกว่าเกณฑ์ 160,000 บาทต่อ QALY คำตอบจึงเป็น C
ต้นทุนต่อ QALY ที่เพิ่มของแต่ละขั้น
| ขั้น | ต้นทุนที่เพิ่ม (บาท) | QALY ที่เพิ่ม | บาทต่อ QALY ที่เพิ่ม |
|---|---|---|---|
| A ไป B | 8,000 | 0.08 | 100,000 |
| B ไป C | 8,000 | 0.10 | 80,000 |
| A ไป C (เส้นประสิทธิภาพ) | 16,000 | 0.18 | 88,888.89 |
ตรวจขั้นบนเส้นประสิทธิภาพด้วย R
# Step 3: with B and D set aside, compare C directly with A and judge the step at the threshold.
cost <- c(0, 8000, 16000, 19000)
effect <- c(0, 0.08, 0.18, 0.17)
lambda <- 160000
big <- function(value) prettyNum(round(value, 2), big.mark = ",", digits = 10, scientific = FALSE)
two <- function(value) formatC(value, format = "f", digits = 2)
ratio <- (cost[3] - cost[1]) / (effect[3] - effect[1])
cat("A to C: cost", big(cost[3] - cost[1]), "THB | health", two(effect[3] - effect[1]), "\n")
cat("A to C, THB per unit of health:", big(ratio), "\n")
cat("Below the threshold of", big(lambda), "THB:", ratio < lambda, "\n")
A to C: cost 16,000 THB | health 0.18
A to C, THB per unit of health: 88,888.89
Below the threshold of 160,000 THB: TRUE
ต้องใช้ R ≥ 4.5.2 · tibble 3.3.1 · dplyr 1.2.1 · ggplot2 4.0.3 · dampack 1.0.2.1000 · ใช้ได้กับ R 4.6.1 · ดาวน์โหลด icer-and-net-monetary-benefit-across-strategies.R
สคริปต์ฉบับเต็ม
# Four follow-up plans after a heart attack: set aside the beaten plans, then find the best buy
# แผนติดตามผู้ป่วยหลังกล้ามเนื้อหัวใจขาดเลือดสี่แบบ: กันแผนที่แพ้ออก แล้วหาแผนที่คุ้มที่สุด
# 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)
# dampack 1.0.2.1000 (stable)
# install.packages(c("tibble", "dplyr", "ggplot2", "dampack"))
# update.packages(oldPkgs = c("tibble", "dplyr", "ggplot2", "dampack"))
# remotes::install_version("tibble", "3.3.1")
# remotes::install_version("dplyr", "1.2.1")
# remotes::install_version("ggplot2", "4.0.3")
# remotes::install_version("dampack", "1.0.2.1000")
library(tibble) # Write the four plans as an explicit input table.
library(dplyr) # Add each plan's net gain to the table.
library(ggplot2) # Display the plans without saving files.
library(dampack) # Cross-check which plans drop out with an independent routine.
stopifnot(getRversion() >= "4.5.2")
#%%@note 1. The four plans, as extra cost and extra health over plan A
# Order A, B, C, D. Cost is THB per patient and health is quality-weighted years per patient.
# All values are illustrative, not cardiac rehabilitation evidence or a payer's rule.
# เรียงเป็น A, B, C, D ต้นทุนเป็นบาทต่อผู้ป่วย สุขภาพเป็นปีที่ถ่วงด้วยคุณภาพต่อผู้ป่วย
# ค่าทั้งหมดเป็นตัวอย่างสมมติ ไม่ใช่หลักฐานเรื่องการฟื้นฟูหัวใจหรือเกณฑ์ของผู้จ่าย
cost <- c(0, 8000, 16000, 19000)
effect <- c(0, 0.08, 0.18, 0.17)
lambda <- 160000
strategy <- c("A", "B", "C", "D")
big <- function(value) prettyNum(round(value, 2), big.mark = ",", digits = 10, scientific = FALSE)
two <- function(value) formatC(value, format = "f", digits = 2)
plans <- tibble::tibble(strategy = strategy, cost = cost, effect = effect)
#%%@note 2. Set aside the plan beaten outright, then compare neighbours
# D costs more than C and gives less health, so it leaves first. The steps then run A to B to C.
# D แพงกว่า C และได้สุขภาพน้อยกว่า จึงออกก่อน แล้วจึงไล่ขั้นจาก A ไป B ไป C
stopifnot(cost[4] > cost[3], effect[4] < effect[3])
step_cost <- diff(cost[1:3])
step_effect <- diff(effect[1:3])
stopifnot(step_cost[1] / step_effect[1] > step_cost[2] / step_effect[2])
checked <- dampack::calculate_icers(cost = cost, effect = effect, strategies = strategy)
stopifnot(identical(checked$Status[match(strategy, checked$Strategy)], c("ND", "ED", "ND", "D")))
#%%@note 3. Price the mix of A and C, then the step from A to C
# The mix gives C to a share of patients and A to the rest, so its average health equals B's.
# ส่วนผสมให้ C แก่ผู้ป่วยส่วนหนึ่งและให้ A แก่ที่เหลือ สุขภาพเฉลี่ยจึงเท่ากับของ B
share_c <- (effect[2] - effect[1]) / (effect[3] - effect[1])
mix_cost <- (1 - share_c) * cost[1] + share_c * cost[3]
mix_effect <- (1 - share_c) * effect[1] + share_c * effect[3]
ratio <- (cost[3] - cost[1]) / (effect[3] - effect[1])
stopifnot(mix_cost < cost[2], abs(mix_effect - effect[2]) < 1e-9, ratio < lambda)
#%%@note 4. Value health at the threshold and subtract cost
# Each plan's extra health is priced at the threshold, then its extra cost is taken away.
# ตีค่าสุขภาพที่เพิ่มของแต่ละแผนด้วยเกณฑ์ แล้วหักต้นทุนที่เพิ่มออก
valued <- lambda * effect
net <- valued - cost
plans <- plans |>
dplyr::mutate(net = lambda * effect - cost)
stopifnot(strategy[which.max(net)] == "C", all(abs(plans$net - net) < 1e-9))
#%%@note 5. Display the four plans
# Plot extra cost against extra health per patient, with the line from A to C. No file is saved.
# แสดงต้นทุนที่เพิ่มเทียบกับสุขภาพที่เพิ่มต่อผู้ป่วย พร้อมเส้นจาก A ไป C โดยไม่บันทึกไฟล์ภาพ
print(ggplot2::ggplot(plans, ggplot2::aes(x = effect, y = cost, label = strategy)) +
ggplot2::geom_point() + ggplot2::geom_text(nudge_y = 700) +
ggplot2::geom_line(data = dplyr::filter(plans, strategy %in% c("A", "C"))) +
ggplot2::labs(x = "Extra QALYs per patient", y = "Extra cost per patient (THB)"))
#%%@note 6. Numbers the article quotes
# Print the short boxes' lines in their reading order.
# พิมพ์ผลลัพธ์ตรงกับกล่องโค้ดสั้นตามลำดับในบทความ
cat("10 years at 0.70 =", formatC(10 * 0.70, format = "f", digits = 1),
"| full health over those years adds", formatC(10 * 0.30, format = "f", digits = 1), "\n")
cat("Series example: 150000 / 1.00 =", big(150000 / 1.00), "THB | threshold:", big(lambda), "\n")
cat("Each plan against A, THB per unit of health (B, C, D):", big(cost[-1] / effect[-1]), "\n")
cat("Below the threshold (B, C, D):", cost[-1] / effect[-1] < lambda, "\n")
cat("Series: 270000 - 250000 =", big(270000 - 250000), "| 6.00 - 5.90 =", two(6.00 - 5.90), "\n")
cat("C against D: saves", big(cost[4] - cost[3]), "THB | gains", two(effect[3] - effect[4]), "\n")
cat("D against C:", big(cost[4] - cost[3]), "/", two(effect[4] - effect[3]), "=",
big((cost[4] - cost[3]) / (effect[4] - effect[3])), "\n")
cat("Steps A to B, B to C: cost", big(step_cost), "THB | health", two(step_effect), "\n")
cat("THB per unit of health, A to B then B to C:", big(step_cost / step_effect), "\n")
cat("Share given C | given A:", paste0(two(100 * c(share_c, 1 - share_c)), "%"), "\n")
cat("Per 100 patients, on C:", two(100 * share_c), "\n")
cat("Health of the mix:", two(mix_effect), "| plan B:", two(effect[2]), "\n")
cat("Cost of the mix:", big(mix_cost), "THB | plan B:", big(cost[2]), "THB | saving:",
big(cost[2] - mix_cost), "THB\n")
cat("A to C: cost", big(cost[3] - cost[1]), "THB | health", two(effect[3] - effect[1]), "\n")
cat("A to C, THB per unit of health:", big(ratio), "\n")
cat("Below the threshold of", big(lambda), "THB:", ratio < lambda, "\n")
cat("Series example: 160000 x 1.00 - 150000 =", big(160000 * 1.00 - 150000), "THB\n")
cat("Health valued at the threshold (A, B, C, D):", big(valued), "THB\n")
cat("Net gain over A (A, B, C, D):", big(net), "THB | largest:", strategy[which.max(net)], "\n")
cat("A and C tie at", big(cost[3] / effect[3]), "| B beats A above", big(cost[2] / effect[2]),
"| B beats C below", big((cost[3] - cost[2]) / (effect[3] - effect[2])), "\n")
ตรวจคำตอบด้วยผลประโยชน์สุทธิในรูปตัวเงิน
อัตราส่วนอาจชวนให้เข้าใจผิดเมื่อติดลบ และคำนวณไม่ได้เมื่อสองแผนให้สุขภาพเท่ากัน เพราะตัวหารเป็นศูนย์ จึงมีเครื่องมือที่สองที่ไม่ต้องหาร คือแปลงสุขภาพเป็นเงินก่อน โดยเอา QALY ที่ได้คูณกับเกณฑ์ แล้วหักต้นทุนออก ในตัวอย่างร่วมของชุดบทความ การได้เพิ่ม 1.00 QALY ที่เกณฑ์ 160,000 บาทต่อ QALY คิดเป็นเงิน 160,000 บาท เมื่อหักต้นทุนที่เพิ่ม 150,000 บาท จะเหลือ 10,000 บาท ค่าที่เป็นบวกแปลว่าต้นทุนที่เพิ่มคุ้มที่จะจ่าย ค่านี้เรียกว่าผลประโยชน์สุทธิในรูปตัวเงิน (net monetary benefit, NMB) และเมื่อเทียบสองทางเลือกเรียกว่า NMB ส่วนเพิ่ม (incremental NMB, INMB) อ่านบทเรียนเต็มได้ที่บทความพื้นฐานเรื่องผลประโยชน์สุทธิ
สำหรับกรณีของทีมโรคหัวใจ NMB ของแต่ละแผนเมื่อเทียบกับ A ก็คือ INMB เมื่อเทียบกับการนัดตรวจตามปกติ เริ่มจากแผน B ซึ่งได้ 0.08 QALY มีค่า 0.08 × 160,000 = 12,800 บาท เมื่อหัก 8,000 บาทของแผน B ออก จะเหลือ NMB 4,800 บาท ในทำนองเดียวกัน NMB ของ C คือ 28,800 ลบ 16,000 = 12,800 บาท และของ D คือ 27,200 ลบ 19,000 = 8,200 บาท ส่วนของ A คือ 0
กฎคือเลือกแผนที่มี NMB สูงที่สุด ในที่นี้คือ C ที่ 12,800 บาทต่อผู้ป่วย ซึ่งเป็นคำตอบเดียวกับเส้นประสิทธิภาพ และจะตรงกันเสมอ เพราะแผนที่มี NMB สูงที่สุดที่เกณฑ์ใดก็ตามย่อมอยู่บนเส้นประสิทธิภาพ NMB ของ D เป็นบวก แต่ของ C สูงกว่าที่ทุกเกณฑ์ เพราะ C ถูกกว่าและได้มากกว่า
เกณฑ์เป็นตัวกำหนดว่าคำตอบเปลี่ยนที่จุดใด และจุดเปลี่ยนแต่ละจุดคือต้นทุนต่อ QALY ที่เพิ่มที่เคยเห็นมาแล้ว A กับ C มี NMB เท่ากันเมื่อ NMB ของ C เป็นศูนย์ คือเมื่อ 0.18 × เกณฑ์ เท่ากับ 16,000 บาท ซึ่งได้เกณฑ์ 16,000 / 0.18 = 88,888.89 บาทต่อ QALY ตรงกับขั้นจาก A ไป C ถ้าเกณฑ์ต่ำกว่านี้ A มี NMB สูงกว่า ถ้าเกณฑ์สูงกว่านี้ C มี NMB สูงกว่า
B ชนะ A ได้เฉพาะเมื่อ 0.08 × เกณฑ์ มากกว่า 8,000 บาท คือเมื่อเกณฑ์สูงกว่า 8,000 / 0.08 = 100,000 บาทต่อ QALY ซึ่งตรงกับขั้นจาก A ไป B และ B ชนะ C ได้เฉพาะเมื่อ 0.10 QALY ที่ C ได้เพิ่มมีค่าน้อยกว่า 8,000 บาทที่ C แพงกว่า คือเมื่อเกณฑ์ต่ำกว่า 8,000 / 0.10 = 80,000 บาทต่อ QALY ไม่มีเกณฑ์ใดที่เป็นได้ทั้งสองอย่าง B จึงไม่เคยได้อันดับหนึ่ง นี่คือการครอบงำแบบขยายเมื่อมองผ่าน NMB
ตีค่าแต่ละแผนด้วย R
# Value each plan's extra health at the threshold, subtract its extra cost, and pick the largest.
cost <- c(0, 8000, 16000, 19000)
effect <- c(0, 0.08, 0.18, 0.17)
lambda <- 160000
strategy <- c("A", "B", "C", "D")
big <- function(value) prettyNum(round(value, 2), big.mark = ",", digits = 10, scientific = FALSE)
valued <- lambda * effect
net <- valued - cost
cat("Series example: 160000 x 1.00 - 150000 =", big(160000 * 1.00 - 150000), "THB\n")
cat("Health valued at the threshold (A, B, C, D):", big(valued), "THB\n")
cat("Net gain over A (A, B, C, D):", big(net), "THB | largest:", strategy[which.max(net)], "\n")
cat("A and C tie at", big(cost[3] / effect[3]), "| B beats A above", big(cost[2] / effect[2]),
"| B beats C below", big((cost[3] - cost[2]) / (effect[3] - effect[2])), "\n")
Series example: 160000 x 1.00 - 150000 = 10,000 THB
Health valued at the threshold (A, B, C, D): 0 12,800 28,800 27,200 THB
Net gain over A (A, B, C, D): 0 4,800 12,800 8,200 THB | largest: C
A and C tie at 88,888.89 | B beats A above 100,000 | B beats C below 80,000
ต้องใช้ R ≥ 4.5.2 · tibble 3.3.1 · dplyr 1.2.1 · ggplot2 4.0.3 · dampack 1.0.2.1000 · ใช้ได้กับ R 4.6.1 · ดาวน์โหลด icer-and-net-monetary-benefit-across-strategies.R
สคริปต์ฉบับเต็ม
# Four follow-up plans after a heart attack: set aside the beaten plans, then find the best buy
# แผนติดตามผู้ป่วยหลังกล้ามเนื้อหัวใจขาดเลือดสี่แบบ: กันแผนที่แพ้ออก แล้วหาแผนที่คุ้มที่สุด
# 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)
# dampack 1.0.2.1000 (stable)
# install.packages(c("tibble", "dplyr", "ggplot2", "dampack"))
# update.packages(oldPkgs = c("tibble", "dplyr", "ggplot2", "dampack"))
# remotes::install_version("tibble", "3.3.1")
# remotes::install_version("dplyr", "1.2.1")
# remotes::install_version("ggplot2", "4.0.3")
# remotes::install_version("dampack", "1.0.2.1000")
library(tibble) # Write the four plans as an explicit input table.
library(dplyr) # Add each plan's net gain to the table.
library(ggplot2) # Display the plans without saving files.
library(dampack) # Cross-check which plans drop out with an independent routine.
stopifnot(getRversion() >= "4.5.2")
#%%@note 1. The four plans, as extra cost and extra health over plan A
# Order A, B, C, D. Cost is THB per patient and health is quality-weighted years per patient.
# All values are illustrative, not cardiac rehabilitation evidence or a payer's rule.
# เรียงเป็น A, B, C, D ต้นทุนเป็นบาทต่อผู้ป่วย สุขภาพเป็นปีที่ถ่วงด้วยคุณภาพต่อผู้ป่วย
# ค่าทั้งหมดเป็นตัวอย่างสมมติ ไม่ใช่หลักฐานเรื่องการฟื้นฟูหัวใจหรือเกณฑ์ของผู้จ่าย
cost <- c(0, 8000, 16000, 19000)
effect <- c(0, 0.08, 0.18, 0.17)
lambda <- 160000
strategy <- c("A", "B", "C", "D")
big <- function(value) prettyNum(round(value, 2), big.mark = ",", digits = 10, scientific = FALSE)
two <- function(value) formatC(value, format = "f", digits = 2)
plans <- tibble::tibble(strategy = strategy, cost = cost, effect = effect)
#%%@note 2. Set aside the plan beaten outright, then compare neighbours
# D costs more than C and gives less health, so it leaves first. The steps then run A to B to C.
# D แพงกว่า C และได้สุขภาพน้อยกว่า จึงออกก่อน แล้วจึงไล่ขั้นจาก A ไป B ไป C
stopifnot(cost[4] > cost[3], effect[4] < effect[3])
step_cost <- diff(cost[1:3])
step_effect <- diff(effect[1:3])
stopifnot(step_cost[1] / step_effect[1] > step_cost[2] / step_effect[2])
checked <- dampack::calculate_icers(cost = cost, effect = effect, strategies = strategy)
stopifnot(identical(checked$Status[match(strategy, checked$Strategy)], c("ND", "ED", "ND", "D")))
#%%@note 3. Price the mix of A and C, then the step from A to C
# The mix gives C to a share of patients and A to the rest, so its average health equals B's.
# ส่วนผสมให้ C แก่ผู้ป่วยส่วนหนึ่งและให้ A แก่ที่เหลือ สุขภาพเฉลี่ยจึงเท่ากับของ B
share_c <- (effect[2] - effect[1]) / (effect[3] - effect[1])
mix_cost <- (1 - share_c) * cost[1] + share_c * cost[3]
mix_effect <- (1 - share_c) * effect[1] + share_c * effect[3]
ratio <- (cost[3] - cost[1]) / (effect[3] - effect[1])
stopifnot(mix_cost < cost[2], abs(mix_effect - effect[2]) < 1e-9, ratio < lambda)
#%%@note 4. Value health at the threshold and subtract cost
# Each plan's extra health is priced at the threshold, then its extra cost is taken away.
# ตีค่าสุขภาพที่เพิ่มของแต่ละแผนด้วยเกณฑ์ แล้วหักต้นทุนที่เพิ่มออก
valued <- lambda * effect
net <- valued - cost
plans <- plans |>
dplyr::mutate(net = lambda * effect - cost)
stopifnot(strategy[which.max(net)] == "C", all(abs(plans$net - net) < 1e-9))
#%%@note 5. Display the four plans
# Plot extra cost against extra health per patient, with the line from A to C. No file is saved.
# แสดงต้นทุนที่เพิ่มเทียบกับสุขภาพที่เพิ่มต่อผู้ป่วย พร้อมเส้นจาก A ไป C โดยไม่บันทึกไฟล์ภาพ
print(ggplot2::ggplot(plans, ggplot2::aes(x = effect, y = cost, label = strategy)) +
ggplot2::geom_point() + ggplot2::geom_text(nudge_y = 700) +
ggplot2::geom_line(data = dplyr::filter(plans, strategy %in% c("A", "C"))) +
ggplot2::labs(x = "Extra QALYs per patient", y = "Extra cost per patient (THB)"))
#%%@note 6. Numbers the article quotes
# Print the short boxes' lines in their reading order.
# พิมพ์ผลลัพธ์ตรงกับกล่องโค้ดสั้นตามลำดับในบทความ
cat("10 years at 0.70 =", formatC(10 * 0.70, format = "f", digits = 1),
"| full health over those years adds", formatC(10 * 0.30, format = "f", digits = 1), "\n")
cat("Series example: 150000 / 1.00 =", big(150000 / 1.00), "THB | threshold:", big(lambda), "\n")
cat("Each plan against A, THB per unit of health (B, C, D):", big(cost[-1] / effect[-1]), "\n")
cat("Below the threshold (B, C, D):", cost[-1] / effect[-1] < lambda, "\n")
cat("Series: 270000 - 250000 =", big(270000 - 250000), "| 6.00 - 5.90 =", two(6.00 - 5.90), "\n")
cat("C against D: saves", big(cost[4] - cost[3]), "THB | gains", two(effect[3] - effect[4]), "\n")
cat("D against C:", big(cost[4] - cost[3]), "/", two(effect[4] - effect[3]), "=",
big((cost[4] - cost[3]) / (effect[4] - effect[3])), "\n")
cat("Steps A to B, B to C: cost", big(step_cost), "THB | health", two(step_effect), "\n")
cat("THB per unit of health, A to B then B to C:", big(step_cost / step_effect), "\n")
cat("Share given C | given A:", paste0(two(100 * c(share_c, 1 - share_c)), "%"), "\n")
cat("Per 100 patients, on C:", two(100 * share_c), "\n")
cat("Health of the mix:", two(mix_effect), "| plan B:", two(effect[2]), "\n")
cat("Cost of the mix:", big(mix_cost), "THB | plan B:", big(cost[2]), "THB | saving:",
big(cost[2] - mix_cost), "THB\n")
cat("A to C: cost", big(cost[3] - cost[1]), "THB | health", two(effect[3] - effect[1]), "\n")
cat("A to C, THB per unit of health:", big(ratio), "\n")
cat("Below the threshold of", big(lambda), "THB:", ratio < lambda, "\n")
cat("Series example: 160000 x 1.00 - 150000 =", big(160000 * 1.00 - 150000), "THB\n")
cat("Health valued at the threshold (A, B, C, D):", big(valued), "THB\n")
cat("Net gain over A (A, B, C, D):", big(net), "THB | largest:", strategy[which.max(net)], "\n")
cat("A and C tie at", big(cost[3] / effect[3]), "| B beats A above", big(cost[2] / effect[2]),
"| B beats C below", big((cost[3] - cost[2]) / (effect[3] - effect[2])), "\n")
สิ่งที่คำตอบนี้ไม่ได้บอก
การเปรียบเทียบนี้ว่าด้วยความคุ้มค่าต่อผู้ป่วยหนึ่งคน ไม่ได้บอกว่ากองทุนมีเงินพอจ่ายแผน C ให้ผู้ป่วยทุกคนในปีนี้หรือไม่ ซึ่งเป็นคำถามด้านงบประมาณที่มีบทความของตัวเองในชุดนี้
ข้อมูลนำเข้าทุกค่าในที่นี้เป็นค่าประมาณที่ดีที่สุดเพียงค่าเดียว เส้นประสิทธิภาพจึงไม่ได้บอกว่าทีมมั่นใจได้แค่ไหนว่า C ดีที่สุด Briggs และคณะอธิบายวิธีส่งต่อความไม่แน่นอนของข้อมูลนำเข้าแต่ละค่าไปถึงการตัดสินใจ และบทความตอนต่อ ๆ ไปในชุดนี้จะแสดงวิธีทำ
คำศัพท์ตามที่ใช้ในบทความนี้
- Cost-effectiveness plane
- ระนาบต้นทุนประสิทธิผล: ภาพที่วาดแต่ละแผนเป็นจุด โดยสุขภาพที่เพิ่มอยู่ทางขวาและต้นทุนที่เพิ่มอยู่ด้านบน
- Dominance
- การครอบงำ: กฎที่ตัดแผนออกเมื่อมีอีกแผนที่ถูกกว่าและให้สุขภาพไม่น้อยกว่า
- Strict dominance
- การครอบงำแบบเด็ดขาด: แผนหนึ่งแพงกว่าและได้สุขภาพน้อยกว่าอีกแผน อย่าง D เมื่อเทียบกับ C จึงถูกกันออกเป็นอันดับแรก
- Extended dominance
- การครอบงำแบบขยาย: ส่วนผสมของสองแผนข้างเคียงได้สุขภาพเท่าแผนหนึ่งด้วยเงินที่น้อยกว่า อย่างส่วนผสม A-C ที่ชนะ B
- Efficient frontier
- เส้นประสิทธิภาพ: เส้นที่ผ่านแผนซึ่งซื้อสุขภาพแต่ละระดับได้ถูกที่สุด ในที่นี้คือ A และ C
- Threshold
- เกณฑ์: เงินสูงสุดที่กองทุนยอมจ่ายต่อหนึ่ง QALY ในที่นี้คือ 160,000 บาทซึ่งเป็นค่าสมมติ
- Net monetary benefit (NMB)
- ผลประโยชน์สุทธิในรูปตัวเงิน: สุขภาพที่ตีค่าด้วยเกณฑ์ลบด้วยต้นทุน แผนที่มี NMB สูงที่สุดคือแผนที่เลือก
เชื่อมกับบทความพื้นฐาน
บทความพื้นฐานเรื่องICER การครอบงำ และเกณฑ์ ว่าด้วยการเปรียบเทียบทางเลือกทีละสองทาง บทความนี้ขยายไปสู่หลายทางเลือก ส่วนบทความเรื่องการประเมินเทคโนโลยีระยะแรกและการกำหนดเพดานราคาใช้เกณฑ์เดียวกันเพื่อถามว่าแผนใหม่ตั้งราคาได้สูงสุดเท่าใด
ลองใช้ในแอป
เปิดแอปการประเมินทางเศรษฐศาสตร์ของเราเพื่อลองเปลี่ยนค่าข้อมูลนำเข้าและดูผลลัพธ์เปลี่ยนตาม ต้องเข้าสู่ระบบและใช้แผน Pro หรือ Max
แอปเริ่มจากค่าตัวอย่างของแอปเอง ตัวเลขในแอปจึงไม่ตรงกับบทความนี้
เอกสารอ้างอิง
- Michael F. Drummond, Mark J. Sculpher, Karl Claxton, Greg L. Stoddart, George W. Torrance. Methods for the Economic Evaluation of Health Care Programmes. Oxford University Press; 2015. ISBN 9780199665884. https://openlibrary.org/isbn/9780199665884
- 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
- Briggs Andrew H., Weinstein Milton C., Fenwick Elisabeth A.L., Karnon Jonathan, Sculpher Mark J., Paltiel A. David. Model Parameter Estimation and Uncertainty: A Report of the ISPOR-SMDM Modeling Good Research Practices Task Force-6. Value in Health. 2012;15(6):835-842. doi:10.1016/j.jval.2012.04.014. https://doi.org/10.1016/j.jval.2012.04.014
ลำดับการเรียนในชุดนี้
- คู่มือชุดบทความการสร้างแบบจำลองเศรษฐศาสตร์สุขภาพ: จากหลักฐานสู่การตัดสินใจ
- การเลือกแบบจำลองเพื่อการตัดสินใจ: ให้เส้นทางทางคลินิกกำหนดโครงสร้าง
- ข้อมูลนำเข้าของแบบจำลองที่ตรวจสอบได้: สร้างตารางพารามิเตอร์ที่สืบย้อนถึงที่มา
- การค้นหาข้อมูลนำเข้าของแบบจำลองจากวรรณกรรม: เลือกค่าประมาณให้ตรงกับคำถาม
- อัตรา ความน่าจะเป็น และความน่าจะเป็นของการเปลี่ยนสถานะ: คำนวณโดยไม่หลงหน่วยเวลา
- สร้างแผนภูมิต้นไม้การตัดสินใจทีละขั้น: ตามรอยผลลัพธ์ ต้นทุน และสุขภาพ
- สร้างแบบจำลองมาร์คอฟแบบกลุ่มประชากรทีละขั้น: ติดตามประชากรผ่านเวลา
- การวิเคราะห์ผลกระทบด้านงบประมาณในทางปฏิบัติ: นับคนให้ชัดก่อนคำนวณเงิน
- ICER และผลประโยชน์สุทธิในรูปตัวเงินเมื่อมีหลายทางเลือก: หาขอบเขตทางเลือกที่มีประสิทธิภาพ (บทความนี้)
- การวิเคราะห์ความไวแบบอาศัยความน่าจะเป็น: จากการแจกแจงพารามิเตอร์สู่ CEAC
- การประเมินความสมเหตุสมผลและตรวจสอบแบบจำลอง: ทดสอบคำถาม สมการ และโค้ด
- มูลค่าคาดหมายของข้อมูลสมบูรณ์: หลักฐานที่ดีขึ้นอาจมีมูลค่าเพียงใด
ประเด็นสำคัญ
- การผ่านเกณฑ์เมื่อเทียบกับการดูแลตามปกติไม่ได้ทำให้แผนนั้นเป็นคำตอบที่ถูก B (100,000), C (88,888.89) และ D (111,764.71 บาทต่อ QALY) ผ่านทั้งหมด แต่มีเพียง C ที่คุ้มที่สุด
- กันแผนที่แพ้แผนอื่นทั้งสองด้านออก C ครอบงำ D ซึ่งแพงกว่า 3,000 บาทแต่ได้น้อยกว่า 0.01 QALY
- เรียงแผนที่เหลือตามสุขภาพ แล้วเทียบแต่ละแผนกับแผนข้างเคียง ไม่ใช่กับการดูแลตามปกติ ต้นทุนต่อ QALY ที่เพิ่มซึ่งลดลงจากขั้นหนึ่งไปขั้นถัดไป (100,000 แล้วเป็น 80,000 บาท) บอกว่ามีแผนที่แพ้ส่วนผสม
- ไล่ตามเส้นประสิทธิภาพตราบที่แต่ละขั้นมีต้นทุนต่อ QALY ที่เพิ่มต่ำกว่าเกณฑ์ A ไป C ที่ 88,888.89 บาทต่อ QALY ซึ่งต่ำกว่าเกณฑ์ 160,000 บาทต่อ QALY
- NMB สูงสุดให้คำตอบเดียวกันโดยไม่ต้องหาร คือแผน C ที่ 12,800 บาทต่อผู้ป่วย
อ่านต่อในวิกิ: อัตราส่วนต้นทุนประสิทธิผลส่วนเพิ่มและระนาบต้นทุนประสิทธิผล: ทางเลือกที่ด้อยกว่า ผลประโยชน์สุทธิ และเกณฑ์ 160,000 บาทต่อปีสุขภาวะ · การประเมินเทคโนโลยีสุขภาพระยะเริ่มต้น เพดานราคาที่คุ้มค่า และการตัดสินใจชุดสิทธิประโยชน์