library(dplyr) # for data wrangling
library(seminr) # for PLS-SEM
data <- openxlsx::read.xlsx("MMM_influencer_data.xlsx")MMM WT 2023/24: Exercise 4
Set-up
Load packages dplyr and seminr.
The original data$WP01_01 is a character (not a numeric variable) since it was a free text in field in the survey.
class(data$WP01_01)[1] "character"
data$WP01_01 [1] "30" "20" "20" "10" "50" "10" "15" "6" "15"
[10] "35" "0" "15" "30" "1" "5" "20" "5" "5"
[19] "15" "18" "19,99" "30" "15" "0" "35" "10" "19"
[28] "20" "20" "19,99" "0" "6" "0" "10" "5" "15"
[37] "25" "5" "25" "30" "25" "5" "15" "30" "0"
[46] "5" "0" "2" "0" "0" "50" "0" ",75" "30"
[55] "39,99" "10" "37" "25" "15" "7" "5" "50" "10"
[64] "20" "20" "6" "10" "15" "20" "50" "12" "18"
[73] "4" "10" "20" "7" "25" "8" "10" "40" "8"
[82] "30" "78" "10" "40" "10" "5" "40" "5" "80"
[91] "5" "25" "15" "10" "35" "0" "2" "5" "0"
[100] "0" "29,99" "8" "19,99" "6" "25" "30" "35" "20"
[109] "5" "8" "15" "40" "0" "2" "5" "20" "20"
[118] "5" "15" "25" "0" "20" "17" "0" "5" "0"
[127] "0" "0" "0" "5" "7" "9" "0" "0" "0"
[136] "25" "15" "7" "5" "30" "40" "15" "15" "30"
[145] "20" "20" "15" "50" "20" "25" "10" "5" "20"
[154] "20" "30" "24" "35" "20" "30" "15" "30" "30"
[163] "15" "20" "15" "25" "5" "0" "5" "0" "20"
[172] "1" "20" "10" "10" "3" "0" "50" "40" "8"
[181] "30" "15" "40" "0" "20" "5" "40" "18" "15"
[190] "15" "9,99" "29" "7" "5" "15" "25" "2" "4"
[199] "5" "15" "50" "30" "150" "0" "35" "10" "2"
[208] "0" "0" "50" "20" "10" "0" "40" "30" "5"
[217] "25" "30" "4" "30" "40" "5" "10"
To use the variable in the SEM, we need to convert WP01_01 to a numeric variable. Since participants used a “,” and not “.” as a decimal seperator, we need to preprocess WP01_01 and replace “,” with “.” (–> gsub-command)
data$WP01_01_num <- gsub(pattern = ",", replacement = ".", data$WP01_01) %>%
as.numeric()
data$WP01_01_num [1] 30.00 20.00 20.00 10.00 50.00 10.00 15.00 6.00 15.00 35.00
[11] 0.00 15.00 30.00 1.00 5.00 20.00 5.00 5.00 15.00 18.00
[21] 19.99 30.00 15.00 0.00 35.00 10.00 19.00 20.00 20.00 19.99
[31] 0.00 6.00 0.00 10.00 5.00 15.00 25.00 5.00 25.00 30.00
[41] 25.00 5.00 15.00 30.00 0.00 5.00 0.00 2.00 0.00 0.00
[51] 50.00 0.00 0.75 30.00 39.99 10.00 37.00 25.00 15.00 7.00
[61] 5.00 50.00 10.00 20.00 20.00 6.00 10.00 15.00 20.00 50.00
[71] 12.00 18.00 4.00 10.00 20.00 7.00 25.00 8.00 10.00 40.00
[81] 8.00 30.00 78.00 10.00 40.00 10.00 5.00 40.00 5.00 80.00
[91] 5.00 25.00 15.00 10.00 35.00 0.00 2.00 5.00 0.00 0.00
[101] 29.99 8.00 19.99 6.00 25.00 30.00 35.00 20.00 5.00 8.00
[111] 15.00 40.00 0.00 2.00 5.00 20.00 20.00 5.00 15.00 25.00
[121] 0.00 20.00 17.00 0.00 5.00 0.00 0.00 0.00 0.00 5.00
[131] 7.00 9.00 0.00 0.00 0.00 25.00 15.00 7.00 5.00 30.00
[141] 40.00 15.00 15.00 30.00 20.00 20.00 15.00 50.00 20.00 25.00
[151] 10.00 5.00 20.00 20.00 30.00 24.00 35.00 20.00 30.00 15.00
[161] 30.00 30.00 15.00 20.00 15.00 25.00 5.00 0.00 5.00 0.00
[171] 20.00 1.00 20.00 10.00 10.00 3.00 0.00 50.00 40.00 8.00
[181] 30.00 15.00 40.00 0.00 20.00 5.00 40.00 18.00 15.00 15.00
[191] 9.99 29.00 7.00 5.00 15.00 25.00 2.00 4.00 5.00 15.00
[201] 50.00 30.00 150.00 0.00 35.00 10.00 2.00 0.00 0.00 50.00
[211] 20.00 10.00 0.00 40.00 30.00 5.00 25.00 30.00 4.00 30.00
[221] 40.00 5.00 10.00
Model set up
Measurement model
mm <- constructs(
composite("SIC", multi_items("SC02_0", 1:7)),
composite("PL", multi_items("PL01_0", c(1, 4, 6, 7))),
composite("PQ", multi_items("PQ01_0", 1:4)),
composite("PI", multi_items("PI01_0", c(1, 2, 4, 5, 6))),
composite("WTP", single_item("WP01_01_num"))
)Inspect the element: For each construct (e.g., “SIC”) mm shows
- its indicators (e.g., “SC02_01”)
- its mode (i.e., mode A for correlation weights = reflective measurement; mode B for regression weights = formative measurement)
mm$composite
[1] "SIC" "SC02_01" "A" "SIC" "SC02_02" "A" "SIC"
[8] "SC02_03" "A" "SIC" "SC02_04" "A" "SIC" "SC02_05"
[15] "A" "SIC" "SC02_06" "A" "SIC" "SC02_07" "A"
attr(,"class")
[1] "character" "construct" "composite"
$composite
[1] "PL" "PL01_01" "A" "PL" "PL01_04" "A" "PL"
[8] "PL01_06" "A" "PL" "PL01_07" "A"
attr(,"class")
[1] "character" "construct" "composite"
$composite
[1] "PQ" "PQ01_01" "A" "PQ" "PQ01_02" "A" "PQ"
[8] "PQ01_03" "A" "PQ" "PQ01_04" "A"
attr(,"class")
[1] "character" "construct" "composite"
$composite
[1] "PI" "PI01_01" "A" "PI" "PI01_02" "A" "PI"
[8] "PI01_04" "A" "PI" "PI01_05" "A" "PI" "PI01_06"
[15] "A"
attr(,"class")
[1] "character" "construct" "composite"
$composite
[1] "WTP" "WP01_01_num" "A"
attr(,"class")
[1] "character" "construct" "composite"
attr(,"class")
[1] "list" "measurement_model" "seminr_model"
Structural model
sm <- relationships(
paths(from = "SIC", to = c("PL", "PQ", "PI")),
paths(from = "PL", to = "PI"),
paths(from = "PQ", to = "PI"),
paths(from = "PI", to = "WTP"))sm source target
[1,] "SIC" "PL"
[2,] "SIC" "PQ"
[3,] "SIC" "PI"
[4,] "PL" "PI"
[5,] "PQ" "PI"
[6,] "PI" "WTP"
attr(,"class")
[1] "matrix" "array" "structural_model" "seminr_model"
Estimate and plot the model:
model <- estimate_pls(data = data,
measurement_model = mm,
structural_model = sm,
inner_weights = path_weighting)Generating the seminr model
All 223 observations are valid.
plot(model)Summarize the model
model_sum <- summary(model)Measurement model assessment
Reliability statistics and convergent validity
model_sum$reliability alpha rhoC AVE rhoA
SIC 0.930 0.943 0.705 0.942
PL 0.939 0.956 0.846 0.942
PQ 0.936 0.954 0.840 0.939
PI 0.945 0.958 0.821 0.949
WTP 1.000 1.000 1.000 1.000
Alpha, rhoC, and rhoA should exceed 0.7 while AVE should exceed 0.5
plot(model_sum$reliability)Show an interpretation
# Internal consistency: Cronbach's alpha (alpha), composite reliability (rhoC, rhoA)
# --> All values exceed the threshold values of at least 0.70 required (0.80 for established constructs).
# --> Thus constructs are internally consistent (i.e., reliable).
# --> However, all values are also very high --> values higher than 0.90 (or 0.95) are often not desirable and indicate that the items are too redundant.
# Convergent validity: AVE
# --> all values > 0.5. Thus all constructs (on average) explain at least 50% of the assigned indicators’ variance.
# --> Constructs show sufficient convergent validity (i.e., constructs represent items sufficiently)Indicator reliability
Inspect the outer loadings and square the loadigs to assess explained variance.
model_sum$loadings SIC PL PQ PI WTP
SC02_01 0.870 0.000 0.000 0.000 0.000
SC02_02 0.877 0.000 0.000 0.000 0.000
SC02_03 0.886 0.000 0.000 0.000 0.000
SC02_04 0.777 0.000 0.000 0.000 0.000
SC02_05 0.758 0.000 0.000 0.000 0.000
SC02_06 0.796 0.000 0.000 0.000 0.000
SC02_07 0.903 0.000 0.000 0.000 0.000
PL01_01 0.000 0.926 0.000 0.000 0.000
PL01_04 0.000 0.906 0.000 0.000 0.000
PL01_06 0.000 0.947 0.000 0.000 0.000
PL01_07 0.000 0.898 0.000 0.000 0.000
PQ01_01 0.000 0.000 0.921 0.000 0.000
PQ01_02 0.000 0.000 0.911 0.000 0.000
PQ01_03 0.000 0.000 0.906 0.000 0.000
PQ01_04 0.000 0.000 0.928 0.000 0.000
PI01_01 0.000 0.000 0.000 0.867 0.000
PI01_02 0.000 0.000 0.000 0.887 0.000
PI01_04 0.000 0.000 0.000 0.915 0.000
PI01_05 0.000 0.000 0.000 0.909 0.000
PI01_06 0.000 0.000 0.000 0.951 0.000
WP01_01_num 0.000 0.000 0.000 0.000 1.000
model_sum$loadings^2 SIC PL PQ PI WTP
SC02_01 0.756 0.000 0.000 0.000 0.000
SC02_02 0.768 0.000 0.000 0.000 0.000
SC02_03 0.784 0.000 0.000 0.000 0.000
SC02_04 0.604 0.000 0.000 0.000 0.000
SC02_05 0.574 0.000 0.000 0.000 0.000
SC02_06 0.633 0.000 0.000 0.000 0.000
SC02_07 0.815 0.000 0.000 0.000 0.000
PL01_01 0.000 0.858 0.000 0.000 0.000
PL01_04 0.000 0.821 0.000 0.000 0.000
PL01_06 0.000 0.898 0.000 0.000 0.000
PL01_07 0.000 0.806 0.000 0.000 0.000
PQ01_01 0.000 0.000 0.849 0.000 0.000
PQ01_02 0.000 0.000 0.829 0.000 0.000
PQ01_03 0.000 0.000 0.820 0.000 0.000
PQ01_04 0.000 0.000 0.861 0.000 0.000
PI01_01 0.000 0.000 0.000 0.751 0.000
PI01_02 0.000 0.000 0.000 0.788 0.000
PI01_04 0.000 0.000 0.000 0.837 0.000
PI01_05 0.000 0.000 0.000 0.826 0.000
PI01_06 0.000 0.000 0.000 0.905 0.000
WP01_01_num 0.000 0.000 0.000 0.000 1.000
Show an interpretation
# All indicators show sufficient indicator reliability:
# --> all loadings > 0.707
# --> all squared loadings > 0.5 (i.e., construct accounts for > 50% of each indicator's variance)Discriminant validity (HTMT)
model_sum$validity$htmt SIC PL PQ PI WTP
SIC . . . . .
PL 0.476 . . . .
PQ 0.413 0.785 . . .
PI 0.423 0.825 0.682 . .
WTP 0.140 0.463 0.485 0.449 .
Show an interpretation
# All HTMT point estimates meet the thresholds and are below 0.85 (resp. 0.9).
# --> Thus, they indicate discriminant validity between the latent variables (i.e., latent variables measure different constructs).
# However, the HTMT for PL and PI as well as for PL and PQ are rather high (HTMT(PI-PL) = .825, resp. HTMT(PQ-PL) = .785)
# Indicating that the constructs are partly related. This mirrors the factor analytic results (last exercise) that showed high interrelations between these constructs' items.