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

Health EconomicsClinical Epidemiology ResearchMethodology and Research Design TH
การค้นหาข้อมูลนำเข้าของแบบจำลองจากวรรณกรรม: เลือกค่าประมาณให้ตรงกับคำถาม
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 ของโรงพยาบาลได้ตามที่เป็นอยู่ อีกสองค่าต้องแปลงก่อน และการแปลงแต่ละแบบต้องอาศัยข้อสมมติ

อ่านทีละแถวจากซ้ายไปขวา การทดลอง A ตรงกับคำถามทั้งผลลัพธ์ เวลา และมาตรวัด ค่า 0.70 ของการทดลองนี้จึงคูณกับความเสี่ยงของโรงพยาบาลเองได้ การศึกษา B และการทดลอง C รายงานออดส์และความเร็ว จึงต้องแปลงค่าก่อน และการศึกษา B ซึ่งใช้เวชระเบียนต้องตัดสินคุณภาพด้วย

ตรวจตัวอย่างทบทวนทั้งสองด้วย R

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

  1. เริ่มจากความเสี่ยงของโรงพยาบาลเอง

    \[ \frac{200}{1000} = 0.20 \]

    ภายใต้การดูแลปกติ ผู้ป่วยที่จำหน่าย 1,000 คนกลับมานอนโรงพยาบาลภายในสามเดือน 200 คน คิดเป็นความเสี่ยง 0.20

  2. คูณด้วย risk ratio

    \[ 0.20 \times 0.70 = 0.14 \]

    เมื่อมีการโทรติดตาม ความเสี่ยงลดลงเหลือ 0.14 หรือ 14% ของผู้ป่วยที่จำหน่าย

  3. ลบกันเพื่อหาประโยชน์

    \[ 200 - 140 = 60 \]

    ช่องว่างคือ 6 จุดร้อยละ จากผู้ป่วยจำหน่าย 1,000 คน กลับมา 140 คนแทน 200 คนภายใต้การดูแลปกติ การโทรติดตามจึงป้องกันการกลับมานอนโรงพยาบาลได้ 60 ครั้ง

ผลลัพธ์: เมื่ออ่านเป็น risk ratio ตามที่เป็นจริง 0.70 ของการทดลอง A ให้การกลับมานอนโรงพยาบาลน้อยลง 60 ครั้งต่อผู้ป่วยจำหน่าย 1,000 คน หากค่านี้ใช้กับผู้ป่วยกลุ่มนี้ได้

ตรวจตัวอย่างคำนวณด้วย R

โค้ด R example.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")
ผลลัพธ์จากการรัน example.log
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)

ดูแท่งสีสามแท่งในแต่ละช่องว่าห่างกันเท่าใด โดยมีแท่งสีเทาของการดูแลปกติเป็นจุดอ้างอิง ที่ความเสี่ยงพื้นฐานของโรงพยาบาล (0.20) ทั้งสามแบบห่างกันไม่ถึงหนึ่งจุด แต่ยังหมายถึงการกลับมานอนโรงพยาบาลที่ลดได้ 60, 51 หรือ 55 ครั้งต่อผู้ป่วยจำหน่าย 1,000 คน ชื่อมาตรวัดจึงเปลี่ยนประโยชน์ที่แบบจำลองนับ ในกลุ่มที่ป่วยหนักกว่า (0.60) แท่งกระจายจาก 42% ถึง 51.22% การอ่านชื่อผิดจึงสำคัญที่สุดเมื่อการกลับมานอนโรงพยาบาลพบบ่อย

ตรวจการอ่านทั้งสามแบบด้วย R

โค้ด R measures.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")
ผลลัพธ์จากการรัน measures.log
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")
ผลลัพธ์เรียงตามย่อหน้าด้านบน คือออดส์ สัดส่วนที่ยังไม่กลับมา ความเสี่ยงเมื่อมีการโทรติดตามสามค่า แล้วจึงการกลับมานอนโรงพยาบาลที่ลดได้
ตัวควบคุมเริ่มที่โรงพยาบาล คือความเสี่ยงภายใต้การดูแลปกติ 0.20 และค่าที่รายงาน 0.70 ที่อ่านเป็น risk ratio ลองเปลี่ยนสิ่งที่การศึกษารายงานเป็น odds ratio แล้วลากความเสี่ยงภายใต้การดูแลปกติให้สูงขึ้น เส้นประแนวตั้งจะเลื่อนตามความเสี่ยงที่เลือก เส้นโค้งตัวหนาและจุดใหญ่คือความเสี่ยงเมื่อมีการโทรติดตามที่ถูกต้อง ซึ่งแยกออกจากเส้นประสีเหลืองอำพันของ risk ratio และจุดเล็กของมัน การ์ดสุดท้ายบอกว่าข้อมูลนำเข้าต่ำไปกี่จุดร้อยละเมื่ออ่าน odds ratio ผิดเป็น risk ratio ประโยชน์จึงดูมากเกินจริง

ใช้อัตราส่วนจากการทดลองกับความเสี่ยงพื้นฐานของเราเอง

การทดลอง 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

โค้ด R transport.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")
ผลลัพธ์จากการรัน transport.log
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

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

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

  1. 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
  2. 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
  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.70 แต่ละค่าวัดอะไร ถ้าเป็น risk ratio จะคูณกับ 0.20 ของเราได้ 0.14 ถ้าเป็นอัตราส่วนออดส์ได้ 14.89% และถ้าเป็นอัตราส่วนฮาซาร์ดได้ 14.46% เมื่อแปลงแล้ว
  • ใช้อัตราส่วนจากการศึกษาที่ดีที่สุด และใช้ความเสี่ยงพื้นฐานจากผู้ป่วยของเราเอง คือ 0.20 ไม่ใช่ 0.25 ของการทดลอง จึงลดการกลับมานอนโรงพยาบาลได้ 60 ครั้งต่อผู้ป่วยจำหน่าย 1,000 คน ไม่ใช่ 75
  • ตัดสินคุณภาพของการศึกษา การนำไปใช้ข้ามบริบท และการแปลงค่าแยกกัน และบันทึกทุกการเลือกให้นักวิเคราะห์คนอื่นตามได้

อ่านต่อในวิกิ: การคัดเลือกพารามิเตอร์ บัญชีต้นทุนอ้างอิง และฐานข้อมูลค่าอรรถประโยชน์เมื่อข้อมูลในประเทศมีจำกัด · อัตราส่วนความเสี่ยง อัตราส่วนออดส์ ผลต่างความเสี่ยง และจำนวนที่ต้องรักษา: ตารางสองคูณสองเดียว คำตอบสี่แบบ

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

ความคิดเห็น

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

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