นโยบายการจัดการความรู้ มหาวิทยาลัยสงขลานครินทร์ 1.ให้ใช้เครื่องมือการจัดการความรู้ผลักดัน คุณภาพคน และกระบวนทำงาน 2.ส่งเสริมการแลกเปลี่ยนประสบการณ์การทำงาน จากหน้างาน 3.ส่งเสริมให้มีเวทีเรียนรู้ร่วมกัน

Our Shangri-La
Ico64
Kittisakdi Choomalee

ภาควิชาเวชศาสตร์ชุมชน คณะแพทยศาสตร์ มหาวิทยาลัยสงขลานครินทร์
Network
Members · Following: 0 · Followed: 16

อ่าน: 1290
ความเห็น: 1

การวิเคราะห์องค์ประกอบเชิงยืนยันด้วย sem package ใน R: ก้าวย่างทางเดิน ลืมเลือนคืนวัน ดั้นด้นไป

การวิเคราะห์องค์ประกอบเชิงยืนยันด้วย package sem ใน R

ทบทวน CFA (Confirmatory Factor Analysis) ด้วย R กันลืมนะครับ

ทฤษฏียกเอาไว้นะครับ

ใน R มี package สำหรับวิเคราะห์ CFA หลาย Package ด้วยกัน แต่ที่ผมเคยลองใช้ก็เป็น sem กับ lavaan ครับ package หลังสุดนี่ใช้งานง่ายหน่อยครับ แต่อาจจะติดตรงที่จำนวนดัชนีสำหรับ CFA นั้นมีน้อยกว่าอีก package หนึ่ง

Sem นี่ ใช้งานยากกว่านิดนึง แต่มีดัชนี CFA หลายตัวให้ดู

SEM = Structural Equation Modeling

ความยากของ SEM ก็คือการเขียนสมการโครงสร้างสำหรับเป็น input ให้ R นี่แหละครับ ซึ่งการเขียนสมการโครงสร้างก็ต้องเริ่มต้นจากการ path diagram ครับ เขียนสมการได้ต้องมี path diagram หรือตัวโครงสร้างตามทฤษฎี/ กรอบแนวคิดของเรานั่นเอง

ต้องเขียน path diagram ให้ได้ก่อน กำหนดว่า path ระหว่าง Latent variable (construct) กับ Observable variable (manifest variable) ภาษาไทยก็คงเป็นตัวแปรแฝงกับตัวแปรสังเกตได้ ทำนองนั้นครับ

ต้องเขียนเส้นทาง ว่าอันไหนเป็น direct effect indirect effect เป็น correlation, ….

จากนั้นนำเอาโครงสร้างที่เราเขียน (ต้องการทดสอบกับข้อมูล) มาแปลงให้เป็นภาษาของสมการโครงสร้างเพื่อเป็น input ให้กับ R นอกเหนือจากที่ต้องใส่ข้อมูลที่เก็บรวบรวมมาเป็น input อีกหนึ่งอย่าง

การเขียนสมการโครงสร้างนี่มีวิธีการเขียนอยู่หลายแบบ ซึ่งผมก็ไม่เคยเจอะไม่เคยเจอ เช่น LISREL , RAM1, RAM2, Bentler-Weeks, และ EzPath models

การแปลงสมการโครงสร้างเป็นภาษาที่ R เข้าใจ (ในที่นี้คือ package sem) นั้นเขียนเป็นภาษา ASCII ที่ชื่อว่า PATH1 (James H. Steiger)

R สามารถถอด code ของการเขียน model แบบ RAM ได้

ในที่นี้ก็ให้เข้าใจว่า RAM นั้นคืออะไร เป็นแบบไหนก็ช่างหัวมันเถอะ

วิธีการนำเข้า model หรือจะเรียกว่า path diagram สู่ environment ของ R นั้นทำได้ผ่านหลายฟังก์ชันด้วยกัน แต่ที่ง่ายที่สุดก็คือการนำเข้าผ่านฟังก์ชัน cfa()

ฟังก์ชัน cfa() ใน sem นะครับ

ตัวอย่างต่อไปนี้เป็นตัวอย่างที่นำมาจากงานวิจัยของ  Holzinger และ Swineford (1939) เป็นข้อมูลส่วนหนึ่ง (73 records)

Holzinger และ Swineford ทำการทดสอบเด็ก (ผู้หญิง) ด้วย seven test (different aspects of educational ability) ซึ่งประกอบไปด้วย

  1. Visual perception
  2. Cube identification
  3. lozenge identification
  4. Word meanings
  5. sentence structure
  6. paragraph understanding

 

นำเข้าข้อมูลตัวอย่าง

> t7 <- read.table("t7.dat", header=T)

> head(t7)

  visperc cubes lozenges paragrap sentence wordmean

1      33    22       17        8       17       10

2      30    25       20       10       23       18

3      36    33       36       17       25       41

4      28    25        9       10       18       11

5      30    25       11       11       21        8

6      20    25        6        9       21       16

 

ในที่นี้เราจะทำการทดสอบยืนยันว่า t7 เป็นการวัด 2 กลุ่ม/ domain  (2 latent variables) คือ visual perception (vp) กับ reading (rd)

Path diagram คือ (ในที่นี้เราจะละสัญลักษณ์ต่าง ๆ เช่น lamda, phi, error, … ไว้ไม่เขียนใน diagram)

ฟังก์ชัน cfa() นี้สามารถใส่ input ได้ 2 แบบคือ อนโดยตรงที่ Rconsole หรือเรียกสมการจากแฟ้มข้อมูล ในที่นี้จะใช้การ input ข้อมูลผ่าน Rconsole

> ct7 <- cfa(reference.indicators=FALSE, covs=NULL)

1: vp: visperc, cubes, lozenges

2: rd: paragrap, sentence, wordmean

3:

Read 2 items

NOTE: adding 6 variances to the model

> ct7

   Path                  Parameter        StartValue

1  vp -> visperc         lam[visperc:vp]           

2  vp -> cubes           lam[cubes:vp]              

3  vp -> lozenges        lam[lozenges:vp]          

4  rd -> paragrap        lam[paragrap:rd]           

5  rd -> sentence        lam[sentence:rd]          

6  rd -> wordmean        lam[wordmean:rd]          

7  vp <-> vp             <fixed>          1        

8  rd <-> rd             <fixed>          1        

9  visperc <-> visperc   V[visperc]                

10 cubes <-> cube        V[cubes]                   

11 lozenges <-> lozenges V[lozenges]               

12 paragrap <-> paragrap V[paragrap]               

13 sentence <-> sentence V[sentence]               

14 wordmean <-> wordmean V[wordmean]   

ที่เราเห็นผลลัพธ์ข้างต้นนั่นคือการแปลงจาก input ของฟังก์ชัน cfa() ให้เป็นภาษา PATH1

จากนั้นสร้าง correlation matrix  ของข้อมูล

> cot7 <- cor(t7)

> cot7

           visperc     cubes  lozenges  paragrap  sentence  wordmean

visperc  1.0000000 0.4828862 0.4916630 0.3430168 0.3667612 0.2297377

cubes    0.4828862 1.0000000 0.4924264 0.2106977 0.1786094 0.1838991

lozenges 0.4916630 0.4924264 1.0000000 0.3258026 0.3354078 0.3689271

paragrap 0.3430168 0.2106977 0.3258026 1.0000000 0.7243611 0.7430226

sentence 0.3667612 0.1786094 0.3354078 0.7243611 1.0000000 0.6955315

wordmean 0.2297377 0.1838991 0.3689271 0.7430226 0.6955315 1.0000000

 

เมื่อทุกอย่างพร้อมก็สั่ง fit สมการ โดยที่ N= จำนวนข้อมูลทั้งหมด และ S= correlation matrix ของข้อมูล (ระหว่างตัวแปร)

> semt7 <- sem(ct7, N=73,S=cot7)

จากนั้นสั่งให้แสดงผลลัพธ์โดยแสดงค่าดัชนีต่าง ๆ

> summary(semt7,conf.level=.95,fit.indices=c("GFI", "AGFI", "RMSEA", "NFI", "NNFI","CFI", "RNI", "IFI", "SRMR"))

 

 Model Chisquare =  19.86044   Df =  9 Pr(>Chisq) = 0.01879349

 Goodness-of-fit index =  0.9219684

 Adjusted goodness-of-fit index =  0.8179262

 RMSEA index =  0.1294602   95% CI: (0.02492434, 0.2204861)

 Bentler-Bonett NFI =  0.8942005

 Tucker-Lewis NNFI =  0.8952005

 Bentler CFI =  0.9371203

 Bentler RNI =  0.9371203

 Bollen IFI =  0.9392313

 SRMR =  0.1914631

 

 Normalized Residuals

      Min.    1st Qu.     Median       Mean    3rd Qu.       Max.

-0.0000011 -0.0000001  0.7578000  1.1990000  2.7650000  3.1300000

 

 R-square for Endogenous Variables

 visperc    cubes lozenges paragrap sentence wordmean

  0.4821   0.4836   0.5014   0.7738   0.6781   0.7135

 

 Parameter Estimates

                 Estimate  Std Error  z value  Pr(>|z|)                           

lam[visperc:vp]  0.6943612 0.12659520 5.484893 4.137188e-08 visperc <--- vp      

lam[cubes:vp]    0.6954395 0.12662144 5.492273 3.967935e-08 cubes <--- vp        

lam[lozenges:vp] 0.7080795 0.12693163 5.578432 2.426961e-08 lozenges <--- vp     

lam[paragrap:rd] 0.8796707 0.09856879 8.924434 4.479843e-19 paragrap <--- rd     

lam[sentence:rd] 0.8234458 0.10115440 8.140485 3.936984e-16 sentence <--- rd     

lam[wordmean:rd] 0.8446600 0.10020665 8.429181 3.480937e-17 wordmean <--- rd     

V[visperc]       0.5178625 0.13427138 3.856834 1.148649e-04 visperc <--> visperc 

V[cubes]         0.5163638 0.13435632 3.843242 1.214197e-04 cubes <--> cubes     

V[lozenges]      0.4986234 0.13545010 3.681233 2.321084e-04 lozenges <--> lozenges

V[paragrap]      0.2261796 0.07167599 3.155583 1.601775e-03 paragrap <--> paragrap

V[sentence]      0.3219371 0.07571344 4.252047 2.118252e-05 sentence <--> sentence

V[wordmean]      0.2865496 0.07375643 3.885080 1.022960e-04 wordmean <--> wordmean

 

 Iterations =  23

จากการทดสอบสมการด้วย Chi-square test ให้ผลการทดสอบ significant หรือค่า Chi-square = 19.80644 degree of freedom เท่ากับ 9 แสดงให้เห็นว่า โมเดลโครงสร้างตามทฤษฎีหรือกรอบแนวคิดที่เรากำหนดขึ้นใน diagram ยังไม่ fit หรือยังมีความแตกต่างจากโมเดลการวัด (ข้อมูล) อยู่

เราอาจจะปรับโมเดลโครงสร้างของเราใหม่ ซึ่งมี 2 แนวคิดคือ เพิ่มเส้นความสัมพันธ์ในโมเดลกับลดเส้นความสัมพันธ์ในโมเดล

ข้อแนะนำจากผู้เชี่ยวชาญคือการเพิ่มเส้นความสัมพันธ์ในโมเดล แต่จะเพิ่มเส้นที่ใดดี (ระหว่าง ? กับ ?๗

ใน package sem มีฟังก์ชันที่ใช้ตรวจสอบว่า หากเราเพิ่ม/ กำหนดความสัมพันธ์ขึ้นในโมเดลแล้ว จะทำให้สามารถลดค่า chi-square ลงได้เท่าไหร่ เราเลือกเพิ่มเส้นความสัมพันธ์ให้กับตัวแปรที่สามารถลดค่า chi-square ลงได้มากที่สุด

ฟังก์ชันใน sem ที่ว่าคือ modInduces() หรือ Model Induces นั่นเอง หรือความสัมพันธ์ที่เพิ่มเข้าไป ความสัมพันธ์แบบไหน/ ระหว่างอะไร ที่ส่งผลต่อการเปลี่ยนแปลงของสมการ

> modIndices(semt7)

 

 5 largest modification indices, A matrix (regression coefficients):

    vp<-rd     rd<-vp     rd<-lozenges vp<-sentence vp<-paragrap

  10.761443    10.761443   10.278320      9.451144     9.415826

 

  5 largest modification indices, P matrix (variances/covariances):

rd<->vp   rd<->lozenges wordmean<->lozenges  wordmean<->visperc  sentence<->visperc

10.761443      3.935540        3.208525          2.760979            2.694762

 

จากผลลัพธ์ของ modInduces() ทำให้เราทราบว่า ถ้าเราเพิ่มความสัมพันธ์ระหว่างตัวแปร vc กับ rd เข้าไปจะทำให้ค่า chi-square ลดลงมา 10.761 ซึ่งตัวแปร vc และ rd นั้นเป็นตัวแปรแฝง (latent variable)

เราจะเลือกเส้นความสัมพันธ์ระหว่าง vc กับ rd ในรูปแบบใด?

ความสัมพันธ์ทางเดียวกับความสัมพันธ์ 2 ทาง

ทางเดียว (สัญญลักษณ์ลูกศรทางเดียว) เช่น rd ส่งผลต่อ vc หรือ vc ส่งผลต่อ rd (ส่งผลให้ค่า chi-sqaure ลดลงเท่ากัน)

สองทาง (สัญญลักษณ์ลูกศร 2 ทาง) หรือในอีกนัยยะหนึ่งคือ vc กับ rd ส่งผลซึ่งกันและกัน หรือมีความสัมพันธ์กันเอง

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

ในที่นี้เพิ่มเส้นความสัมพันธ์ระหว่าง vp กับ rd โดยที่ให้ vp ไป rd (อันนี้สมมติเอาดื้อ ๆ ว่า vp ส่งผลต่อ rd หรือเห็นช่วยให้อ่านดีขึ้น)

เราปรับโมเดลใหม่ ในที่นี้ผมจะใช้การใส่โมเดลใหม่ทับโมเดลเดิม โดยเพิ่มบรรทัดที่เป็นความสัมพันธ์ระหว่าง vp กับ rd เพิ่มเข้าไปอีกบรรทัด ใช้การป้อนข้อมูลผ่านทาง Rconsole เช่นเดิมครับ

> ct7 <- cfa(reference.indicators=FALSE, covs=NULL)

1: vp: visperc, cubes, lozenges

2: rd: paragrap, sentence, wordmean

3: rd: vp:

4:

Read 3 items

NOTE: adding 6 variances to the model

> ct7

   Path                  Parameter        StartValue

1  vp -> visperc         lam[visperc:vp]           

2  vp -> cubes           lam[cubes:vp]             

3  vp -> lozenges        lam[lozenges:vp]          

4  rd -> paragrap        lam[paragrap:rd]          

5  rd -> sentence        lam[sentence:rd]          

6  rd -> wordmean        lam[wordmean:rd]          

7  rd -> vp              lam[vp:rd]                

8  vp <-> vp             <fixed>          1        

9  rd <-> rd             <fixed>          1        

10 visperc <-> visperc   V[visperc]                 

11 cubes <-> cubes       V[cubes]                  

12 lozenges <-> lozenges V[lozenges]               

13 paragrap <-> paragrap V[paragrap]               

14 sentence <-> sentence V[sentence]               

15 wordmean <-> wordmean V[wordmean]

 

คราวนี้มา fit โมเดลอีกครั้ง (พร้อมทั้งสั่งแสดงผลลัพธ์)

> semt7 <- sem(ct7, N=73,S=cot7)

> summary(semt7,conf.level=.95,fit.indices=c("GFI", "AGFI", "RMSEA", "NFI", "NNFI","CFI", "RNI", "IFI", "SRMR"))

 

 Model Chisquare =  7.852894   Df =  8 Pr(>Chisq) = 0.4479704

 Goodness-of-fit index =  0.9658616

 Adjusted goodness-of-fit index =  0.9103867

 RMSEA index =  0   95% CI: (NA, 0.1522889)

 Bentler-Bonett NFI =  0.9581665

 Tucker-Lewis NNFI =  1.001597

 Bentler CFI =  1

 Bentler RNI =  1.000852

 Bollen IFI =  1.000819

 SRMR =  0.04293757

 

 Normalized Residuals

     Min.   1st Qu.    Median      Mean   3rd Qu.      Max.

-0.695100 -0.193800  0.000001 -0.021430  0.180000  0.683500

 

 R-square for Endogenous Variables

      vp  visperc    cubes lozenges paragrap sentence wordmean

  0.2372   0.4940   0.4275   0.5419   0.7736   0.6838   0.7081

 

 Parameter Estimates

                 Estimate  Std Error  z value  Pr(>|z|)                          

lam[visperc:vp]  0.6138345 0.11234527 5.463821 4.659926e-08 visperc <--- vp      

lam[cubes:vp]    0.5710648 0.11168135 5.113340 3.165111e-07 cubes <--- vp        

lam[lozenges:vp] 0.6429527 0.11340596 5.669479 1.432322e-08 lozenges <--- vp     

lam[paragrap:rd] 0.8795392 0.09804371 8.970889 2.941304e-19 paragrap <--- rd     

lam[sentence:rd] 0.8269340 0.10068013 8.213478 2.148724e-16 sentence <--- rd     

lam[wordmean:rd] 0.8414863 0.09996723 8.417621 3.842058e-17 wordmean <--- rd     

lam[vp:rd]       0.5576151 0.17756559 3.140333 1.687557e-03 vp <--- rd           

V[visperc]       0.5060492 0.12689285 3.988004 6.663150e-05 visperc <--> visperc 

V[cubes]         0.5724844 0.12749524 4.490241 7.114262e-06 cubes <--> cubes     

V[lozenges]      0.4580750 0.12784742 3.582982 3.396938e-04 lozenges <--> lozenges

V[paragrap]      0.2264106 0.06938893 3.262921 1.102702e-03 paragrap <--> paragrap

V[sentence]      0.3161800 0.07417707 4.262503 2.021500e-05 sentence <--> sentence

V[wordmean]      0.2919008 0.07253485 4.024283 5.714914e-05 wordmean <--> wordmean

 

 Iterations =  27

 

เริ่ดไหมครับ

แถมท้ายด้วย path diagram ที่สร้างจาก R

> pathDiagram(semt7, hat=TRUE,parameters=round(coef(semt7),3),style = "ram", node.colors = c("lightgreen", "yellow"))

 

ข้อสังเกต:

การกำหนดเครื่องหมายลูกศรใน diagram  นั้นเราจะเห็นว่า ลูกศรพุ่งออกจากตัวแปรแฝง (latent variable) ไปยังตัวแปรสังเกตได้ (Observable variable) ทั้งนี้เป็นความหมายในนัยยะของปัจจัย (factor) แต่หากเรากำหนดให้ลูกศรพุ่งในทิศทางกลับกันนั่นคือ ลูกศรพุ่งออกจากตัวแปรสังเกตได้ (Observable variable) ไปยังตัวแปรแฝง (latent variable) จะเป็นความหมายในนัยยะขององค์ประกอบ (component)

 

อิอิอิ

 

เราเอง

 

เพลง: Hotter Than Hell
ศิลปิน: Kiss

 

 

หมวดหมู่บันทึก: เรื่องทั่วไป
สัญญาอนุญาต: ซีซี: แสดงที่มา-ไม่ใช้เพื่อการค้า-อนุญาตแบบเดียวกัน Cc-by-nc-sa
สร้าง: 14 เมษายน 2559 22:43 แก้ไข: 14 เมษายน 2559 22:43 [ แจ้งไม่เหมาะสม ]
ดอกไม้
สมาชิกที่ให้กำลังใจ: Ico24 panyarak และ Ico24 โอ๋-อโณ.
สมาชิกที่ให้กำลังใจ
 
Facebook
Twitter
Google

บันทึกอื่นๆ

ความเห็น

Ico48
suka [IP: 14.182.56.57]
30 พฤศจิกายน 2561 17:03
#108283

Thank for your writting! I have read through some similar topics! However, your post has given me a very special impression, unlike other posts. I hope you continue to have valuable articles like this or more to share with everyone! vex

ร่วมแสดงความเห็นในหน้านี้

ชื่อ:
อีเมล:
IP แอดเดรส: 54.235.55.253
ข้อความ:  
เรียกเครื่องมือจัดการข้อความ
   
ยกเลิก หรือ