ปฏิกิริยาสัมพันธ์ระหว่างการรักษากับเวลา: สัมประสิทธิ์ตัวไหนคือผลของการรักษา

Clinical Epidemiology ResearchMethodology and Research Design THUniqcret doctor knowledges TH
ปฏิกิริยาสัมพันธ์ระหว่างการรักษากับเวลา: สัมประสิทธิ์ตัวไหนคือผลของการรักษา
On this page

Read the English version

บทคัดย่อ

ในการทดลองแบบสุ่มที่วัดผลซ้ำหลายครั้ง แบบจำลองถดถอยที่มีตัวแปรกลุ่มการรักษา (arm) ครั้งที่วัด (visit) และปฏิกิริยาสัมพันธ์ (interaction) ของทั้งสองจะพิมพ์สัมประสิทธิ์ออกมาหลายตัว โดยไม่มีตัวใดถูกระบุว่าเป็นผลของการรักษา บทความนี้จับคู่สัมประสิทธิ์แต่ละตัวกับค่าเฉลี่ยรายกลุ่มรายครั้งที่วัดที่มันเปรียบเทียบ เมื่อมีสองครั้งที่วัด สัมประสิทธิ์ของกลุ่มคือความต่างระหว่างกลุ่มที่จุดเริ่มต้น (baseline) สัมประสิทธิ์ของครั้งที่วัดคือการเปลี่ยนแปลงในกลุ่มควบคุม และปฏิกิริยาสัมพันธ์คือผลต่างของผลต่าง (difference in differences) ได้แก่การเปลี่ยนแปลงในกลุ่มรักษาลบการเปลี่ยนแปลงในกลุ่มควบคุม เมื่อมีสี่ครั้งที่วัดและลงรหัสแต่ละครั้งเป็นหมวดของตัวเอง ซึ่งเรียกว่าเวลาแบบจัดกลุ่ม (categorical time) ความต่างระหว่างกลุ่มในครั้งหลังเท่ากับสัมประสิทธิ์ของกลุ่มบวกสัมประสิทธิ์ปฏิกิริยาสัมพันธ์ของครั้งนั้น การถือว่าเวลาเป็นตัวเลขให้ผลต่างของความชันหนึ่งค่า และสมมติว่าเป็นเส้นตรง การทดลองจำลองในผู้ใหญ่ 300 คนแสดงการคำนวณ เปรียบเทียบวิธีใช้คะแนนที่จุดเริ่มต้นสามวิธี และสร้างแบบจำลองสหสัมพันธ์ระหว่างครั้งที่วัด บทความนี้สรุปว่าต้องระบุครั้งที่วัดควบคู่กับผลของการรักษา และอ่านผลเป็นผลรวมของสัมประสิทธิ์ และความต่างนี้ในแบบที่ปรับด้วยคะแนนที่จุดเริ่มต้นมักแม่นยำกว่า


ภาพสรุป ข้อมูลจำลอง

ตารางถดถอยในที่ประชุมเขียนรายงานการทดลอง

คณะผู้เขียนกำลังร่างรายงานหลักของการทดลองแบบสุ่ม การทดลองนี้รับผู้ใหญ่ 300 คนที่มีคะแนนอาการเรื้อรัง โดยคะแนนต่ำหมายถึงอาการน้อยลง วัดคะแนนที่สัปดาห์ที่ 0, 4, 8 และ 12 โดยสัปดาห์ที่ 0 คือก่อนได้รับยาครั้งแรก การรักษานี้เป็นของสมมติและข้อมูลเป็นข้อมูลจำลอง

ตารางถดถอยมีค่าจุดตัดแกน (intercept) หนึ่งค่า สัมประสิทธิ์ของกลุ่มหนึ่งตัว สัมประสิทธิ์ของครั้งที่วัดสามตัว และสัมประสิทธิ์ปฏิกิริยาสัมพันธ์ระหว่างกลุ่มกับครั้งที่วัดสามตัว

ปฏิกิริยาสัมพันธ์ระหว่างการรักษากับเวลา (treatment-by-time interaction) ทำให้ความต่างระหว่างกลุ่มเปลี่ยนไปได้ในแต่ละครั้งที่วัด การทดสอบร่วม (joint test) ของสัมประสิทธิ์ปฏิกิริยาสัมพันธ์ทั้งสามตัว ซึ่งเป็นการทดสอบครั้งเดียวว่าความต่างระหว่างกลุ่มเท่ากันทุกครั้งที่วัดหรือไม่ มีนัยสำคัญชัดเจน แพทย์ท่านหนึ่งถามว่า ในตัวเลขแปดตัวนี้ ตัวไหนคือผลของการรักษา

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

เนื่องจากการทดลองวัดคะแนนที่จุดเริ่มต้นก่อนการรักษา ความต่างนี้ในแบบที่ปรับด้วยคะแนนที่จุดเริ่มต้น (จุดเริ่มต้นร่วมแบบบังคับ หรือ ANCOVA ซึ่งนิยามไว้ในหัวข้อ 'สามวิธีใช้คะแนนสัปดาห์ที่ 0') มักเป็นค่าประมาณหลักที่แม่นยำกว่า ส่วนที่เหลือของบทความแสดงเหตุผล

สองกลุ่ม สองครั้งที่วัด: ค่าเฉลี่ยสี่ค่าและสัมประสิทธิ์สี่ตัว

เริ่มจากครั้งที่วัดเริ่มต้นและครั้งติดตามผลหนึ่งครั้ง ให้ $Y_{ij}$ เป็นคะแนนของผู้เข้าร่วมคนที่ $i$ ในครั้งที่วัด $j$ ให้ $\mathrm{arm}_i$ เป็น 1 สำหรับกลุ่มรักษาและ 0 สำหรับกลุ่มควบคุม และ $\mathrm{post}_j$ เป็น 1 ที่ครั้งติดตามผลและ 0 ที่จุดเริ่มต้น แบบจำลองของค่าเฉลี่ยคือ

$$\mathrm{E}(Y_{ij}) = \beta_0 + \beta_1\,\mathrm{arm}_i + \beta_2\,\mathrm{post}_j + \beta_3\,\mathrm{arm}_i\,\mathrm{post}_j$$

ในสมการนี้ $\mathrm{E}(Y_{ij})$ คือคะแนนเฉลี่ยของกลุ่มและครั้งที่วัดที่กำหนด และ $\beta$ แต่ละตัวคือสัมประสิทธิ์ที่ต้องประมาณ เมื่อกำหนดตัวบ่งชี้ทั้งสองเป็น 0 หรือ 1 จะได้ค่าเฉลี่ยของเซลล์สี่ค่าในตาราง

ค่าเฉลี่ยของเซลล์สี่ค่าในแบบจำลองสองครั้งที่วัด

ดูแถวล่างสุด: ความต่างระหว่างกลุ่มที่ครั้งติดตามผลคือผลรวมของสัมประสิทธิ์สองตัว
กลุ่มจุดเริ่มต้น ($\mathrm{post}_j = 0$)ติดตามผล ($\mathrm{post}_j = 1$)การเปลี่ยนแปลง ติดตามผลลบจุดเริ่มต้น
กลุ่มควบคุม ($\mathrm{arm}_i = 0$)$\beta_0$$\beta_0 + \beta_2$$\beta_2$
กลุ่มรักษา ($\mathrm{arm}_i = 1$)$\beta_0 + \beta_1$$\beta_0 + \beta_1 + \beta_2 + \beta_3$$\beta_2 + \beta_3$
กลุ่มรักษาลบกลุ่มควบคุม$\beta_1$$\beta_1 + \beta_3$$\beta_3$

อ่านเซลล์ทั้งสี่

สัมประสิทธิ์แต่ละตัวตอนนี้มีความหมายชัดเจน $\beta_0$ คือค่าเฉลี่ยของกลุ่มควบคุมที่จุดเริ่มต้น (baseline) ซึ่งเป็นครั้งที่วัดก่อนการรักษา และ $\beta_1$ คือความต่างระหว่างกลุ่มที่จุดเริ่มต้น $\beta_2$ คือการเปลี่ยนแปลงในกลุ่มควบคุม $\beta_3$ คือการเปลี่ยนแปลงในกลุ่มรักษาลบการเปลี่ยนแปลงในกลุ่มควบคุม หรือ ผลต่างของผลต่าง (difference in differences)

ความต่างระหว่างกลุ่มที่ครั้งติดตามผลคือ $\beta_1 + \beta_3$ ซึ่งเป็นผลรวม ไม่ใช่สัมประสิทธิ์ตัวใดตัวหนึ่งตามลำพัง คอนทราสต์ (contrast) คือผลรวมหรือผลต่างของสัมประสิทธิ์ที่ตอบคำถามเดียว เช่นความต่างระหว่างกลุ่มที่สัปดาห์ที่ 12

ระดับอ้างอิง (reference level) ของตัวแปรคือหมวดที่หมวดอื่นถูกนำมาเปรียบเทียบด้วย ในที่นี้คือหมวดที่ลงรหัสเป็น 0 ในแบบจำลองที่มีปฏิกิริยาสัมพันธ์ สัมประสิทธิ์ของกลุ่มหรือของครั้งที่วัดแต่ละตัวอ่านโดยให้ตัวแปรอีกตัวอยู่ที่ระดับอ้างอิงของมัน ในที่นี้คือจุดเริ่มต้นและกลุ่มควบคุม

ในการทดลอง จุดเริ่มต้นเกิดก่อนการรักษา การสุ่มจึงทำให้ความต่างที่คาดไว้ที่จุดเริ่มต้นเป็นศูนย์ ค่าประมาณของ $\beta_1$ จึงสะท้อนความไม่สมดุลที่เกิดจากความบังเอิญ ไม่ใช่ผลของการรักษา หากกำหนดให้ครั้งติดตามผลเป็นระดับอ้างอิง $\beta_1$ จะกลายเป็นความต่างที่ครั้งติดตามผล โดยค่าเฉลี่ยที่ประมาณได้ไม่เปลี่ยน

ตัวอย่างคำนวณด้วยมือ: ค่าเฉลี่ยจริงสี่ค่า สัมประสิทธิ์สี่ตัว

ตัวอย่างคำนวณด้วยมือ ในการทดลองจำลองที่ใช้ตลอดบทความนี้ ค่าเฉลี่ยจริงของคะแนน (ค่าจริงในข้อมูลจำลอง) ที่สัปดาห์ที่ 0 เท่ากับ 50 ในทั้งสองกลุ่ม ที่สัปดาห์ที่ 12 ค่าเฉลี่ยจริงเท่ากับ 44 ในกลุ่มควบคุม และ 38 ในกลุ่มรักษา ให้สัปดาห์ที่ 0 เป็นจุดเริ่มต้นและสัปดาห์ที่ 12 เป็นครั้งติดตามผล

  1. ค่าเฉลี่ยกลุ่มควบคุมที่จุดเริ่มต้น

    \[ \beta_0 = 50 \]

    ค่าจุดตัดแกนคือกลุ่มควบคุมที่สัปดาห์ที่ 0

  2. ความต่างที่จุดเริ่มต้น

    \[ \beta_1 = 50 - 50 = 0 \]

    การสุ่มทำให้ความต่างจริงที่จุดเริ่มต้นเป็นศูนย์

  3. การเปลี่ยนแปลงในกลุ่มควบคุม

    \[ \beta_2 = 44 - 50 = -6 \]

    กลุ่มควบคุมดีขึ้น 6 คะแนนโดยไม่ได้รับการรักษา

  4. ผลต่างของผลต่าง

    \[ \beta_3 = (38 - 50) - (44 - 50) = -12 - (-6) = -6 \]

    กลุ่มรักษาเปลี่ยนไป -12 คะแนน เทียบกับ -6 คะแนนในกลุ่มควบคุม

  5. ผลของการรักษาที่สัปดาห์ที่ 12

    \[ \beta_1 + \beta_3 = 0 + (-6) = -6 \]

    ได้ตัวเลขเดียวกันโดยตรงจากค่าเฉลี่ยของสัปดาห์ที่ 12 คือ 38 ลบ 44 เท่ากับ -6

ผลลัพธ์: ความต่างจริงของคะแนนเฉลี่ยระหว่างกลุ่มที่สัปดาห์ที่ 12 คือ -6 คะแนน ซึ่งเท่ากับ $\beta_3$ ในที่นี้เพียงเพราะ $\beta_1 = 0$

สี่ครั้งที่วัด: สัมประสิทธิ์ปฏิกิริยาสัมพันธ์หนึ่งตัวต่อหนึ่งครั้ง

เมื่อวัดที่สัปดาห์ที่ 0, 4, 8 และ 12 แนวทางหนึ่งคือ เวลาแบบจัดกลุ่ม (categorical time) คือมีตัวบ่งชี้หนึ่งตัวต่อหนึ่งครั้งที่วัดหลังจุดเริ่มต้น โดยไม่สมมติรูปร่างใด ๆ ให้ $d_{kj}$ เป็น 1 เมื่อครั้งที่วัด $j$ เป็นครั้งที่ $k$ หลังจุดเริ่มต้น และเป็น 0 ในกรณีอื่น ดังนั้น $k$ = 1, 2 และ 3 หมายถึงสัปดาห์ที่ 4, 8 และ 12 แบบจำลองของค่าเฉลี่ยจึงเป็น

$$\mathrm{E}(Y_{ij}) = \beta_0 + \beta_1\,\mathrm{arm}_i + \sum_{k=1}^{3} \beta_{2,k}\,d_{kj} + \sum_{k=1}^{3} \beta_{3,k}\,\mathrm{arm}_i\,d_{kj}$$

ครั้งที่วัดหลังแต่ละครั้งมีการเปลี่ยนแปลงในกลุ่มควบคุมของตัวเอง คือ $\beta_{2,k}$ และมีสัมประสิทธิ์ปฏิกิริยาสัมพันธ์ของตัวเอง คือ $\beta_{3,k}$ ความต่างระหว่างกลุ่มที่ครั้งที่ $k$ คือ $\beta_1 + \beta_{3,k}$ เป็นผลรวมแบบเดิม เพียงแต่ดูทีละครั้ง เมื่อมีสัมประสิทธิ์แปดตัวสำหรับค่าเฉลี่ยของเซลล์แปดค่า แบบจำลองนี้อิ่มตัว (saturated) และถ้าไม่มีครั้งที่วัดใดขาดหาย มันจะทำซ้ำค่าเฉลี่ยของเซลล์ที่สังเกตได้อย่างตรงทุกค่า

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

ใช้เส้นตรงแทน: ผลต่างของความชันหนึ่งค่า

แนวทางที่สองถือว่าเวลาเป็นตัวเลข เรียกว่าเวลาเชิงเส้น (linear time) ให้ $t_j$ เป็นสัปดาห์ของครั้งที่วัด $j$ แบบจำลองเวลาเชิงเส้นคือ

$$\mathrm{E}(Y_{ij}) = \gamma_0 + \gamma_1\,\mathrm{arm}_i + \gamma_2\,t_j + \gamma_3\,\mathrm{arm}_i\,t_j$$

ในสมการนี้ $\gamma_0$ และ $\gamma_1$ ทำหน้าที่เหมือน $\beta_0$ และ $\beta_1$ ส่วน $\gamma_2$ คือความชันของกลุ่มควบคุมในหน่วยคะแนนต่อสัปดาห์ และ $\gamma_3$ คือผลต่างของความชันระหว่างกลุ่ม ความต่างระหว่างกลุ่มที่สัปดาห์ $t$ คือ $\gamma_1 + \gamma_3 t$ สัมประสิทธิ์ตัวเดียวจึงบรรจุเส้นทางตามเวลาทั้งหมด ราคาที่ต้องจ่ายคือข้อสมมติว่าแต่ละกลุ่มเดินตามเส้นตรง

ในการทดลองจำลอง ความต่างจริงระหว่างกลุ่มคือ -2, -4 และ -6 คะแนนที่สัปดาห์ที่ 4, 8 และ 12 ซึ่งอยู่บนเส้นตรงเดียวกัน การลงรหัสทั้งสองแบบจึงมุ่งไปยังค่าเดียวกัน เมื่อแนวโน้มโค้ง เช่นตอบสนองเร็วแล้วราบลง แบบจำลองเชิงเส้นอาจระบุความต่างที่ครั้งสุดท้ายผิดไป เวลาแบบจัดกลุ่มไม่สมมติรูปร่างใด และเหมาะกับการทดลองที่มีครั้งที่วัดคงที่ไม่กี่ครั้ง [1]

เวลาแบบจัดกลุ่มเทียบกับเวลาเชิงเส้น

การลงรหัสเวลาสองแบบเทียบกัน แถวสุดท้ายคือข้อแลกเปลี่ยนที่ต้องชั่งในแผนการวิเคราะห์
ลักษณะเวลาแบบจัดกลุ่มเวลาเชิงเส้น
ตัวแปรเวลาตัวบ่งชี้หนึ่งตัวต่อหนึ่งครั้งที่วัดหลังจุดเริ่มต้นสัปดาห์เป็นตัวเลข
พจน์ปฏิกิริยาสัมพันธ์หนึ่งตัวต่อหนึ่งครั้งที่วัดหลัง คือ $\beta_{3,k}$ผลต่างของความชันหนึ่งค่า คือ $\gamma_3$
ความต่างระหว่างกลุ่มที่ครั้งที่วัดหนึ่ง$\beta_1 + \beta_{3,k}$$\gamma_1 + \gamma_3 t$
รูปร่างที่สมมติไม่มีเส้นตรงในแต่ละกลุ่ม
ความเสี่ยงหลักสัมประสิทธิ์มากขึ้น ช่วงเชื่อมั่นกว้างขึ้นเมื่อมีครั้งที่วัดมากเกิดความเอนเอียงที่ครั้งสุดท้ายเมื่อแนวโน้มโค้ง
ลากค่าเฉลี่ยของครั้งที่วัดใดก็ได้ในกลุ่มใดก็ได้ แผงจะแสดงสัมประสิทธิ์ของเวลาแบบจัดกลุ่ม ความต่างระหว่างกลุ่มในแต่ละครั้งที่วัด และผลต่างของความชันจากแบบจำลองเวลาเชิงเส้น ลองทำให้แนวโน้มของกลุ่มหนึ่งโค้งเพื่อดูว่าการลงรหัสสองแบบให้ผลต่างกัน ค่าเริ่มต้นคือค่าเฉลี่ยที่สังเกตได้ในแต่ละครั้งที่วัดของการทดลองจำลอง (ข้อมูลจำลอง) ซึ่งเป็นค่าเดียวกับในตารางค่าเฉลี่ยที่สังเกตได้ด้านล่าง

การทดลองจำลอง: แบบจำลองผสมให้ผลอย่างไร

ส่วนที่เหลือของบทความวิเคราะห์ชุดข้อมูลจำลองชุดเดียว ชุดนี้มีผู้เข้าร่วม 300 คน กลุ่มละ 150 คน แต่ละคนถูกวัดคะแนนสี่ครั้ง รวมเป็น 1,200 แถว โดยหนึ่งแถวคือผู้เข้าร่วมหนึ่งคนในหนึ่งครั้งที่วัด ค่าเฉลี่ยจริงตรงกับตัวอย่างคำนวณด้วยมือ ความต่างจริงระหว่างกลุ่มคือ -2, -4 และ -6 คะแนนที่สัปดาห์ที่ 4, 8 และ 12

คะแนนเฉลี่ยที่สังเกตได้ แยกตามกลุ่มและสัปดาห์

ข้อมูลจำลอง คะแนนอาการเฉลี่ย ยิ่งต่ำยิ่งดี กลุ่มละ 150 คน ที่สัปดาห์ที่ 0 สองกลุ่มต่างกันไม่ถึงหนึ่งคะแนน ซึ่งเกิดจากความบังเอิญล้วน ๆ
กลุ่มสัปดาห์ที่ 0 (คะแนน)สัปดาห์ที่ 4 (คะแนน)สัปดาห์ที่ 8 (คะแนน)สัปดาห์ที่ 12 (คะแนน)
กลุ่มควบคุม50.1648.1847.1144.96
กลุ่มรักษา49.9246.1841.8837.54

ประมาณเวลาแบบจัดกลุ่มพร้อมผลสุ่ม (random effects)

ข้อมูลรายผู้เข้าร่วมไม่ได้เผยแพร่ ตารางค่าเฉลี่ยด้านบนเพียงพอสำหรับคำนวณสัมประสิทธิ์ด้วยมือ และโค้ดแสดงวิธีประมาณแบบจำลอง

แบบจำลองที่ใช้คือแบบจำลองผสมเชิงเส้น (linear mixed model) ซึ่งประมาณด้วย REML (ภาวะน่าจะเป็นสูงสุดแบบจำกัด หรือ restricted maximum likelihood ซึ่งเป็นวิธีปกติในการประมาณแบบจำลองเหล่านี้) ได้แก่แบบจำลองค่าเฉลี่ยของเวลาแบบจัดกลุ่มบวกพจน์ระดับผู้เข้าร่วมสองพจน์ ซึ่งเรียกว่าผลสุ่ม (random effects) จุดตัดแกนสุ่ม (random intercept) เลื่อนเส้นทางทั้งเส้นของผู้เข้าร่วมคนหนึ่งขึ้นหรือลง ความชันสุ่ม (random slope) เอียงเส้นนั้นในหน่วยคะแนนต่อสัปดาห์ พจน์เหล่านี้จำลองว่าคะแนนของผู้เข้าร่วมคนเดียวกันสัมพันธ์กันอย่างไร และไม่เปลี่ยนความหมายของสัมประสิทธิ์ค่าเฉลี่ย

เครื่องหมายหมวก (hat) แสดงค่าประมาณจากตัวอย่าง $\hat\beta_1$ เท่ากับ -0.24 คะแนน (ช่วงเชื่อมั่น 95% คือ -1.90 ถึง 1.42) ซึ่งเป็นความต่างที่จุดเริ่มต้นอันเกิดจากความบังเอิญ ปฏิกิริยาสัมพันธ์ของสัปดาห์ที่ 12 คือ $\hat\beta_{3,3}$ เท่ากับ -7.18 คะแนน (ช่วงเชื่อมั่น 95% คือ -8.98 ถึง -5.38)

ความต่างระหว่างกลุ่มที่สัปดาห์ที่ 12 คือ $\hat\beta_1 + \hat\beta_{3,3}$ เท่ากับ -7.42 คะแนน ตัวเลขสุดท้ายนี้เท่ากับ 37.54 ลบ 44.96 จากตาราง เพราะแบบจำลองค่าเฉลี่ยอิ่มตัว

โค้ดด้านล่างยังประมาณวิธีใช้คะแนนสัปดาห์ที่ 0 สามวิธี (ดูหัวข้อ 'สามวิธีใช้คะแนนสัปดาห์ที่ 0') และความแปรปรวนร่วมแบบไม่มีโครงสร้าง (unstructured covariance) ระหว่างจุดตัดแกนสุ่มกับความชันสุ่ม (ดูหัวข้อ 'ความสัมพันธ์ระหว่างครั้งที่วัด และสิ่งที่เปลี่ยนไปเมื่อมีครั้งที่วัดขาดหาย')

ความต่างระหว่างกลุ่มในแต่ละครั้งที่วัด: ค่าจริงและค่าประมาณ

ข้อมูลจำลอง ช่วงเชื่อมั่น 95% แต่ละช่วงครอบคลุมค่าจริงของมัน การทดสอบร่วมว่าสัมประสิทธิ์ปฏิกิริยาสัมพันธ์ทั้งสามเป็นศูนย์ ให้ค่าสถิติไคสแควร์ 70.56 ที่องศาอิสระ 3
สัปดาห์ความต่างจริง (คะแนน)ความต่างที่ประมาณได้ (คะแนน)ช่วงเชื่อมั่น 95% (คะแนน)
00-0.24-1.90 ถึง 1.42
4-2-2.00-3.67 ถึง -0.33
8-4-5.23-7.02 ถึง -3.44
12-6-7.42-9.41 ถึง -5.43

Stata: แบบจำลองผสม คอนทราสต์รายครั้งที่วัด และวิธีใช้คะแนนที่จุดเริ่มต้นสำหรับสัปดาห์ที่ 12

โค้ด Stata d2_lmm.do
* Simulated trial: 300 participants, 1:1, symptom score at weeks 0, 4, 8, 12 (lower is better).
* Simulated data only: nothing here is evidence about any real drug or patient.
version 18
clear all
set more off
set linesize 120

* Load the simulated data (long format: one row per participant-visit).
import delimited using trial.csv, clear asdouble
label define armlab 0 "control" 1 "treatment"
label values arm armlab

* ---------------------------------------------------------------- mixed model, arm x visit
* Categorical visit, arm-by-visit interaction, random intercept and random slope on week (REML).
* stddeviations prints the random effects as standard deviations and their correlation.
mixed score i.arm##i.visit || id: week, covariance(unstructured) reml stddeviations
* beta1 = 1.arm: the difference between arms at week 0, the reference visit.
lincom 1.arm
* beta3,3 = 1.arm#3.visit: the week-12 interaction, a difference in differences.
lincom 1.arm#3.visit
* Difference between arms at each visit, beta1 + beta3,k (k = 1, 2, 3 for weeks 4, 8, 12).
contrast r.arm@visit, effects
forvalues k = 1/3 {
    lincom 1.arm + 1.arm#`k'.visit
}
* Joint Wald test that the three interaction coefficients are zero.
testparm 1.arm#i.visit

* ---------------------------------------------------------------- constrained baseline
* Same random-effects structure, but one common baseline mean for both arms.
generate byte trt_wk4 = arm * (visit == 1)
generate byte trt_wk8 = arm * (visit == 2)
generate byte trt_wk12 = arm * (visit == 3)
mixed score i.visit trt_wk4 trt_wk8 trt_wk12 || id: week, covariance(unstructured) reml stddeviations
lincom trt_wk12

* ---------------------------------------------------------------- week-12 ANCOVA and change score
* Baseline score copied to every row of the participant.
bysort id (visit): generate double score0 = score[1]
generate double change = score - score0
* ANCOVA: week-12 score on arm, adjusted for the baseline score (OLS).
regress score i.arm score0 if visit == 3
* Change score: (week-12 minus week-0) on arm, no baseline adjustment (OLS).
regress change i.arm if visit == 3
ผลลัพธ์จากการรัน d2_lmm.log
. * Simulated trial: 300 participants, 1:1, symptom score at weeks 0, 4, 8, 12
> (lower is better).
. * Simulated data only: nothing here is evidence about any real drug or patien
> t.
. version 18

. clear all

. set more off

. set linesize 120

.
. * Load the simulated data (long format: one row per participant-visit).
. import delimited using trial.csv, clear asdouble
(encoding automatically selected: ISO-8859-1)
(6 vars, 1,200 obs)

. label define armlab 0 "control" 1 "treatment"

. label values arm armlab

.
. * ---------------------------------------------------------------- mixed model, arm x visit
. * Categorical visit, arm-by-visit interaction, random intercept and random slope on week (REML).
. * stddeviations prints the random effects as standard deviations and their correlation.
. mixed score i.arm##i.visit || id: week, covariance(unstructured) reml stddeviations

Performing EM optimization ...

Performing gradient-based optimization:
Iteration 0:  Log restricted-likelihood = -3829.3213
Iteration 1:  Log restricted-likelihood = -3829.3199
Iteration 2:  Log restricted-likelihood = -3829.3199

Computing standard errors ...

Mixed-effects REML regression                        Number of obs    =  1,200
Group variable: id                                   Number of groups =    300
                                                     Obs per group:
                                                                  min =      4
                                                                  avg =    4.0
                                                                  max =      4
                                                     Wald chi2(7)     = 460.58
Log restricted-likelihood = -3829.3199               Prob > chi2      = 0.0000

----------------------------------------------------------------------------------
           score | Coefficient  Std. err.      z    P>|z|     [95% conf. interval]
-----------------+----------------------------------------------------------------
             arm |
      treatment  |  -.2397333   .8462269    -0.28   0.777    -1.898308    1.418841
                 |
           visit |
              1  |    -1.9842   .4868589    -4.08   0.000    -2.938426   -1.029974
              2  |  -3.056333   .5534852    -5.52   0.000    -4.141144   -1.971522
              3  |     -5.208    .649515    -8.02   0.000    -6.481026   -3.934974
                 |
       arm#visit |
    treatment#1  |  -1.761667   .6885225    -2.56   0.011    -3.111146   -.4121874
    treatment#2  |  -4.987867   .7827463    -6.37   0.000    -6.522021   -3.453712
    treatment#3  |  -7.177467   .9185529    -7.81   0.000    -8.977797   -5.377136
                 |
           _cons |   50.16413   .5983728    83.83   0.000     48.99134    51.33692
----------------------------------------------------------------------------------

------------------------------------------------------------------------------
  Random-effects parameters  |   Estimate   Std. err.     [95% conf. interval]
-----------------------------+------------------------------------------------
id: Unstructured             |
                    sd(week) |   .4654107   .0387788      .3952873    .5479739
                   sd(_cons) |   6.137018   .3306216       5.52205    6.820472
            corr(week,_cons) |  -.1110897    .092756     -.2872992    .0723929
-----------------------------+------------------------------------------------
                sd(Residual) |    4.00556   .1160179      3.784503     4.23953
------------------------------------------------------------------------------
LR test vs. linear model: chi2(3) = 684.31                Prob > chi2 = 0.0000

Note: LR test is conservative and provided only for reference.

. * beta1 = 1.arm: the difference between arms at week 0, the reference visit.
. lincom 1.arm

 ( 1)  [score]1.arm = 0

------------------------------------------------------------------------------
       score | Coefficient  Std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
         (1) |  -.2397333   .8462269    -0.28   0.777    -1.898308    1.418841
------------------------------------------------------------------------------

. * beta3,3 = 1.arm#3.visit: the week-12 interaction, a difference in differences.
. lincom 1.arm#3.visit

 ( 1)  [score]1.arm#3.visit = 0

------------------------------------------------------------------------------
       score | Coefficient  Std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
         (1) |  -7.177467   .9185529    -7.81   0.000    -8.977797   -5.377136
------------------------------------------------------------------------------

. * Difference between arms at each visit, beta1 + beta3,k (k = 1, 2, 3 for weeks 4, 8, 12).
. contrast r.arm@visit, effects

Contrasts of marginal linear predictions

Margins: asbalanced

-------------------------------------------------------------
                          |         df        chi2     P>chi2
--------------------------+----------------------------------
score                     |
                arm@visit |
(treatment vs control) 0  |          1        0.08     0.7769
(treatment vs control) 1  |          1        5.50     0.0190
(treatment vs control) 2  |          1       32.80     0.0000
(treatment vs control) 3  |          1       53.39     0.0000
                   Joint  |          4       79.42     0.0000
-------------------------------------------------------------

-------------------------------------------------------------------------------------------
                          |   Contrast   Std. err.      z    P>|z|     [95% conf. interval]
--------------------------+----------------------------------------------------------------
score                     |
                arm@visit |
(treatment vs control) 0  |  -.2397333   .8462269    -0.28   0.777    -1.898308    1.418841
(treatment vs control) 1  |    -2.0014   .8535013    -2.34   0.019    -3.674232   -.3285682
(treatment vs control) 2  |    -5.2276   .9128241    -5.73   0.000    -7.016702   -3.438498
(treatment vs control) 3  |    -7.4172   1.015111    -7.31   0.000    -9.406781   -5.427619
-------------------------------------------------------------------------------------------

. forvalues k = 1/3 {
  2.     lincom 1.arm + 1.arm#`k'.visit
  3. }

 ( 1)  [score]1.arm + [score]1.arm#1.visit = 0

------------------------------------------------------------------------------
       score | Coefficient  Std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
         (1) |    -2.0014   .8535013    -2.34   0.019    -3.674232   -.3285682
------------------------------------------------------------------------------

 ( 1)  [score]1.arm + [score]1.arm#2.visit = 0

------------------------------------------------------------------------------
       score | Coefficient  Std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
         (1) |    -5.2276   .9128241    -5.73   0.000    -7.016702   -3.438498
------------------------------------------------------------------------------

 ( 1)  [score]1.arm + [score]1.arm#3.visit = 0

------------------------------------------------------------------------------
       score | Coefficient  Std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
         (1) |    -7.4172   1.015111    -7.31   0.000    -9.406781   -5.427619
------------------------------------------------------------------------------

. * Joint Wald test that the three interaction coefficients are zero.
. testparm 1.arm#i.visit

 ( 1)  [score]1.arm#1.visit = 0
 ( 2)  [score]1.arm#2.visit = 0
 ( 3)  [score]1.arm#3.visit = 0

           chi2(  3) =   70.56
         Prob > chi2 =    0.0000

.
. * ---------------------------------------------------------------- constrained baseline
. * Same random-effects structure, but one common baseline mean for both arms.
. generate byte trt_wk4 = arm * (visit == 1)

. generate byte trt_wk8 = arm * (visit == 2)

. generate byte trt_wk12 = arm * (visit == 3)

. mixed score i.visit trt_wk4 trt_wk8 trt_wk12 || id: week, covariance(unstructured) reml stddeviations

Performing EM optimization ...

Performing gradient-based optimization:
Iteration 0:  Log restricted-likelihood = -3830.1128
Iteration 1:  Log restricted-likelihood = -3830.1114
Iteration 2:  Log restricted-likelihood = -3830.1114

Computing standard errors ...

Mixed-effects REML regression                        Number of obs    =  1,200
Group variable: id                                   Number of groups =    300
                                                     Obs per group:
                                                                  min =      4
                                                                  avg =    4.0
                                                                  max =      4
                                                     Wald chi2(6)     = 460.62
Log restricted-likelihood = -3830.1114               Prob > chi2      = 0.0000

----------------------------------------------------------------------------------
           score | Coefficient  Std. err.      z    P>|z|     [95% conf. interval]
-----------------+----------------------------------------------------------------
           visit |
              1  |  -1.945501   .4673096    -4.16   0.000    -2.861411   -1.029591
              2  |  -3.014831   .5337274    -5.65   0.000    -4.060917   -1.968744
              3  |  -5.163694   .6303518    -8.19   0.000    -6.399161   -3.928227
                 |
         trt_wk4 |  -1.839065   .6320851    -2.91   0.004    -3.077929   -.6002009
         trt_wk8 |  -5.070871   .7258901    -6.99   0.000     -6.49359   -3.648153
        trt_wk12 |  -7.266078   .8636518    -8.41   0.000    -8.958804   -5.573352
           _cons |   50.04427   .4225711   118.43   0.000     49.21604    50.87249
----------------------------------------------------------------------------------

------------------------------------------------------------------------------
  Random-effects parameters  |   Estimate   Std. err.     [95% conf. interval]
-----------------------------+------------------------------------------------
id: Unstructured             |
                    sd(week) |   .4652983   .0387653      .3951986    .5478321
                   sd(_cons) |   6.125979   .3297757       5.51256    6.807657
            corr(week,_cons) |  -.1098813   .0927455     -.2861117    .0735397
-----------------------------+------------------------------------------------
                sd(Residual) |   4.005283   .1159944       3.78427    4.239204
------------------------------------------------------------------------------
LR test vs. linear model: chi2(3) = 684.45                Prob > chi2 = 0.0000

Note: LR test is conservative and provided only for reference.

. lincom trt_wk12

 ( 1)  [score]trt_wk12 = 0

------------------------------------------------------------------------------
       score | Coefficient  Std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
         (1) |  -7.266078   .8636518    -8.41   0.000    -8.958804   -5.573352
------------------------------------------------------------------------------

.
. * ---------------------------------------------------------------- week-12 ANCOVA and change score
. * Baseline score copied to every row of the participant.
. bysort id (visit): generate double score0 = score[1]

. generate double change = score - score0

. * ANCOVA: week-12 score on arm, adjusted for the baseline score (OLS).
. regress score i.arm score0 if visit == 3

      Source |       SS           df       MS      Number of obs   =       300
-------------+----------------------------------   F(2, 297)       =     96.75
       Model |  11054.4924         2  5527.24619   Prob > F        =    0.0000
    Residual |  16967.1828       297  57.1285616   R-squared       =    0.3945
-------------+----------------------------------   Adj R-squared   =    0.3904
       Total |  28021.6752       299  93.7179772   Root MSE        =    7.5583

------------------------------------------------------------------------------
       score | Coefficient  Std. err.      t    P>|t|     [95% conf. interval]
-------------+----------------------------------------------------------------
         arm |
  treatment  |   -7.25869   .8728811    -8.32   0.000    -8.976506   -5.540875
      score0 |   .6611917   .0600397    11.01   0.000     .5430346    .7793488
       _cons |   11.78802   3.074414     3.83   0.000     5.737628    17.83842
------------------------------------------------------------------------------

. * Change score: (week-12 minus week-0) on arm, no baseline adjustment (OLS).
. regress change i.arm if visit == 3

      Source |       SS           df       MS      Number of obs   =       300
-------------+----------------------------------   F(1, 298)       =     61.29
       Model |  3863.70208         1  3863.70208   Prob > F        =    0.0000
    Residual |  18786.4013       298  63.0416152   R-squared       =    0.1706
-------------+----------------------------------   Adj R-squared   =    0.1678
       Total |  22650.1034       299  75.7528542   Root MSE        =    7.9399

------------------------------------------------------------------------------
      change | Coefficient  Std. err.      t    P>|t|     [95% conf. interval]
-------------+----------------------------------------------------------------
         arm |
  treatment  |  -7.177467   .9168178    -7.83   0.000    -8.981724   -5.373209
       _cons |     -5.208   .6482881    -8.03   0.000    -6.483803   -3.932197
------------------------------------------------------------------------------
ข้อมูลจำลอง ผลลัพธ์จากโค้ดที่แสดง คำสั่ง mixed ประมาณเวลาแบบจัดกลุ่มพร้อมจุดตัดแกนสุ่มและความชันสุ่มด้วย REML ส่วน contrast และ lincom พิมพ์ความต่างระหว่างกลุ่มในแต่ละครั้งที่วัด และ testparm ให้การทดสอบร่วม การประมาณสามชุดสุดท้ายให้ค่าประมาณที่สัปดาห์ที่ 12 จากจุดเริ่มต้นร่วมแบบบังคับ ANCOVA และคะแนนการเปลี่ยนแปลง ค่าประมาณ ค่าคลาดเคลื่อนมาตรฐาน (standard error) และช่วงเชื่อมั่นทุกค่าในตารางผลของแบบจำลองในบทความนี้พิมพ์อยู่ในผลลัพธ์นี้

R: แบบจำลองชุดเดียวกันด้วย lme4

โค้ด R d2_lmm_r.R
# Simulated trial: 300 participants, 1:1, symptom score at weeks 0, 4, 8, 12 (lower is better).
# Simulated data only: nothing here is evidence about any real drug or patient.
suppressPackageStartupMessages(library(lme4))
z975 <- qnorm(0.975)

# Load the simulated data (long format: one row per participant-visit).
trial <- read.csv("trial.csv")
trial <- trial[order(trial$id, trial$visit), ]
trial$visitf <- factor(trial$visit)

# ---------------------------------------------------------------- mixed model, arm x visit
# Categorical visit, arm-by-visit interaction, random intercept and random slope on week (REML).
lmm <- lmer(score ~ arm * visitf + (week | id), data = trial, REML = TRUE)
print(summary(lmm), correlation = FALSE)
b <- fixef(lmm)
V <- as.matrix(vcov(lmm))
# Wald estimate, SE and 95% CI (normal) of a sum of coefficients.
lc <- function(terms) {
  L <- setNames(numeric(length(b)), names(b))
  L[terms] <- 1
  est <- sum(L * b)
  se <- sqrt(drop(t(L) %*% V %*% L))
  c(estimate = est, se = se, lo = est - z975 * se, hi = est + z975 * se)
}
# beta1 = arm: the difference between arms at week 0, the reference visit.
print(round(lc("arm"), 4))
# beta3,3 = arm:visitf3: the week-12 interaction, a difference in differences.
print(round(lc("arm:visitf3"), 4))
# Difference between arms at each visit, beta1 + beta3,k (k = 1, 2, 3 for weeks 4, 8, 12).
diffs <- t(sapply(0:3, function(k) lc(if (k == 0) "arm" else c("arm", paste0("arm:visitf", k)))))
rownames(diffs) <- paste("week", 4 * (0:3))
print(round(diffs, 4))
# Joint Wald test that the three interaction coefficients are zero.
idx <- paste0("arm:visitf", 1:3)
chi2 <- drop(t(b[idx]) %*% solve(V[idx, idx]) %*% b[idx])
cat(sprintf("Joint test: chi2(3) = %.4f, p = %.4g\n", chi2, pchisq(chi2, 3, lower.tail = FALSE)))

# ---------------------------------------------------------------- constrained baseline
# Same random-effects structure, but one common baseline mean for both arms.
trial$trt_wk4 <- trial$arm * (trial$visit == 1)
trial$trt_wk8 <- trial$arm * (trial$visit == 2)
trial$trt_wk12 <- trial$arm * (trial$visit == 3)
cb <- lmer(score ~ visitf + trt_wk4 + trt_wk8 + trt_wk12 + (week | id), data = trial, REML = TRUE)
est <- fixef(cb)[["trt_wk12"]]
se <- sqrt(as.matrix(vcov(cb))["trt_wk12", "trt_wk12"])
print(round(c(estimate = est, se = se, lo = est - z975 * se, hi = est + z975 * se), 4))

# ---------------------------------------------------------------- week-12 ANCOVA and change score
# One row per participant: baseline and week-12 scores side by side.
wide <- data.frame(id = trial$id[trial$visit == 0], arm = trial$arm[trial$visit == 0],
                   score0 = trial$score[trial$visit == 0], score12 = trial$score[trial$visit == 3])
# ANCOVA: week-12 score on arm, adjusted for the baseline score (OLS).
anc <- lm(score12 ~ arm + score0, data = wide)
print(summary(anc))
print(round(confint(anc), 4))
# Change score: (week-12 minus week-0) on arm, no baseline adjustment (OLS).
chg <- lm(I(score12 - score0) ~ arm, data = wide)
print(summary(chg))
print(round(confint(chg), 4))
ผลลัพธ์จากการรัน d2_lmm_r.log
> suppressPackageStartupMessages(library(lme4))

> z975 <- qnorm(0.975)

> trial <- read.csv("trial.csv")

> trial <- trial[order(trial$id, trial$visit), ]

> trial$visitf <- factor(trial$visit)

> lmm <- lmer(score ~ arm * visitf + (week | id), data = trial,
+     REML = TRUE)

> print(summary(lmm), correlation = FALSE)
Linear mixed model fit by REML ['lmerMod']
Formula: score ~ arm * visitf + (week | id)
   Data: trial

REML criterion at convergence: 7658.6

Scaled residuals:
    Min      1Q  Median      3Q     Max
-2.8884 -0.5185 -0.0007  0.5334  3.1753

Random effects:
 Groups   Name        Variance Std.Dev. Corr
 id       (Intercept) 37.6629  6.1370
          week         0.2166  0.4654   -0.11
 Residual             16.0445  4.0056
Number of obs: 1200, groups:  id, 300

Fixed effects:
            Estimate Std. Error t value
(Intercept)  50.1641     0.5984  83.834
arm          -0.2397     0.8462  -0.283
visitf1      -1.9842     0.4869  -4.076
visitf2      -3.0563     0.5535  -5.522
visitf3      -5.2080     0.6495  -8.018
arm:visitf1  -1.7617     0.6885  -2.559
arm:visitf2  -4.9879     0.7827  -6.372
arm:visitf3  -7.1775     0.9186  -7.814

> b <- fixef(lmm)

> V <- as.matrix(vcov(lmm))

> lc <- function(terms) {
+     L <- setNames(numeric(length(b)), names(b))
+     L[terms] <- 1
+     est <- sum(L * b)
+     se <- sqrt(drop(t(L) %*% V %*% L))
+     c(estimate = est, se = se, lo = est - z975 * se, hi = est +
+         z975 * se)
+ }

> print(round(lc("arm"), 4))
estimate       se       lo       hi
 -0.2397   0.8462  -1.8983   1.4188

> print(round(lc("arm:visitf3"), 4))
estimate       se       lo       hi
 -7.1775   0.9186  -8.9778  -5.3771

> diffs <- t(sapply(0:3, function(k) lc(if (k == 0) "arm" else c("arm",
+     paste0("arm:visitf", k)))))

> rownames(diffs) <- paste("week", 4 * (0:3))

> print(round(diffs, 4))
        estimate     se      lo      hi
week 0   -0.2397 0.8462 -1.8983  1.4188
week 4   -2.0014 0.8535 -3.6742 -0.3286
week 8   -5.2276 0.9128 -7.0167 -3.4385
week 12  -7.4172 1.0151 -9.4068 -5.4276

> idx <- paste0("arm:visitf", 1:3)

> chi2 <- drop(t(b[idx]) %*% solve(V[idx, idx]) %*%
+     b[idx])

> cat(sprintf("Joint test: chi2(3) = %.4f, p = %.4g\n",
+     chi2, pchisq(chi2, 3, lower.tail = FALSE)))
Joint test: chi2(3) = 70.5554, p = 3.246e-15

> trial$trt_wk4 <- trial$arm * (trial$visit == 1)

> trial$trt_wk8 <- trial$arm * (trial$visit == 2)

> trial$trt_wk12 <- trial$arm * (trial$visit == 3)

> cb <- lmer(score ~ visitf + trt_wk4 + trt_wk8 + trt_wk12 +
+     (week | id), data = trial, REML = TRUE)

> est <- fixef(cb)[["trt_wk12"]]

> se <- sqrt(as.matrix(vcov(cb))["trt_wk12", "trt_wk12"])

> print(round(c(estimate = est, se = se, lo = est -
+     z975 * se, hi = est + z975 * se), 4))
estimate       se       lo       hi
 -7.2661   0.8636  -8.9588  -5.5734

> wide <- data.frame(id = trial$id[trial$visit == 0],
+     arm = trial$arm[trial$visit == 0], score0 = trial$score[trial$visit ==
+         0], score12 = trial$score[trial$visit == 3])

> anc <- lm(score12 ~ arm + score0, data = wide)

> print(summary(anc))

Call:
lm(formula = score12 ~ arm + score0, data = wide)

Residuals:
     Min       1Q   Median       3Q      Max
-24.6458  -5.1035   0.8545   4.7741  15.7149

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept) 11.78802    3.07441   3.834 0.000154 ***
arm         -7.25869    0.87288  -8.316 3.32e-15 ***
score0       0.66119    0.06004  11.013  < 2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 7.558 on 297 degrees of freedom
Multiple R-squared:  0.3945,	Adjusted R-squared:  0.3904
F-statistic: 96.75 on 2 and 297 DF,  p-value: < 2.2e-16


> print(round(confint(anc), 4))
              2.5 %  97.5 %
(Intercept)  5.7376 17.8384
arm         -8.9765 -5.5409
score0       0.5430  0.7793

> chg <- lm(I(score12 - score0) ~ arm, data = wide)

> print(summary(chg))

Call:
lm(formula = I(score12 - score0) ~ arm, data = wide)

Residuals:
     Min       1Q   Median       3Q      Max
-25.0045  -5.0189   0.9755   5.0555  16.9255

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)  -5.2080     0.6483  -8.033 2.23e-14 ***
arm          -7.1775     0.9168  -7.829 8.69e-14 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 7.94 on 298 degrees of freedom
Multiple R-squared:  0.1706,	Adjusted R-squared:  0.1678
F-statistic: 61.29 on 1 and 298 DF,  p-value: 8.689e-14


> print(round(confint(chg), 4))
              2.5 %  97.5 %
(Intercept) -6.4838 -3.9322
arm         -8.9817 -5.3732
ข้อมูลจำลอง ผลลัพธ์จากโค้ดที่แสดง ฟังก์ชัน lmer ประมาณแบบจำลองเดียวกัน และผลรวมของสัมประสิทธิ์ที่เขียนออกมาเองให้ผลตรงกับคอนทราสต์ของ Stata การทดสอบร่วม จุดเริ่มต้นร่วมแบบบังคับ ANCOVA และคะแนนการเปลี่ยนแปลงตรงกับผลลัพธ์ของ Stata

สามวิธีใช้คะแนนสัปดาห์ที่ 0

การทดลองที่วัดผลลัพธ์ที่จุดเริ่มต้นสามารถใช้คะแนนนั้นได้อย่างน้อยสามวิธี เมื่อเป้าหมายคือความต่างที่สัปดาห์ที่ 12 [2, 3]

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

ความต่างระหว่างกลุ่มที่สัปดาห์ที่ 12 แยกตามวิธีใช้คะแนนที่จุดเริ่มต้น

ข้อมูลจำลอง ค่าจริงคือ -6 คะแนน วิธีใช้คะแนนที่จุดเริ่มต้นให้ผลใกล้เคียงกันมาก ANCOVA และจุดเริ่มต้นร่วมแบบบังคับมีช่วงเชื่อมั่นแคบที่สุด และคอนทราสต์ที่ไม่ปรับมีช่วงกว้างที่สุด
วิธีค่าประมาณ (คะแนน)ค่าคลาดเคลื่อนมาตรฐาน (คะแนน)ช่วงเชื่อมั่น 95% (คะแนน)
แบบจำลองผสม คอนทราสต์ที่ไม่ปรับที่สัปดาห์ที่ 12-7.421.02-9.41 ถึง -5.43
ANCOVA-7.260.87-8.98 ถึง -5.54
คะแนนการเปลี่ยนแปลง-7.180.92-8.98 ถึง -5.37
จุดเริ่มต้นร่วมแบบบังคับ-7.270.86-8.96 ถึง -5.57

ค่าประมาณทั้งสามเชื่อมโยงกันอย่างไร

สำหรับข้อมูลครบถ้วนชุดนี้ ความเชื่อมโยงเป็นไปอย่างตรงทุกตัวเลข ค่าประมาณของคะแนนการเปลี่ยนแปลงคือ -7.18 เท่ากับ $\hat\beta_{3,3}$ เพราะทั้งสองคือการเปลี่ยนแปลงในกลุ่มรักษาลบการเปลี่ยนแปลงในกลุ่มควบคุม ช่วงเชื่อมั่นของคะแนนการเปลี่ยนแปลงต่างกันที่ทศนิยมตำแหน่งที่สอง เพราะได้จากการถดถอยแยกอีกชุดหนึ่ง

ค่าประมาณของ ANCOVA เท่ากับความต่างดิบที่สัปดาห์ที่ 12 ลบ 0.66 คูณความต่างที่จุดเริ่มต้น โดย 0.66 คือสัมประสิทธิ์ของคะแนนที่จุดเริ่มต้นที่ประมาณได้ ส่วนคะแนนการเปลี่ยนแปลงตรึงตัวคูณนั้นไว้ที่ 1

เพราะ ANCOVA ประมาณตัวคูณจากข้อมูล จึงมักแม่นยำที่สุดในบรรดาวิธีง่าย ๆ [2] ค่าประมาณจากวิธีจุดเริ่มต้นร่วมแบบบังคับคือ -7.27 ใกล้เคียงกับ ANCOVA และมีค่าคลาดเคลื่อนมาตรฐานใกล้กัน

คอนทราสต์ที่สัปดาห์ที่ 12 แบบไม่ปรับจากแบบจำลองผสมมีค่าคลาดเคลื่อนมาตรฐานมากที่สุดคือ 1.02 คะแนน และช่วงเชื่อมั่นกว้างที่สุด มันเปรียบเทียบค่าเฉลี่ยของสัปดาห์ที่ 12 โดยตรงและไม่ใช้ข้อมูลในคะแนนที่จุดเริ่มต้น ซึ่ง ANCOVA และจุดเริ่มต้นร่วมแบบบังคับใช้ตัดความแปรปรวนจากความบังเอิญออกบางส่วน

ความสัมพันธ์ระหว่างครั้งที่วัด และสิ่งที่เปลี่ยนไปเมื่อมีครั้งที่วัดขาดหาย

คะแนนของผู้เข้าร่วมคนเดียวกันสัมพันธ์กัน คนที่เริ่มสูงมักอยู่ในระดับสูงต่อไป หากถือว่า 1,200 แถวเป็นคนอิสระ 1,200 คน ค่าคลาดเคลื่อนมาตรฐานจะผิด แบบจำลองจึงต้องมีโครงสร้างความแปรปรวนร่วม (covariance structure) ของคะแนนข้ามครั้งที่วัด

แบบจำลองข้างต้นใช้จุดตัดแกนสุ่มและความชันสุ่มพร้อม ความแปรปรวนร่วมแบบไม่มีโครงสร้าง (unstructured covariance) ระหว่างทั้งสอง ความแปรปรวนและสหสัมพันธ์ของมันจึงถูกประมาณอย่างอิสระ ส่วนเบี่ยงเบนมาตรฐานที่ประมาณได้คือ 6.14 คะแนนสำหรับจุดตัดแกน และ 0.47 คะแนนต่อสัปดาห์สำหรับความชัน สหสัมพันธ์ระหว่างทั้งสองคือ -0.11 และส่วนเบี่ยงเบนมาตรฐานของส่วนเหลือ (residual) คือ 4.01 คะแนน

ทางเลือกที่ใช้กันแพร่หลายคือ MMRM หรือแบบจำลองผสมสำหรับการวัดซ้ำ (mixed model for repeated measures) ซึ่งคงเวลาแบบจัดกลุ่มไว้ ตัดผลสุ่มออก และใส่ความแปรปรวนร่วมแบบไม่มีโครงสร้างบนส่วนเหลือ แต่ละครั้งที่วัดมีความแปรปรวนของตัวเอง และแต่ละคู่ของครั้งที่วัดมีสหสัมพันธ์ของตัวเอง [1]

เมื่อข้อมูลครบถ้วนและแบบจำลองค่าเฉลี่ยอิ่มตัว ทั้งสองแบบให้ค่าประมาณจุดเท่ากัน และต่างกันเฉพาะค่าคลาดเคลื่อนมาตรฐาน เมื่อมีครั้งที่วัดขาดหาย ค่าประมาณก็เปลี่ยนด้วย แบบจำลองที่อิงภาวะน่าจะเป็น (likelihood-based model) เลือกค่าพารามิเตอร์ที่ทำให้คะแนนที่สังเกตได้มีโอกาสเกิดขึ้นสูงที่สุด แบบจำลองนี้ใช้ทุกครั้งที่วัดที่สังเกตได้ของผู้เข้าร่วมแต่ละคน จึงยืมข้อมูล (borrow strength) จากครั้งเหล่านั้น

การยืมข้อมูลจากครั้งที่วัดที่สังเกตได้ใช้ได้ภายใต้ข้อมูลขาดหายแบบสุ่ม (missing at random, MAR) คือการขาดหายของครั้งที่วัดขึ้นกับข้อมูลที่สังเกตได้แล้วเท่านั้น และยังต้องกำหนดแบบจำลองค่าเฉลี่ยและความแปรปรวนร่วมถูกต้องด้วย ดังนั้นจุดตัดแกนสุ่มและความชันสุ่มที่เข้ากับข้อมูลได้ไม่ดีอาจทำให้คอนทราสต์ที่สัปดาห์ที่ 12 เปลี่ยนไปเมื่อมีครั้งที่วัดขาดหาย นี่เป็นเหตุผลหนึ่งที่มักกำหนดความแปรปรวนร่วมแบบไม่มีโครงสร้างข้ามครั้งที่วัดไว้ล่วงหน้าเมื่อคาดว่าจะมีผู้ถอนตัว [1]

ระบุครั้งที่วัดไว้ใน estimand

Estimand (ปริมาณเป้าหมายของการประมาณ) คือปริมาณที่แน่ชัดซึ่งการศึกษาตั้งใจประมาณ ภาคผนวก ICH E9(R1) อธิบาย estimand ด้วยองค์ประกอบห้าประการ ได้แก่ การรักษา ประชากร ตัวแปร (ผลลัพธ์ที่วัด) การจัดการกับเหตุการณ์ระหว่างการศึกษา (intercurrent events) และมาตรวัดสรุประดับประชากร (population-level summary) [4] เหตุการณ์ระหว่างการศึกษาคือเหตุการณ์ที่เกิดหลังเริ่มการรักษา เช่นการหยุดการรักษาหรือการใช้ยาเพิ่มเติม ที่มีผลต่อการวัดผลลัพธ์ได้หรือไม่ หรือต่อวิธีอ่านผลลัพธ์

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

เมื่อระบุครั้งที่วัดแล้ว ค่าประมาณคือคอนทราสต์ที่ครั้งนั้น ได้แก่ $\hat\beta_1 + \hat\beta_{3,k}$ หรือสัมประสิทธิ์ของกลุ่มจาก ANCOVA ค่าเฉลี่ยตลอดสัปดาห์ที่ 4, 8 และ 12 เป็น estimand อีกแบบ ซึ่งคำนวณเป็นการรวมเชิงเส้น (linear combination) หมายถึงผลรวมถ่วงน้ำหนักของสัมประสิทธิ์ (ในที่นี้คือค่าเฉลี่ยของความต่างหลังจุดเริ่มต้นทั้งสามค่า พร้อมช่วงเชื่อมั่นของมันเอง)

ความเข้าใจผิดที่พบบ่อยและวิธีแก้

  • "beta1 คือผลของการรักษา"

    เมื่อมีปฏิกิริยาสัมพันธ์ สัมประสิทธิ์ของกลุ่มอ่านที่ครั้งที่วัดอ้างอิง ที่จุดเริ่มต้นก่อนการรักษา มันวัดความไม่สมดุลที่เกิดจากความบังเอิญ

    วิธีแก้: ในแบบจำลองที่มีกลุ่มการรักษา ครั้งที่วัด และปฏิกิริยาสัมพันธ์ระหว่างทั้งสอง beta1 คือผลต่างระหว่างกลุ่ม ณ ครั้งที่วัดอ้างอิง ผลของการรักษา ณ ครั้งที่วัดหลังจากนั้นคือ beta1 บวกสัมประสิทธิ์ปฏิกิริยาสัมพันธ์ของครั้งนั้น และ estimand ต้องระบุครั้งที่วัดเสมอ

  • "beta3 คือผลของการรักษาเสมอ"

    ในการทดลองแบบสุ่มที่วัดคะแนนที่จุดเริ่มต้นก่อนการรักษา $\hat\beta_{3,k}$ คือค่าประมาณแบบคะแนนการเปลี่ยนแปลงของความต่างที่สัปดาห์ $k$ ค่าเดียวกัน คือ -7.18 คะแนนที่สัปดาห์ที่ 12 เทียบกับ -7.42 จาก $\hat\beta_1 + \hat\beta_{3,3}$ ทั้งสองค่าต่างกันเพียงเพราะความไม่สมดุลที่จุดเริ่มต้นซึ่งเกิดจากความบังเอิญ และ ANCOVA (-7.26) หรือจุดเริ่มต้นร่วมแบบบังคับ (-7.27) มักแม่นยำกว่า การอ่าน $\beta_{3,k}$ ตัวเดียวเป็นผลของการรักษาจะผิดเมื่อกลุ่มไม่ได้มาจากการสุ่ม เมื่อครั้งที่วัดอ้างอิงอยู่หลังเริ่มการรักษา หรือเมื่อไม่ได้วัดค่าเริ่มต้นก่อนการรักษา

    วิธีแก้: เมื่อมีครั้งที่วัดเริ่มต้น ผลของการรักษาที่ครั้งหลังคือผลรวม $\beta_1 + \beta_{3,k}$ ซึ่งเท่ากับ $\beta_{3,k}$ ก็ต่อเมื่อ $\beta_1 = 0$

  • "สัมประสิทธิ์ของกลุ่มคือผลเฉลี่ยตลอดทุกครั้งที่วัด"

    เมื่อมีปฏิกิริยาสัมพันธ์ในแบบจำลอง ไม่มีสัมประสิทธิ์ตัวเดียวที่ใช้ได้กับทุกครั้งที่วัด

    วิธีแก้: ระบุค่าเฉลี่ยนั้นเป็น estimand ของมันเอง และคำนวณเป็นการรวมเชิงเส้นพร้อมช่วงเชื่อมั่นของมันเอง

  • "สัมประสิทธิ์ของกลุ่มคือผลที่ครั้งสุดท้าย"

    จริงเฉพาะเมื่อครั้งสุดท้ายเป็นระดับอ้างอิง การเปลี่ยนรหัสเปลี่ยนสัมประสิทธิ์ แต่ไม่เปลี่ยนค่าเฉลี่ยที่ประมาณได้

    วิธีแก้: ตรวจครั้งที่วัดอ้างอิง หรือรายงานคอนทราสต์ที่ครั้งที่วัดซึ่งระบุไว้ ซึ่งไม่ขึ้นกับการลงรหัส

  • "สัมประสิทธิ์ของครั้งที่วัดแสดงว่าการรักษาออกฤทธิ์อย่างไรตามเวลา"

    $\beta_{2,k}$ แต่ละตัวคือการเปลี่ยนแปลงจากจุดเริ่มต้นในกลุ่มควบคุมเท่านั้น

    วิธีแก้: การเปลี่ยนแปลงในกลุ่มรักษาคือ $\beta_{2,k} + \beta_{3,k}$

  • "ตัดปฏิกิริยาสัมพันธ์ออกแล้วจะได้ผลของการรักษาร่วมหนึ่งค่า"

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

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

  • "แบบจำลองความแปรปรวนร่วมไม่สำคัญ เพราะค่าประมาณไม่เปลี่ยน"

    จริงเฉพาะเมื่อข้อมูลครบถ้วนและใช้เวลาแบบจัดกลุ่ม และถึงอย่างนั้นค่าคลาดเคลื่อนมาตรฐานก็ยังต่างกัน

    วิธีแก้: กำหนดแบบจำลองความแปรปรวนร่วมไว้ล่วงหน้าและรายงานคู่กับผลลัพธ์

สิ่งที่ควรทำในการวิเคราะห์ของคุณเอง

อภิธานศัพท์

treatment-by-time interaction (ปฏิกิริยาสัมพันธ์ระหว่างการรักษากับเวลา)
พจน์ในแบบจำลองที่ทำให้ความต่างระหว่างกลุ่มเปลี่ยนไปในแต่ละครั้งที่วัด
difference in differences
การเปลี่ยนแปลงในกลุ่มรักษาลบการเปลี่ยนแปลงในกลุ่มควบคุม
categorical time
แต่ละครั้งที่วัดถูกลงรหัสเป็นหมวดของตัวเอง โดยไม่สมมติรูปร่างของแนวโน้ม
MMRM (แบบจำลองผสมสำหรับการวัดซ้ำ)
แบบจำลองผสมสำหรับการวัดซ้ำ (mixed model for repeated measures): ครั้งที่วัดแบบจัดกลุ่ม พจน์กลุ่มการรักษาคูณครั้งที่วัด และความแปรปรวนร่วมแบบไม่มีโครงสร้างสำหรับผลลัพธ์ที่วัดซ้ำ
unstructured covariance
แบบจำลองความแปรปรวนร่วมที่ความแปรปรวนและสหสัมพันธ์ทุกค่าถูกประมาณอย่างอิสระ
ANCOVA
การวิเคราะห์ความแปรปรวนร่วม (analysis of covariance): คะแนนตอนติดตามผลที่ถดถอยบนกลุ่มและคะแนนที่จุดเริ่มต้น
change score
คะแนนตอนติดตามผลลบคะแนนที่จุดเริ่มต้น แล้วนำมาเปรียบเทียบระหว่างกลุ่ม
constrained baseline
แบบจำลองระยะยาวที่ให้ทั้งสองกลุ่มมีค่าเฉลี่ยที่จุดเริ่มต้นร่วมกันหนึ่งค่า
estimand (ปริมาณเป้าหมายของการประมาณ)
ปริมาณที่แน่ชัดซึ่งการศึกษาตั้งใจประมาณ ซึ่ง ICH E9(R1) อธิบายด้วยการรักษา ประชากร ตัวแปร การจัดการกับเหตุการณ์ระหว่างการศึกษา และมาตรวัดสรุประดับประชากร

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

  1. Fitzmaurice GM, Laird NM, Ware JH. Applied longitudinal analysis. 2nd ed. Wiley; 2011. doi:10.1002/9781119513469 https://doi.org/10.1002/9781119513469
  2. Vickers AJ, Altman DG. Analysing controlled trials with baseline and follow up measurements. BMJ. 2001;323(7321):1123-1124. doi:10.1136/bmj.323.7321.1123 https://doi.org/10.1136/bmj.323.7321.1123
  3. Twisk J, Bosman L, Hoekstra T, Rijnhart J, Welten M, Heymans M. Different ways to estimate treatment effects in randomised controlled trials. Contemp Clin Trials Commun. 2018;10:80-85. doi:10.1016/j.conctc.2018.03.008 https://doi.org/10.1016/j.conctc.2018.03.008
  4. International Council for Harmonisation (ICH). ICH E9(R1): Addendum on estimands and sensitivity analysis in clinical trials to the guideline on statistical principles for clinical trials. ICH Harmonised Guideline, Step 4; 2019. https://database.ich.org/sites/default/files/E9-R1_Step4_Guideline_2019_1203.pdf

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

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

อ่านต่อในวิกิ: [[repeated-measures-modeling-guide-th]] [[mixed-model-series-guide-th]]

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

ความคิดเห็น

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

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

ปฏิกิริยาสัมพันธ์ระหว่างการรักษากับเวลา: สัมประสิทธิ์ตัวไหนคือผลของการรักษา — Uniqcret