การค้นหาข้อมูลนำเข้าของแบบจำลองจากวรรณกรรม: เลือกค่าประมาณให้ตรงกับคำถาม

On this page
Read the English version
บทคัดย่อ
โรงพยาบาลประจำจังหวัดแห่งหนึ่งอยากรู้ว่าการให้พยาบาลโทรติดตามผู้ป่วยหลังจำหน่ายคุ้มที่จะจ่ายหรือไม่ เวชระเบียนของโรงพยาบาลแสดงว่ามีการกลับมานอนโรงพยาบาล 200 ครั้งภายในสามเดือน จากผู้ป่วยหัวใจล้มเหลวที่จำหน่าย 1,000 คน คิดเป็นความเสี่ยง 0.20 ภายใต้การดูแลปกติ แบบจำลองยังต้องใช้ผลของการโทรติดตาม และการค้นวรรณกรรมพบการศึกษาสามเรื่องที่ต่างรายงานค่า 0.70 แต่ทั้งสามไม่ใช่ตัวเลขเดียวกัน การทดลองหนึ่งรายงานอัตราส่วนของความเสี่ยงในสามเดือน ซึ่งคูณกับ 0.20 ของโรงพยาบาลได้ทันที คือ 0.20 × 0.70 = 0.14 ผลคือมีการกลับมานอนโรงพยาบาลน้อยลง 60 ครั้งต่อผู้ป่วยจำหน่าย 1,000 คน อีกสองเรื่องรายงานอัตราส่วนของออดส์และอัตราส่วนของความเร็วที่ผู้ป่วยกลับมานอนโรงพยาบาล เมื่อแปลงภายใต้ข้อสมมติของแต่ละแบบจะลดลง 51 และ 55 ครั้ง ก่อนค้นหา ให้เขียนคำถามที่ตัวเลขต้องตอบ คือผู้ป่วยของใคร เปรียบเทียบอะไร ผลลัพธ์ใด ในช่วงเวลาเท่าใด จากนั้นตัดสินแต่ละการศึกษาสามด้าน คือการศึกษาน่าเชื่อถือไหม เข้ากับผู้ป่วยของเราไหม และต้องสมมติอะไรบ้างเพื่อแปลงค่า
โรงพยาบาลเดียว คำถามเดียว การศึกษาสามเรื่อง
โรงพยาบาลประจำจังหวัดแห่งหนึ่งจำหน่ายผู้ป่วยหัวใจล้มเหลวราว 1,000 คนต่อปี เวชระเบียนแสดงว่า 200 คนในจำนวนนี้กลับมานอนโรงพยาบาลแบบฉุกเฉินภายในสามเดือน คิดเป็นความเสี่ยง 0.20 ภายใต้การดูแลปกติ ทีมอายุรกรรมหัวใจเสนอให้พยาบาลโทรติดตามผู้ป่วยในช่วงสัปดาห์แรก ๆ หลังจำหน่าย คณะกรรมการบริหารโรงพยาบาลต้องการแบบจำลองก่อนตัดสินใจจ่ายค่าเวลาของพยาบาล
แบบจำลองเริ่มอย่างง่าย ผู้ป่วยที่จำหน่ายแต่ละคนไปตามกิ่งใดกิ่งหนึ่งในสองกิ่ง คือกลับมานอนโรงพยาบาลภายในสามเดือน หรือไม่กลับมา ภายใต้การดูแลปกติ กิ่งที่กลับมานอนโรงพยาบาลมีผู้ป่วย 0.20 ของทั้งหมด เมื่อมีการโทรติดตาม สัดส่วนนี้จะเล็กลง และสัดส่วนนั้นคือตัวเลขที่บทความนี้ตามหา
เพื่อนร่วมงานค้นวรรณกรรมแล้วกลับมาพร้อมข่าวดี คือพบการศึกษาสามเรื่อง และทุกเรื่องรายงานค่า 0.70 สำหรับการติดตามโดยพยาบาล จึงชวนให้พิมพ์ 0.70 ลงในแบบจำลองแล้วไปต่อ แต่ 0.70 ทั้งสามค่ามีความหมายต่างกัน และมีเพียงค่าเดียวที่คูณกับ 0.20 ของโรงพยาบาลได้ตามที่เป็นอยู่
เขียนคำถามก่อนค้นหา
ตัวเลขที่แบบจำลองต้องการมีสี่ส่วน ส่วนแรก ผู้ป่วยของใคร คือผู้ใหญ่ที่เป็นหัวใจล้มเหลวซึ่งจำหน่ายจากโรงพยาบาลนี้ ส่วนที่สอง เปรียบเทียบอะไร คือการโทรติดตามโดยพยาบาลเทียบกับการดูแลปกติ ส่วนที่สาม ผลลัพธ์ใด คือการกลับมานอนโรงพยาบาลแบบฉุกเฉิน ส่วนที่สี่ ในช่วงเวลาเท่าใด คือภายในสามเดือน โดยนับเป็นสัดส่วนของผู้ป่วย ซึ่งก็คือความเสี่ยง
เมื่อเขียนสี่ส่วนนี้ลงไป จะได้คำถามของพารามิเตอร์ (parameter question) คือปริมาณที่ระบุให้ชัดเจนครบถ้วนว่าข้อมูลนำเข้าหนึ่งตัวของแบบจำลองต้องประมาณอะไร คำถามนี้กำหนดการค้นหาต่อ: คำค้นสำหรับหัวใจล้มเหลว การจำหน่าย การโทรศัพท์หรือการติดตามโดยพยาบาล และการกลับมานอนโรงพยาบาล เชื่อมกันจนการศึกษาต้องเกี่ยวกับทั้งสี่เรื่อง
บันทึกฐานข้อมูล ข้อความค้นหาฉบับเต็ม วันที่ค้น และข้อจำกัดที่ตั้งไว้ เพื่อให้นักวิเคราะห์อีกคนค้นซ้ำแล้วพบการศึกษาชุดเดียวกัน (Briggs and colleagues)
ตั้งเกณฑ์การคัดเลือกการศึกษาก่อนอ่านผลใด ๆ ว่ารูปแบบการศึกษา การเปรียบเทียบ นิยามผลลัพธ์ และระยะเวลาติดตามแบบใดที่นับได้ ใช้เกณฑ์เดียวกันกับทุกการศึกษา และจดเหตุผลที่คัดแต่ละเรื่องออก ในการค้นของโรงพยาบาล มีการศึกษาสามเรื่องที่ผ่านเกณฑ์ และทุกเรื่องรายงานค่า 0.70
การศึกษาสามเรื่อง 0.70 สามแบบ
การทดลอง A สุ่มผู้ป่วยให้ได้รับการโทรติดตามหรือการดูแลปกติ แล้วนับการกลับมานอนโรงพยาบาลภายในสามเดือน ค่า 0.70 ของการทดลองนี้เป็น risk ratio คือความเสี่ยงของกลุ่มที่ได้รับการโทรติดตาม หารด้วยความเสี่ยงของกลุ่มที่ได้รับการดูแลปกติ ในช่วงสามเดือนเดียวกัน risk ratio คูณกับความเสี่ยงได้ ซึ่งตรงกับสิ่งที่กิ่งของแบบจำลองต้องการพอดี
การศึกษา B ใช้ข้อมูลเวชระเบียน ไม่ได้สุ่ม และรายงานอัตราส่วนออดส์ (odds ratio) จากการวิเคราะห์ถดถอย ออดส์คือจำนวนที่เกิดเหตุการณ์หารด้วยจำนวนที่ไม่เกิด อัตราส่วนออดส์คือการเปรียบเทียบออดส์ของเหตุการณ์ระหว่างสองกลุ่ม จึงห่างจากหนึ่งมากกว่า risk ratio เมื่อเหตุการณ์พบบ่อย เมื่อกลุ่มรักษาเกิดเหตุการณ์ 8 จาก 66 คน และกลุ่มควบคุม 13 จาก 60 คน อัตราส่วนออดส์คือ 0.50 ส่วน risk ratio คือ 0.56 อ่านบทเรียนเต็มได้ที่ อัตราส่วนความเสี่ยง อัตราส่วนออดส์ ผลต่างความเสี่ยง และจำนวนที่ต้องรักษา: ตารางสองคูณสองเดียว คำตอบสี่แบบ
การทดลอง C ติดตามผู้ป่วยหนึ่งปี และรายงานอัตราส่วนฮาซาร์ด (hazard ratio) จากการวิเคราะห์การอยู่รอด อัตราส่วนฮาซาร์ดคือการเปรียบเทียบความเร็วที่เหตุการณ์เกิดในแต่ละขณะ ในคนที่ยังไม่เกิดเหตุการณ์ ไม่ใช่อัตราส่วนของความเสี่ยงตลอดช่วงเวลา สมมติกลุ่มควบคุมรอดชีพ 0.60 เมื่อครบห้าปี คือหกในสิบคนยังมีชีวิต และอัตราส่วนฮาซาร์ดคือ 0.70 ความเสี่ยงที่จะเสียชีวิตภายในห้าปีจึงเป็น 40.0% ในกลุ่มควบคุม และ 30.1% ในกลุ่มที่ได้รับการรักษา คิดเป็น risk ratio 0.75 ไม่ใช่ 0.70 อ่านบทเรียนเต็มได้ที่ อัตราส่วนฮาซาร์ดไม่ใช่อัตราส่วนความเสี่ยง: ข้อสมมติความเป็นสัดส่วนของฮาซาร์ด เวลารอดชีพเฉลี่ยแบบจำกัดช่วง และข้อมูลนำเข้าแบบจำลอง
ดังนั้น 0.70 ทั้งสามค่าคืออัตราส่วนของความเสี่ยง อัตราส่วนของออดส์ และอัตราส่วนของความเร็ว มีเพียงค่าของการทดลอง A ที่คูณกับ 0.20 ของโรงพยาบาลได้ตามที่เป็นอยู่ อีกสองค่าต้องแปลงก่อน และการแปลงแต่ละแบบต้องอาศัยข้อสมมติ
ตรวจตัวอย่างทบทวนทั้งสองด้วย R
# The two foundation examples behind the recaps: one trial's counts and one five-year survival.
# Writes: nothing to disk; the results print in the console.
events <- c(treated = 8, control = 13)
patients <- c(treated = 66, control = 60)
risks <- events / patients
odds <- events / (patients - events)
control_survival <- 0.60
hazard_ratio <- 0.70
five_year_risks <- 1 - control_survival^c(1, hazard_ratio)
cat("Events, then patients, treated and control:", events, patients, "\n")
cat("Risk ratio and odds ratio:", sprintf("%.2f", c(risks[1] / risks[2], odds[1] / odds[2])), "\n")
cat("Five-year risks, control and treated:", sprintf("%.1f%%", 100 * five_year_risks), "\n")
cat("Five-year risk ratio:", sprintf("%.2f", five_year_risks[2] / five_year_risks[1]), "\n")
Events, then patients, treated and control: 8 13 66 60
Risk ratio and odds ratio: 0.56 0.50
Five-year risks, control and treated: 40.0% 30.1%
Five-year risk ratio: 0.75
ต้องใช้ R ≥ 4.5.2 · tibble 3.3.1 · dplyr 1.2.1 · ggplot2 4.0.3 · ใช้ได้กับ R 4.6.1 · ดาวน์โหลด finding-model-inputs-in-the-literature.R
สคริปต์ฉบับเต็ม
# Finding Model Inputs in the Literature: Match the Estimate to the Question
# Follow one hospital's readmission question from three candidate studies to its model input.
# ติดตามคำถามเรื่องการกลับมานอนโรงพยาบาลของโรงพยาบาลหนึ่ง จากการศึกษาสามเรื่องสู่ค่าที่แบบจำลองใช้
# 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 candidate studies and the readings as explicit tables.
library(dplyr) # Calculate the treated risk for each reading.
library(ggplot2) # Display the readings side by side 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.
# ค่าตั้งต้นทั้งหมดเป็นข้อมูลสมมติ เขียนไว้ครั้งเดียวตามลำดับที่บทความใช้
discharges <- 1000
baseline_risk <- 0.20
risk_ratio <- 0.70
baselines <- c(0.20, 0.60)
effect <- 0.70
trial_control_risk <- 0.25
events <- c(treated = 8, control = 13)
patients <- c(treated = 66, control = 60)
control_survival <- 0.60
hazard_ratio <- 0.70
#%%@note 2. Rework the two foundation examples
# One trial's counts give both ratios; one survival curve turns a rate ratio into risks.
# จำนวนจากการทดลองหนึ่งให้อัตราส่วนทั้งสองแบบ และเส้นการอยู่รอดหนึ่งเส้นแปลงอัตราส่วนเป็นความเสี่ยง
risks <- events / patients
odds <- events / (patients - events)
five_year_risks <- 1 - control_survival^c(1, hazard_ratio)
#%%@note 3. Apply the matching risk ratio to the local baseline
# Treated risk is the baseline times the ratio; the gap is the absolute reduction.
# ความเสี่ยงเมื่อมีการโทรติดตามคือความเสี่ยงพื้นฐานคูณอัตราส่วน ผลต่างคือการลดลงสัมบูรณ์
treated_risk <- baseline_risk * risk_ratio
absolute_reduction <- baseline_risk - treated_risk
per_thousand <- discharges * c(baseline_risk, treated_risk, absolute_reduction)
#%%@note 4. Read the same value through odds and through the share still free
# Each reading changes a different quantity, so each gives a different treated risk.
# แต่ละวิธีอ่านเปลี่ยนปริมาณคนละตัว จึงได้ความเสี่ยงเมื่อมีการโทรติดตามต่างกัน
base_odds <- baselines / (1 - baselines)
call_odds <- effect * base_odds
readings <- tibble::tibble(reading = rep(c("risk", "odds", "hazard"), times = 2),
baseline = rep(baselines, each = 3)) |>
dplyr::mutate(odds = effect * baseline / (1 - baseline),
treated = dplyr::case_when(reading == "risk" ~ baseline * effect,
reading == "odds" ~ odds / (1 + odds),
TRUE ~ 1 - (1 - baseline)^effect))
treated <- matrix(readings$treated, nrow = 3, dimnames = list(c("risk", "odds", "hazard"), NULL))
stopifnot(abs(treated["odds", ] - call_odds / (1 + call_odds)) < 1e-12)
shown <- sprintf("%.2f%%", 100 * treated)
#%%@note 5. Pair the trial's ratio with each baseline
# The ratio comes from the trial; the baseline should come from the hospital's own patients.
# อัตราส่วนมาจากการทดลอง ส่วนความเสี่ยงพื้นฐานควรมาจากผู้ป่วยของโรงพยาบาลเอง
baselines_compared <- c(baseline_risk, trial_control_risk)
avoided <- discharges * baselines_compared * (1 - risk_ratio)
trial_treated <- trial_control_risk * risk_ratio
#%%@note 6. Display the readings
# Plot the treated risk for each reading at both baselines; no graphics file is saved.
# แสดงความเสี่ยงเมื่อมีการโทรติดตามของแต่ละวิธีอ่านที่ความเสี่ยงพื้นฐานทั้งสองค่า ไม่บันทึกไฟล์ภาพ
print(ggplot2::ggplot(readings, ggplot2::aes(x = reading, y = 100 * treated)) +
ggplot2::geom_col() + ggplot2::facet_wrap(~baseline) +
ggplot2::labs(x = "How 0.70 is read", y = "Treated risk (%)"))
#%%@note 7. Numbers the article quotes
# Print exactly the short boxes in their reading order.
# พิมพ์ผลลัพธ์ตรงกับกล่องตัวอย่างตามลำดับในบทความ
cat("Events, then patients, treated and control:", events, patients, "\n")
cat("Risk ratio and odds ratio:", sprintf("%.2f", c(risks[1] / risks[2], odds[1] / odds[2])), "\n")
cat("Five-year risks, control and treated:", sprintf("%.1f%%", 100 * five_year_risks), "\n")
cat("Five-year risk ratio:", sprintf("%.2f", five_year_risks[2] / five_year_risks[1]), "\n")
cat("Treated risk as a share:", treated_risk, "\n")
cat("Treated risk (%):", round(100 * treated_risk, 2), "\n")
cat("Absolute reduction (percentage points):", round(100 * absolute_reduction, 2), "\n")
cat("Per 1,000 discharges, usual care, programme, avoided:", round(per_thousand), "\n")
cat("Odds at 0.20: usual, calls, calls + one:", base_odds[1], call_odds[1], 1 + call_odds[1], "\n")
cat("Still free at 0.20, usual, hazard:", round(1 - c(baselines[1], treated[3, 1]), 3), "\n")
cat("Treated risk at 0.20 read as risk, odds, hazard ratio:", shown[1:3], "\n")
cat("Avoided per 1,000 at 0.20:", round(1000 * (baselines[1] - treated[, 1])), "\n")
cat("Treated risk at 0.60 read as risk, odds, hazard ratio:", shown[4:6], "\n")
cat("Treated risk with the trial baseline (%):", round(100 * trial_treated, 2), "\n")
cat("Avoided per 1,000, local and trial baseline:", round(avoided), "\n")
ตัวอย่างคำนวณ: 0.70 ของการทดลอง A กับผู้ป่วยของโรงพยาบาล
0.70 ของการทดลอง A เป็น risk ratio ในสามเดือน ซึ่งเป็นผลลัพธ์และเวลาเดียวกับที่แบบจำลองต้องการ ตอนนี้ให้สมมติว่าค่านี้ใช้กับผู้ป่วยของโรงพยาบาลได้ หัวข้อถัดไปจะทดสอบข้อสมมตินี้ ตัวเลขเป็นข้อมูลสมมติเพื่อการสอน และไม่มีช่วงความเชื่อมั่น ตัวอย่างนี้จึงไม่บอกอะไรเกี่ยวกับความแม่นยำ
-
เริ่มจากความเสี่ยงของโรงพยาบาลเอง
\[ \frac{200}{1000} = 0.20 \]
ภายใต้การดูแลปกติ ผู้ป่วยที่จำหน่าย 1,000 คนกลับมานอนโรงพยาบาลภายในสามเดือน 200 คน คิดเป็นความเสี่ยง 0.20
-
คูณด้วย risk ratio
\[ 0.20 \times 0.70 = 0.14 \]
เมื่อมีการโทรติดตาม ความเสี่ยงลดลงเหลือ 0.14 หรือ 14% ของผู้ป่วยที่จำหน่าย
-
ลบกันเพื่อหาประโยชน์
\[ 200 - 140 = 60 \]
ช่องว่างคือ 6 จุดร้อยละ จากผู้ป่วยจำหน่าย 1,000 คน กลับมา 140 คนแทน 200 คนภายใต้การดูแลปกติ การโทรติดตามจึงป้องกันการกลับมานอนโรงพยาบาลได้ 60 ครั้ง
ผลลัพธ์: เมื่ออ่านเป็น risk ratio ตามที่เป็นจริง 0.70 ของการทดลอง A ให้การกลับมานอนโรงพยาบาลน้อยลง 60 ครั้งต่อผู้ป่วยจำหน่าย 1,000 คน หากค่านี้ใช้กับผู้ป่วยกลุ่มนี้ได้
ตรวจตัวอย่างคำนวณด้วย R
# One hospital's heart failure discharges: readmission within 90 days, synthetic teaching numbers.
# Writes: nothing to disk; the results print in the console.
discharges <- 1000
baseline_risk <- 0.20
risk_ratio <- 0.70
treated_risk <- baseline_risk * risk_ratio
absolute_reduction <- baseline_risk - treated_risk
per_thousand <- discharges * c(baseline_risk, treated_risk, absolute_reduction)
cat("Treated risk as a share:", treated_risk, "\n")
cat("Treated risk (%):", round(100 * treated_risk, 2), "\n")
cat("Absolute reduction (percentage points):", round(100 * absolute_reduction, 2), "\n")
cat("Per 1,000 discharges, usual care, programme, avoided:", round(per_thousand), "\n")
Treated risk as a share: 0.14
Treated risk (%): 14
Absolute reduction (percentage points): 6
Per 1,000 discharges, usual care, programme, avoided: 200 140 60
ต้องใช้ R ≥ 4.5.2 · tibble 3.3.1 · dplyr 1.2.1 · ggplot2 4.0.3 · ใช้ได้กับ R 4.6.1 · ดาวน์โหลด finding-model-inputs-in-the-literature.R
สคริปต์ฉบับเต็ม
# Finding Model Inputs in the Literature: Match the Estimate to the Question
# Follow one hospital's readmission question from three candidate studies to its model input.
# ติดตามคำถามเรื่องการกลับมานอนโรงพยาบาลของโรงพยาบาลหนึ่ง จากการศึกษาสามเรื่องสู่ค่าที่แบบจำลองใช้
# 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 candidate studies and the readings as explicit tables.
library(dplyr) # Calculate the treated risk for each reading.
library(ggplot2) # Display the readings side by side 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.
# ค่าตั้งต้นทั้งหมดเป็นข้อมูลสมมติ เขียนไว้ครั้งเดียวตามลำดับที่บทความใช้
discharges <- 1000
baseline_risk <- 0.20
risk_ratio <- 0.70
baselines <- c(0.20, 0.60)
effect <- 0.70
trial_control_risk <- 0.25
events <- c(treated = 8, control = 13)
patients <- c(treated = 66, control = 60)
control_survival <- 0.60
hazard_ratio <- 0.70
#%%@note 2. Rework the two foundation examples
# One trial's counts give both ratios; one survival curve turns a rate ratio into risks.
# จำนวนจากการทดลองหนึ่งให้อัตราส่วนทั้งสองแบบ และเส้นการอยู่รอดหนึ่งเส้นแปลงอัตราส่วนเป็นความเสี่ยง
risks <- events / patients
odds <- events / (patients - events)
five_year_risks <- 1 - control_survival^c(1, hazard_ratio)
#%%@note 3. Apply the matching risk ratio to the local baseline
# Treated risk is the baseline times the ratio; the gap is the absolute reduction.
# ความเสี่ยงเมื่อมีการโทรติดตามคือความเสี่ยงพื้นฐานคูณอัตราส่วน ผลต่างคือการลดลงสัมบูรณ์
treated_risk <- baseline_risk * risk_ratio
absolute_reduction <- baseline_risk - treated_risk
per_thousand <- discharges * c(baseline_risk, treated_risk, absolute_reduction)
#%%@note 4. Read the same value through odds and through the share still free
# Each reading changes a different quantity, so each gives a different treated risk.
# แต่ละวิธีอ่านเปลี่ยนปริมาณคนละตัว จึงได้ความเสี่ยงเมื่อมีการโทรติดตามต่างกัน
base_odds <- baselines / (1 - baselines)
call_odds <- effect * base_odds
readings <- tibble::tibble(reading = rep(c("risk", "odds", "hazard"), times = 2),
baseline = rep(baselines, each = 3)) |>
dplyr::mutate(odds = effect * baseline / (1 - baseline),
treated = dplyr::case_when(reading == "risk" ~ baseline * effect,
reading == "odds" ~ odds / (1 + odds),
TRUE ~ 1 - (1 - baseline)^effect))
treated <- matrix(readings$treated, nrow = 3, dimnames = list(c("risk", "odds", "hazard"), NULL))
stopifnot(abs(treated["odds", ] - call_odds / (1 + call_odds)) < 1e-12)
shown <- sprintf("%.2f%%", 100 * treated)
#%%@note 5. Pair the trial's ratio with each baseline
# The ratio comes from the trial; the baseline should come from the hospital's own patients.
# อัตราส่วนมาจากการทดลอง ส่วนความเสี่ยงพื้นฐานควรมาจากผู้ป่วยของโรงพยาบาลเอง
baselines_compared <- c(baseline_risk, trial_control_risk)
avoided <- discharges * baselines_compared * (1 - risk_ratio)
trial_treated <- trial_control_risk * risk_ratio
#%%@note 6. Display the readings
# Plot the treated risk for each reading at both baselines; no graphics file is saved.
# แสดงความเสี่ยงเมื่อมีการโทรติดตามของแต่ละวิธีอ่านที่ความเสี่ยงพื้นฐานทั้งสองค่า ไม่บันทึกไฟล์ภาพ
print(ggplot2::ggplot(readings, ggplot2::aes(x = reading, y = 100 * treated)) +
ggplot2::geom_col() + ggplot2::facet_wrap(~baseline) +
ggplot2::labs(x = "How 0.70 is read", y = "Treated risk (%)"))
#%%@note 7. Numbers the article quotes
# Print exactly the short boxes in their reading order.
# พิมพ์ผลลัพธ์ตรงกับกล่องตัวอย่างตามลำดับในบทความ
cat("Events, then patients, treated and control:", events, patients, "\n")
cat("Risk ratio and odds ratio:", sprintf("%.2f", c(risks[1] / risks[2], odds[1] / odds[2])), "\n")
cat("Five-year risks, control and treated:", sprintf("%.1f%%", 100 * five_year_risks), "\n")
cat("Five-year risk ratio:", sprintf("%.2f", five_year_risks[2] / five_year_risks[1]), "\n")
cat("Treated risk as a share:", treated_risk, "\n")
cat("Treated risk (%):", round(100 * treated_risk, 2), "\n")
cat("Absolute reduction (percentage points):", round(100 * absolute_reduction, 2), "\n")
cat("Per 1,000 discharges, usual care, programme, avoided:", round(per_thousand), "\n")
cat("Odds at 0.20: usual, calls, calls + one:", base_odds[1], call_odds[1], 1 + call_odds[1], "\n")
cat("Still free at 0.20, usual, hazard:", round(1 - c(baselines[1], treated[3, 1]), 3), "\n")
cat("Treated risk at 0.20 read as risk, odds, hazard ratio:", shown[1:3], "\n")
cat("Avoided per 1,000 at 0.20:", round(1000 * (baselines[1] - treated[, 1])), "\n")
cat("Treated risk at 0.60 read as risk, odds, hazard ratio:", shown[4:6], "\n")
cat("Treated risk with the trial baseline (%):", round(100 * trial_treated, 2), "\n")
cat("Avoided per 1,000, local and trial baseline:", round(avoided), "\n")
อ่าน 0.70 อีกสองค่าให้ถูก
สมมติว่าไม่มีการทดลอง A และทีมมีเพียงการศึกษา B ซึ่งค่า 0.70 คูณกับออดส์ ไม่ได้คูณกับความเสี่ยง ออดส์ของการกลับมานอนโรงพยาบาลคือสัดส่วนที่กลับมาหารด้วยสัดส่วนที่ไม่กลับมา ได้ 0.20 / 0.80 = 0.25 การโทรติดตามลดออดส์เหลือ 0.70 × 0.25 = 0.175 และการหารออดส์ด้วย (หนึ่ง + ออดส์) จะแปลงกลับเป็นความเสี่ยง เพราะออดส์ 0.175 หมายถึงกลับมา 0.175 คนต่อคนที่ไม่กลับมาหนึ่งคน จึงได้ 0.175 / 1.175 เท่ากับ 14.89%
ทีนี้สมมติว่าทีมมีเพียงการทดลอง C ค่า 0.70 ของการทดลองนี้ปรับความเร็วของการกลับมานอนโรงพยาบาล จึงมีผลกับสัดส่วนผู้ป่วยที่ยังไม่กลับมานอนโรงพยาบาล ซึ่งเท่ากับ 0.80 เมื่อครบสามเดือนภายใต้การดูแลปกติ ถ้าการโทรติดตามชะลอการกลับมาด้วยอัตราส่วนเดียวกันทุกขณะ สัดส่วนที่ยังไม่กลับมาเมื่อมีการโทรติดตามคือ 0.80 ยกกำลัง 0.70 ซึ่งเท่ากับ 0.855 ความเสี่ยงเมื่อมีการโทรติดตามจึงเป็น 14.46%
อัตราส่วนฮาซาร์ดบอกความเร็ว ไม่ใช่ความเสี่ยงสะสมตลอดช่วงเวลาที่กำหนด อัตราส่วนหนึ่งปีของการทดลอง C จึงนำมาใช้กับสัดส่วนสามเดือนของโรงพยาบาลได้ โดยต้องสมมติว่าอัตราส่วนของความเร็วที่สามเดือนเท่ากับตลอดทั้งปี
ที่ความเสี่ยงพื้นฐานของโรงพยาบาล ค่าทั้งสามอยู่ใกล้กัน คือ 14%, 14.89% และ 14.46% แต่ประโยชน์ที่แบบจำลองให้กับการโทรติดตามขยับมากกว่า คือป้องกันการกลับมานอนโรงพยาบาลได้ 60, 51 หรือ 55 ครั้งต่อผู้ป่วยจำหน่าย 1,000 คน แล้วแต่ว่าการอ่านแบบใดถูก ในกลุ่มที่ป่วยหนักกว่าซึ่งมีความเสี่ยงภายใต้การดูแลปกติ 0.60 การอ่านทั้งสามแบบให้ 42%, 51.22% และ 47.34% ห่างกันมากกว่าเก้าจุด
ดังนั้นอย่าเปลี่ยนชื่อมาตรวัดเพื่อให้ตัวเลขเข้ากับแบบจำลอง ถ้ามีเพียงอัตราส่วนออดส์ ให้แปลงผ่านออดส์ของโรงพยาบาล โดยสมมติว่าอัตราส่วนออดส์เดียวกันใช้ได้ที่ความเสี่ยงพื้นฐานของโรงพยาบาลนี้ และบอกไว้ ถ้ามีเพียงอัตราส่วนฮาซาร์ด ให้แปลงผ่านสัดส่วนที่ยังไม่เกิดเหตุการณ์ และระบุว่าสมมติให้อัตราส่วนนี้คงที่ทุกขณะ (Briggs and colleagues)
ตรวจการอ่านทั้งสามแบบด้วย R
# The same reported 0.70 read as each of three effect measures, at baselines 0.20 and 0.60.
# Writes: nothing to disk; the results print in the console.
baselines <- c(0.20, 0.60)
effect <- 0.70
base_odds <- baselines / (1 - baselines)
call_odds <- effect * base_odds
treated <- rbind(risk = baselines * effect, odds = call_odds / (1 + call_odds),
hazard = 1 - (1 - baselines)^effect)
shown <- sprintf("%.2f%%", 100 * treated)
cat("Odds at 0.20: usual, calls, calls + one:", base_odds[1], call_odds[1], 1 + call_odds[1], "\n")
cat("Still free at 0.20, usual, hazard:", round(1 - c(baselines[1], treated[3, 1]), 3), "\n")
cat("Treated risk at 0.20 read as risk, odds, hazard ratio:", shown[1:3], "\n")
cat("Avoided per 1,000 at 0.20:", round(1000 * (baselines[1] - treated[, 1])), "\n")
cat("Treated risk at 0.60 read as risk, odds, hazard ratio:", shown[4:6], "\n")
Odds at 0.20: usual, calls, calls + one: 0.25 0.175 1.175
Still free at 0.20, usual, hazard: 0.8 0.855
Treated risk at 0.20 read as risk, odds, hazard ratio: 14.00% 14.89% 14.46%
Avoided per 1,000 at 0.20: 60 51 55
Treated risk at 0.60 read as risk, odds, hazard ratio: 42.00% 51.22% 47.34%
ต้องใช้ R ≥ 4.5.2 · tibble 3.3.1 · dplyr 1.2.1 · ggplot2 4.0.3 · ใช้ได้กับ R 4.6.1 · ดาวน์โหลด finding-model-inputs-in-the-literature.R
สคริปต์ฉบับเต็ม
# Finding Model Inputs in the Literature: Match the Estimate to the Question
# Follow one hospital's readmission question from three candidate studies to its model input.
# ติดตามคำถามเรื่องการกลับมานอนโรงพยาบาลของโรงพยาบาลหนึ่ง จากการศึกษาสามเรื่องสู่ค่าที่แบบจำลองใช้
# 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 candidate studies and the readings as explicit tables.
library(dplyr) # Calculate the treated risk for each reading.
library(ggplot2) # Display the readings side by side 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.
# ค่าตั้งต้นทั้งหมดเป็นข้อมูลสมมติ เขียนไว้ครั้งเดียวตามลำดับที่บทความใช้
discharges <- 1000
baseline_risk <- 0.20
risk_ratio <- 0.70
baselines <- c(0.20, 0.60)
effect <- 0.70
trial_control_risk <- 0.25
events <- c(treated = 8, control = 13)
patients <- c(treated = 66, control = 60)
control_survival <- 0.60
hazard_ratio <- 0.70
#%%@note 2. Rework the two foundation examples
# One trial's counts give both ratios; one survival curve turns a rate ratio into risks.
# จำนวนจากการทดลองหนึ่งให้อัตราส่วนทั้งสองแบบ และเส้นการอยู่รอดหนึ่งเส้นแปลงอัตราส่วนเป็นความเสี่ยง
risks <- events / patients
odds <- events / (patients - events)
five_year_risks <- 1 - control_survival^c(1, hazard_ratio)
#%%@note 3. Apply the matching risk ratio to the local baseline
# Treated risk is the baseline times the ratio; the gap is the absolute reduction.
# ความเสี่ยงเมื่อมีการโทรติดตามคือความเสี่ยงพื้นฐานคูณอัตราส่วน ผลต่างคือการลดลงสัมบูรณ์
treated_risk <- baseline_risk * risk_ratio
absolute_reduction <- baseline_risk - treated_risk
per_thousand <- discharges * c(baseline_risk, treated_risk, absolute_reduction)
#%%@note 4. Read the same value through odds and through the share still free
# Each reading changes a different quantity, so each gives a different treated risk.
# แต่ละวิธีอ่านเปลี่ยนปริมาณคนละตัว จึงได้ความเสี่ยงเมื่อมีการโทรติดตามต่างกัน
base_odds <- baselines / (1 - baselines)
call_odds <- effect * base_odds
readings <- tibble::tibble(reading = rep(c("risk", "odds", "hazard"), times = 2),
baseline = rep(baselines, each = 3)) |>
dplyr::mutate(odds = effect * baseline / (1 - baseline),
treated = dplyr::case_when(reading == "risk" ~ baseline * effect,
reading == "odds" ~ odds / (1 + odds),
TRUE ~ 1 - (1 - baseline)^effect))
treated <- matrix(readings$treated, nrow = 3, dimnames = list(c("risk", "odds", "hazard"), NULL))
stopifnot(abs(treated["odds", ] - call_odds / (1 + call_odds)) < 1e-12)
shown <- sprintf("%.2f%%", 100 * treated)
#%%@note 5. Pair the trial's ratio with each baseline
# The ratio comes from the trial; the baseline should come from the hospital's own patients.
# อัตราส่วนมาจากการทดลอง ส่วนความเสี่ยงพื้นฐานควรมาจากผู้ป่วยของโรงพยาบาลเอง
baselines_compared <- c(baseline_risk, trial_control_risk)
avoided <- discharges * baselines_compared * (1 - risk_ratio)
trial_treated <- trial_control_risk * risk_ratio
#%%@note 6. Display the readings
# Plot the treated risk for each reading at both baselines; no graphics file is saved.
# แสดงความเสี่ยงเมื่อมีการโทรติดตามของแต่ละวิธีอ่านที่ความเสี่ยงพื้นฐานทั้งสองค่า ไม่บันทึกไฟล์ภาพ
print(ggplot2::ggplot(readings, ggplot2::aes(x = reading, y = 100 * treated)) +
ggplot2::geom_col() + ggplot2::facet_wrap(~baseline) +
ggplot2::labs(x = "How 0.70 is read", y = "Treated risk (%)"))
#%%@note 7. Numbers the article quotes
# Print exactly the short boxes in their reading order.
# พิมพ์ผลลัพธ์ตรงกับกล่องตัวอย่างตามลำดับในบทความ
cat("Events, then patients, treated and control:", events, patients, "\n")
cat("Risk ratio and odds ratio:", sprintf("%.2f", c(risks[1] / risks[2], odds[1] / odds[2])), "\n")
cat("Five-year risks, control and treated:", sprintf("%.1f%%", 100 * five_year_risks), "\n")
cat("Five-year risk ratio:", sprintf("%.2f", five_year_risks[2] / five_year_risks[1]), "\n")
cat("Treated risk as a share:", treated_risk, "\n")
cat("Treated risk (%):", round(100 * treated_risk, 2), "\n")
cat("Absolute reduction (percentage points):", round(100 * absolute_reduction, 2), "\n")
cat("Per 1,000 discharges, usual care, programme, avoided:", round(per_thousand), "\n")
cat("Odds at 0.20: usual, calls, calls + one:", base_odds[1], call_odds[1], 1 + call_odds[1], "\n")
cat("Still free at 0.20, usual, hazard:", round(1 - c(baselines[1], treated[3, 1]), 3), "\n")
cat("Treated risk at 0.20 read as risk, odds, hazard ratio:", shown[1:3], "\n")
cat("Avoided per 1,000 at 0.20:", round(1000 * (baselines[1] - treated[, 1])), "\n")
cat("Treated risk at 0.60 read as risk, odds, hazard ratio:", shown[4:6], "\n")
cat("Treated risk with the trial baseline (%):", round(100 * trial_treated, 2), "\n")
cat("Avoided per 1,000, local and trial baseline:", round(avoided), "\n")
ใช้อัตราส่วนจากการทดลองกับความเสี่ยงพื้นฐานของเราเอง
การทดลอง A รายงานกลุ่มควบคุมของตัวเองด้วย คือผู้ป่วยภายใต้การดูแลปกติ 0.25 กลับมานอนโรงพยาบาลภายในสามเดือน การทดลองนี้ทำในระบบสุขภาพที่มีคลินิกผู้ป่วยนอกน้อยกว่าของโรงพยาบาลเรา ถ้านำ 0.25 นั้นใส่แบบจำลอง จะได้ความเสี่ยงเมื่อมีการโทรติดตาม 17.5% และป้องกันการกลับมานอนโรงพยาบาลได้ 75 ครั้งต่อผู้ป่วยจำหน่าย 1,000 คน เทียบกับ 60 ครั้งเมื่อใช้ความเสี่ยงของโรงพยาบาลเอง
การทดลองตอบว่าการโทรติดตามเปลี่ยนความเสี่ยงไปเท่าใด ส่วนเวชระเบียนของโรงพยาบาลตอบว่าความเสี่ยงที่นี่สูงเท่าใด อัตราส่วนระหว่างสองกลุ่มมักนำไปใช้ข้ามสถานที่ได้ดีกว่าความเสี่ยงพื้นฐาน แต่นั่นเป็นข้อสมมติที่ต้องตรวจ ไม่ใช่กฎ ให้ถามว่าผู้ป่วย การดูแลปกติ และพยาบาลในการทดลองคล้ายกับของโรงพยาบาลหรือไม่ (Briggs and colleagues)
ระดับที่ค่าประมาณใช้ได้กับผู้ป่วยและบริบทการดูแลของแบบจำลองเรียกว่าการนำไปใช้ข้ามบริบท (transferability) ซึ่งเป็นคนละคำถามกับคุณภาพของการศึกษา คือคำถามว่าอคติทำให้ค่าประมาณคลาดเคลื่อนในผู้ป่วยที่การศึกษานั้นรับเข้ามาเองหรือไม่
การศึกษา B แสดงความต่างนี้ เวชระเบียนอาจครบถ้วน แต่ผู้ป่วยที่ยอมรับการโทรติดตามอาจแข็งแรงกว่าตั้งแต่แรก ค่า 0.70 ส่วนหนึ่งจึงสะท้อนว่าใครเลือกรับสาย ซึ่งเป็นจุดอ่อนภายในการศึกษาที่การนำไปใช้ข้ามบริบทแก้ไม่ได้
ความไม่แน่ใจชั้นที่สามเกิดขึ้นเมื่อแปลงตัวเลข การอ่าน 0.70 ของการทดลอง C ผ่านสัดส่วนที่ยังไม่กลับมา สมมติว่าอัตราส่วนคงที่ทุกขณะ ถ้าการโทรติดตามได้ผลส่วนใหญ่ในสัปดาห์แรก ๆ ค่า 14.46% ที่แปลงได้ก็คลาดไป ความไม่แน่ใจเกี่ยวกับการแปลงเองนี้เรียกว่าความไม่แน่นอนจากการแปลงค่า (transformation uncertainty) ให้บันทึกแยกจากความไม่แน่นอนจากการสุ่มตัวอย่างของการศึกษา คือความผันแปรโดยบังเอิญจากการศึกษาผู้ป่วยเพียงบางส่วน ผู้อ่านจะได้เห็นว่าส่วนใดมาจากข้อมูล และส่วนใดมาจากข้อสมมติ (Briggs and colleagues; Eddy and colleagues)
ตรวจความเสี่ยงพื้นฐานทั้งสองค่าด้วย R
# Whose baseline goes with a trial's risk ratio: its own controls or the hospital's patients?
# Writes: nothing to disk; the results print in the console.
discharges <- 1000
risk_ratio <- 0.70
baseline_risk <- 0.20
trial_control_risk <- 0.25
baselines_compared <- c(baseline_risk, trial_control_risk)
avoided <- discharges * baselines_compared * (1 - risk_ratio)
trial_treated <- trial_control_risk * risk_ratio
cat("Treated risk with the trial baseline (%):", round(100 * trial_treated, 2), "\n")
cat("Avoided per 1,000, local and trial baseline:", round(avoided), "\n")
Treated risk with the trial baseline (%): 17.5
Avoided per 1,000, local and trial baseline: 60 75
ต้องใช้ R ≥ 4.5.2 · tibble 3.3.1 · dplyr 1.2.1 · ggplot2 4.0.3 · ใช้ได้กับ R 4.6.1 · ดาวน์โหลด finding-model-inputs-in-the-literature.R
สคริปต์ฉบับเต็ม
# Finding Model Inputs in the Literature: Match the Estimate to the Question
# Follow one hospital's readmission question from three candidate studies to its model input.
# ติดตามคำถามเรื่องการกลับมานอนโรงพยาบาลของโรงพยาบาลหนึ่ง จากการศึกษาสามเรื่องสู่ค่าที่แบบจำลองใช้
# 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 candidate studies and the readings as explicit tables.
library(dplyr) # Calculate the treated risk for each reading.
library(ggplot2) # Display the readings side by side 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.
# ค่าตั้งต้นทั้งหมดเป็นข้อมูลสมมติ เขียนไว้ครั้งเดียวตามลำดับที่บทความใช้
discharges <- 1000
baseline_risk <- 0.20
risk_ratio <- 0.70
baselines <- c(0.20, 0.60)
effect <- 0.70
trial_control_risk <- 0.25
events <- c(treated = 8, control = 13)
patients <- c(treated = 66, control = 60)
control_survival <- 0.60
hazard_ratio <- 0.70
#%%@note 2. Rework the two foundation examples
# One trial's counts give both ratios; one survival curve turns a rate ratio into risks.
# จำนวนจากการทดลองหนึ่งให้อัตราส่วนทั้งสองแบบ และเส้นการอยู่รอดหนึ่งเส้นแปลงอัตราส่วนเป็นความเสี่ยง
risks <- events / patients
odds <- events / (patients - events)
five_year_risks <- 1 - control_survival^c(1, hazard_ratio)
#%%@note 3. Apply the matching risk ratio to the local baseline
# Treated risk is the baseline times the ratio; the gap is the absolute reduction.
# ความเสี่ยงเมื่อมีการโทรติดตามคือความเสี่ยงพื้นฐานคูณอัตราส่วน ผลต่างคือการลดลงสัมบูรณ์
treated_risk <- baseline_risk * risk_ratio
absolute_reduction <- baseline_risk - treated_risk
per_thousand <- discharges * c(baseline_risk, treated_risk, absolute_reduction)
#%%@note 4. Read the same value through odds and through the share still free
# Each reading changes a different quantity, so each gives a different treated risk.
# แต่ละวิธีอ่านเปลี่ยนปริมาณคนละตัว จึงได้ความเสี่ยงเมื่อมีการโทรติดตามต่างกัน
base_odds <- baselines / (1 - baselines)
call_odds <- effect * base_odds
readings <- tibble::tibble(reading = rep(c("risk", "odds", "hazard"), times = 2),
baseline = rep(baselines, each = 3)) |>
dplyr::mutate(odds = effect * baseline / (1 - baseline),
treated = dplyr::case_when(reading == "risk" ~ baseline * effect,
reading == "odds" ~ odds / (1 + odds),
TRUE ~ 1 - (1 - baseline)^effect))
treated <- matrix(readings$treated, nrow = 3, dimnames = list(c("risk", "odds", "hazard"), NULL))
stopifnot(abs(treated["odds", ] - call_odds / (1 + call_odds)) < 1e-12)
shown <- sprintf("%.2f%%", 100 * treated)
#%%@note 5. Pair the trial's ratio with each baseline
# The ratio comes from the trial; the baseline should come from the hospital's own patients.
# อัตราส่วนมาจากการทดลอง ส่วนความเสี่ยงพื้นฐานควรมาจากผู้ป่วยของโรงพยาบาลเอง
baselines_compared <- c(baseline_risk, trial_control_risk)
avoided <- discharges * baselines_compared * (1 - risk_ratio)
trial_treated <- trial_control_risk * risk_ratio
#%%@note 6. Display the readings
# Plot the treated risk for each reading at both baselines; no graphics file is saved.
# แสดงความเสี่ยงเมื่อมีการโทรติดตามของแต่ละวิธีอ่านที่ความเสี่ยงพื้นฐานทั้งสองค่า ไม่บันทึกไฟล์ภาพ
print(ggplot2::ggplot(readings, ggplot2::aes(x = reading, y = 100 * treated)) +
ggplot2::geom_col() + ggplot2::facet_wrap(~baseline) +
ggplot2::labs(x = "How 0.70 is read", y = "Treated risk (%)"))
#%%@note 7. Numbers the article quotes
# Print exactly the short boxes in their reading order.
# พิมพ์ผลลัพธ์ตรงกับกล่องตัวอย่างตามลำดับในบทความ
cat("Events, then patients, treated and control:", events, patients, "\n")
cat("Risk ratio and odds ratio:", sprintf("%.2f", c(risks[1] / risks[2], odds[1] / odds[2])), "\n")
cat("Five-year risks, control and treated:", sprintf("%.1f%%", 100 * five_year_risks), "\n")
cat("Five-year risk ratio:", sprintf("%.2f", five_year_risks[2] / five_year_risks[1]), "\n")
cat("Treated risk as a share:", treated_risk, "\n")
cat("Treated risk (%):", round(100 * treated_risk, 2), "\n")
cat("Absolute reduction (percentage points):", round(100 * absolute_reduction, 2), "\n")
cat("Per 1,000 discharges, usual care, programme, avoided:", round(per_thousand), "\n")
cat("Odds at 0.20: usual, calls, calls + one:", base_odds[1], call_odds[1], 1 + call_odds[1], "\n")
cat("Still free at 0.20, usual, hazard:", round(1 - c(baselines[1], treated[3, 1]), 3), "\n")
cat("Treated risk at 0.20 read as risk, odds, hazard ratio:", shown[1:3], "\n")
cat("Avoided per 1,000 at 0.20:", round(1000 * (baselines[1] - treated[, 1])), "\n")
cat("Treated risk at 0.60 read as risk, odds, hazard ratio:", shown[4:6], "\n")
cat("Treated risk with the trial baseline (%):", round(100 * trial_treated, 2), "\n")
cat("Avoided per 1,000, local and trial baseline:", round(avoided), "\n")
ปิดเส้นทางของหลักฐาน
ก่อนนำตัวเลขเข้าแบบจำลอง ให้บันทึกการเลือกไว้ในตารางพารามิเตอร์ ได้แก่ แหล่งที่มา และตารางหรือหน้าที่พบค่า 0.70 และเหตุผลที่เลือกการทดลอง A และเหตุผลที่เก็บการศึกษา B กับการทดลอง C ไว้เป็นตัวตรวจสอบแทนที่จะใช้เป็นข้อมูลนำเข้า รวมทั้งการแปลงค่าที่ทำ
บันทึกสิ่งที่ขาดด้วย ในตัวอย่างสมมตินี้ 0.70 ของการทดลอง A ไม่มีช่วงความเชื่อมั่น แบบจำลองจึงยังบอกไม่ได้ว่าประโยชน์ไม่แน่นอนเพียงใด ถ้าไม่มีการศึกษาใดตอบคำถามได้ ให้บันทึกช่องว่างนั้นและผลที่มีต่อการตัดสินใจ (Eddy and colleagues) อย่าสร้างช่วงความเชื่อมั่น การอ้างอิง หรือตัวเลขที่ดูน่าเชื่อขึ้นมาเองเพื่อเติมตารางให้เต็ม ฐานรวบรวมแหล่งข้อมูลช่วยให้หาการศึกษาที่เป็นตัวเลือก แต่ไม่ได้ทำให้ตัวเลขของการศึกษาเหล่านั้นใช้แทนกันได้
หากต้องการฝึกกับบทความจริง ให้อ่านการประเมินทางเศรษฐศาสตร์ของการรักษาผ่านหลอดเลือดสำหรับโรคหลอดเลือดสมองตีบเฉียบพลันในประเทศไทย ของ Rattanavipapong and colleagues สำหรับข้อมูลนำเข้าแต่ละตัว ให้หาแหล่งที่มา แล้วเทียบผู้ป่วย การเปรียบเทียบ ผลลัพธ์ และเวลากับคำถามของแบบจำลอง บทความนี้ไม่ได้นำตัวเลขของงานนั้นมาใช้
คำศัพท์ที่ควรแยกให้ชัด
- Parameter question (คำถามของพารามิเตอร์)
- ปริมาณที่ข้อมูลนำเข้าหนึ่งตัวของแบบจำลองต้องประมาณ คือผู้ป่วยของใคร เปรียบเทียบอะไร ผลลัพธ์ใด ในช่วงเวลาเท่าใด
- Baseline risk (ความเสี่ยงพื้นฐาน)
- ความเสี่ยงของเหตุการณ์ภายใต้การดูแลปกติในผู้ป่วยของแบบจำลองเอง ในที่นี้คือ 0.20
- Risk ratio (อัตราส่วนความเสี่ยง)
- ความเสี่ยงของกลุ่มที่ได้รับการรักษาหารด้วยความเสี่ยงของกลุ่มที่ไม่ได้รับ ในช่วงเวลาเดียวกัน คูณกับความเสี่ยงได้โดยตรง
- Odds ratio (อัตราส่วนออดส์)
- อัตราส่วนของออดส์ โดยออดส์คือจำนวนที่เกิดเหตุการณ์หารด้วยจำนวนที่ไม่เกิด คูณกับออดส์ ไม่ได้คูณกับความเสี่ยง
- Hazard ratio (อัตราส่วนฮาซาร์ด)
- อัตราส่วนของความเร็วที่เหตุการณ์เกิดในคนที่ยังไม่เกิดเหตุการณ์ มีผลกับสัดส่วนที่ยังไม่เกิดเหตุการณ์
- Transferability (การนำไปใช้ข้ามบริบท)
- ระดับที่ค่าประมาณใช้ได้กับผู้ป่วยและบริบทการดูแลของแบบจำลอง
- Transformation uncertainty (ความไม่แน่นอนจากการแปลงค่า)
- ความไม่แน่ใจที่มาจากข้อสมมติที่ใช้แปลงค่าประมาณ ซึ่งบันทึกแยกจากความไม่แน่นอนจากการสุ่มตัวอย่าง
เชื่อมกับบทความพื้นฐาน
บทความพื้นฐานเรื่องการคัดเลือกพารามิเตอร์และฐานรวบรวมแหล่งข้อมูล แสดงว่าตัวเลขที่เป็นตัวเลือกมาจากไหนเมื่อข้อมูลในพื้นที่มีน้อย ส่วนบทความเรื่อง risk ratio, odds ratio และผลต่างความเสี่ยง คำนวณจำนวนผู้ป่วยเบื้องหลังตัวอย่างอัตราส่วนออดส์อย่างละเอียด บทความตอนถัดไปของชุดนี้สอนการคงเวลาไว้ในการคำนวณ ซึ่งผลระยะหนึ่งปีอย่างที่การทดลอง C รายงานต้องใช้
ลองใช้ในแอป
เปิดแอปการประเมินทางเศรษฐศาสตร์ของเราเพื่อลองเปลี่ยนค่าข้อมูลนำเข้าและดูผลลัพธ์เปลี่ยนตาม ต้องเข้าสู่ระบบและใช้แผน Pro หรือ Max
แอปเริ่มจากค่าตัวอย่างของแอปเอง ตัวเลขในแอปจึงไม่ตรงกับบทความนี้
เอกสารอ้างอิง
- 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
- Rattanavipapong Waranya, Worakijthamrongchai Thanaboon, Soboon Budsadee, Luankongsomchit Vilawan, Kongmuangpuk Mananchaya, Isaranuwatchai Wanrudee, Teerawattananon Yot, Nilanont Yongchai. Economic evaluation of endovascular treatment for acute ischaemic stroke in Thailand. BMJ Open. 2022;12(9):e064403. doi:10.1136/bmjopen-2022-064403. https://doi.org/10.1136/bmjopen-2022-064403
- 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.70 แต่ละค่าวัดอะไร ถ้าเป็น risk ratio จะคูณกับ 0.20 ของเราได้ 0.14 ถ้าเป็นอัตราส่วนออดส์ได้ 14.89% และถ้าเป็นอัตราส่วนฮาซาร์ดได้ 14.46% เมื่อแปลงแล้ว
- ใช้อัตราส่วนจากการศึกษาที่ดีที่สุด และใช้ความเสี่ยงพื้นฐานจากผู้ป่วยของเราเอง คือ 0.20 ไม่ใช่ 0.25 ของการทดลอง จึงลดการกลับมานอนโรงพยาบาลได้ 60 ครั้งต่อผู้ป่วยจำหน่าย 1,000 คน ไม่ใช่ 75
- ตัดสินคุณภาพของการศึกษา การนำไปใช้ข้ามบริบท และการแปลงค่าแยกกัน และบันทึกทุกการเลือกให้นักวิเคราะห์คนอื่นตามได้
อ่านต่อในวิกิ: การคัดเลือกพารามิเตอร์ บัญชีต้นทุนอ้างอิง และฐานข้อมูลค่าอรรถประโยชน์เมื่อข้อมูลในประเทศมีจำกัด · อัตราส่วนความเสี่ยง อัตราส่วนออดส์ ผลต่างความเสี่ยง และจำนวนที่ต้องรักษา: ตารางสองคูณสองเดียว คำตอบสี่แบบ