Introduction

# install.packages("seminr")
library(seminr)

2. Load and clean data

my_data <-read.csv(file = "Poland_consumers_data.csv",header = TRUE,sep=",")
my_data

3.Review data

head(my_data)
colnames(my_data)
##  [1] "ID"                    "Time"                  "Sex"                  
##  [4] "Age_group"             "Age"                   "Residence"            
##  [7] "Med_city_size"         "Large_city_size"       "Province"             
## [10] "Climate_change_belief" "Wft"                   "ATT1"                 
## [13] "ATT2"                  "ATT3"                  "SN1"                  
## [16] "SN2"                   "SN3"                   "PBC1"                 
## [19] "PBC2"                  "PBC3"                  "ECD1"                 
## [22] "ECD2"                  "ECD3"                  "ECC1"                 
## [25] "ECC2"                  "ECC3"                  "ECA1"                 
## [28] "ECA2"                  "ECA3"                  "PI1"                  
## [31] "PI2"                   "PI3"                   "AF1"                  
## [34] "AF2"                   "AF3"                   "WL1"                  
## [37] "WL2"                   "WL3"                   "WL4"                  
## [40] "Marital"               "Education"             "Fam_size"             
## [43] "Job"                   "Income"                "FCW"

4. Specify measurement model (mm)

  1. composite(): measurement of individual constructs. ii)interaction_term(): specifies interaction terms.
  2. higher_composite(): specifies hierarchial component models.
# to create reflective mm (no need to write mode_A)
simple_mm<- constructs(
  composite("PI", multi_items("PI",1:3)), 
  composite("ATT", multi_items("ATT",1:3)),
  composite("SN", multi_items("SN",1:3)),
  composite("PBC", multi_items("PBC",2:3)),   #PBC1 was removed because loading=0.540 and alpha< 0.7its removal has a better effect on reliability and validity metrics/content validity (<0.708 recommendation limit)
  composite("AFF", multi_items("AF",1:3))
)
simple_mm
## $composite
## [1] "PI"  "PI1" "A"   "PI"  "PI2" "A"   "PI"  "PI3" "A"  
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## $composite
## [1] "ATT"  "ATT1" "A"    "ATT"  "ATT2" "A"    "ATT"  "ATT3" "A"   
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## $composite
## [1] "SN"  "SN1" "A"   "SN"  "SN2" "A"   "SN"  "SN3" "A"  
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## $composite
## [1] "PBC"  "PBC2" "A"    "PBC"  "PBC3" "A"   
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## $composite
## [1] "AFF" "AF1" "A"   "AFF" "AF2" "A"   "AFF" "AF3" "A"  
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## attr(,"class")
## [1] "list"              "measurement_model" "seminr_model"

5. Specify structural model (sm)

  1. relationships(): specifies all the structural relationships between constructs.
  2. paths(): specifies relationship between sets of antecedents and outcomes.
# to create sm
simple_sm <- relationships(
  paths(from = c("ATT","SN","PBC","AFF"), to = "PI")
)
simple_sm
##      source target
## [1,] "ATT"  "PI"  
## [2,] "SN"   "PI"  
## [3,] "PBC"  "PI"  
## [4,] "AFF"  "PI"  
## attr(,"class")
## [1] "matrix"           "array"            "structural_model" "seminr_model"

6. Estimate the structural model

# to estimate the model
simple_model <- estimate_pls(data = my_data,
                             measurement_model = simple_mm,
                             structural_model = simple_sm,
                             inner_weights = path_weighting,
                             missing = mean_replacement,
                             missing_value = "-99")
## Generating the seminr model
## All 999 observations are valid.
# summary() [gives info about sub-meta]can be used for estimate_pls(), bootstrap_model() and predict_pls() functions
summary_simple <- summary(simple_model)  #shows the path coefficients and reliability
summary_simple
## 
## Results from  package seminr (2.3.7)
## 
## Path Coefficients:
##           PI
## R^2    0.746
## AdjR^2 0.745
## ATT    0.194
## SN     0.130
## PBC    0.112
## AFF    0.555
## 
## Reliability:
##     alpha  rhoC   AVE  rhoA
## ATT 0.924 0.952 0.869 0.927
## SN  0.925 0.952 0.870 0.926
## PBC 0.744 0.886 0.796 0.744
## AFF 0.737 0.851 0.657 0.745
## PI  0.950 0.968 0.909 0.950
## 
## Alpha, rhoC, and rhoA should exceed 0.7 while AVE should exceed 0.5
# plot the see estimated model
plot(simple_model) #β IS PATH COEFFICIENT ; λ IS outer loadings

7.Check if the algorithm of estimated sm converge

summary_simple$iterations  # should be lower than 300
## [1] 4

8. Bootstrap the estimated model

boot_simple <- bootstrap_model(
  seminr_model = simple_model,
  nboot = 10000,
  cores = NULL,
  seed = 123
)
## Bootstrapping model using seminr...
## SEMinR Model successfully bootstrapped
# store the summary of the bootstrapped model
# A path is significant when its **t-value exceeds 1.96 and its 95% confidence interval does not include zero
summary_boot <- summary(boot_simple,alpha=0.10)
summary_boot 
## 
## Results from Bootstrap resamples:  10000
## 
## Bootstrapped Structural Paths:
##             Original Est. Bootstrap Mean Bootstrap SD T Stat. 5% CI 95% CI
## ATT  ->  PI         0.194          0.194        0.025   7.706 0.152  0.236
## SN  ->  PI          0.130          0.130        0.028   4.670 0.085  0.176
## PBC  ->  PI         0.112          0.112        0.028   4.042 0.066  0.157
## AFF  ->  PI         0.555          0.554        0.031  18.133 0.503  0.604
## 
## Bootstrapped Weights:
##               Original Est. Bootstrap Mean Bootstrap SD T Stat. 5% CI 95% CI
## PI1  ->  PI           0.346          0.346        0.003 132.067 0.342  0.350
## PI2  ->  PI           0.348          0.349        0.002 141.424 0.345  0.353
## PI3  ->  PI           0.354          0.354        0.003 108.293 0.349  0.360
## ATT1  ->  ATT         0.369          0.369        0.007  55.779 0.358  0.380
## ATT2  ->  ATT         0.365          0.365        0.007  49.638 0.353  0.377
## ATT3  ->  ATT         0.339          0.339        0.007  46.078 0.327  0.351
## SN1  ->  SN           0.361          0.362        0.006  62.071 0.352  0.372
## SN2  ->  SN           0.345          0.345        0.004  77.382 0.338  0.353
## SN3  ->  SN           0.366          0.366        0.006  58.066 0.356  0.377
## PBC2  ->  PBC         0.563          0.563        0.014  39.223 0.540  0.587
## PBC3  ->  PBC         0.558          0.558        0.014  40.433 0.536  0.581
## AF1  ->  AFF          0.433          0.433        0.015  29.864 0.410  0.458
## AF2  ->  AFF          0.454          0.454        0.012  38.700 0.436  0.474
## AF3  ->  AFF          0.348          0.347        0.011  31.639 0.329  0.365
## 
## Bootstrapped Loadings:
##               Original Est. Bootstrap Mean Bootstrap SD T Stat. 5% CI 95% CI
## PI1  ->  PI           0.954          0.953        0.005 204.402 0.945  0.961
## PI2  ->  PI           0.961          0.961        0.004 252.291 0.954  0.967
## PI3  ->  PI           0.946          0.946        0.006 158.747 0.936  0.955
## ATT1  ->  ATT         0.951          0.951        0.004 224.009 0.944  0.958
## ATT2  ->  ATT         0.939          0.939        0.009 109.963 0.924  0.952
## ATT3  ->  ATT         0.905          0.905        0.010  92.792 0.888  0.920
## SN1  ->  SN           0.929          0.929        0.006 145.914 0.918  0.939
## SN2  ->  SN           0.943          0.943        0.006 158.861 0.932  0.952
## SN3  ->  SN           0.926          0.926        0.007 132.918 0.914  0.937
## PBC2  ->  PBC         0.893          0.893        0.010  93.733 0.877  0.908
## PBC3  ->  PBC         0.891          0.891        0.010  87.279 0.873  0.906
## AF1  ->  AFF          0.738          0.738        0.019  38.030 0.704  0.768
## AF2  ->  AFF          0.884          0.884        0.009 103.643 0.869  0.897
## AF3  ->  AFF          0.803          0.803        0.018  44.274 0.771  0.831
## 
## Bootstrapped HTMT:
##              Original Est. Bootstrap Mean Bootstrap SD 5% CI 95% CI
## ATT  ->  SN          0.643          0.643        0.025 0.601  0.683
## ATT  ->  PBC         0.743          0.744        0.029 0.695  0.790
## ATT  ->  AFF         0.704          0.705        0.032 0.651  0.756
## ATT  ->  PI          0.713          0.713        0.023 0.673  0.750
## SN  ->  PBC          0.754          0.754        0.028 0.707  0.799
## SN  ->  AFF          0.733          0.734        0.029 0.684  0.780
## SN  ->  PI           0.696          0.696        0.024 0.656  0.734
## PBC  ->  AFF         0.882          0.882        0.032 0.828  0.934
## PBC  ->  PI          0.804          0.804        0.025 0.763  0.844
## AFF  ->  PI          0.971          0.971        0.014 0.948  0.994
## 
## Bootstrapped Total Paths:
##             Original Est. Bootstrap Mean Bootstrap SD 5% CI 95% CI
## ATT  ->  PI         0.194          0.194        0.025 0.152  0.236
## SN  ->  PI          0.130          0.130        0.028 0.085  0.176
## PBC  ->  PI         0.112          0.112        0.028 0.066  0.157
## AFF  ->  PI         0.555          0.554        0.031 0.503  0.604
# use tstat and CI from Bootstrapped Structural Paths results to check which is significant

9. Evaluating estimated structural models (can be done for either formative/reflective model)

STEP 1: Assess multi-collinearity issues (VIF < 5: No multicollinearity problems)

# inspect the items VIF
summary_simple$validity$vif_items # CONCLUSION: PI1 and PI2 has VIF > 5, So presence of multicollinearity problems (not good)
## ATT :
##  ATT1  ATT2  ATT3 
## 4.792 4.197 2.798 
## 
## SN :
##   SN1   SN2   SN3 
## 3.473 4.223 3.270 
## 
## PBC :
## PBC2 PBC3 
## 1.54 1.54 
## 
## AFF :
##   AF1   AF2   AF3 
## 1.226 2.179 1.974 
## 
## PI :
##   PI1   PI2   PI3 
## 5.277 5.977 4.389
summary_simple$vif_antecedents # CONCLUSION: all constructs VIF < 5, So absence of multicollinearity problems (good)
## PI :
##   ATT    SN   PBC   AFF 
## 1.924 1.992 2.212 2.089

STEP 2: Assess significance and relevance of sm relationships (path coefficient)

# to inspect specific significance direct effects
summary_boot$bootstrapped_paths #path coefficent is sig at 5% if there is no zeros in between the CI
##             Original Est. Bootstrap Mean Bootstrap SD T Stat. 5% CI 95% CI
## ATT  ->  PI         0.194          0.194        0.025   7.706 0.152  0.236
## SN  ->  PI          0.130          0.130        0.028   4.670 0.085  0.176
## PBC  ->  PI         0.112          0.112        0.028   4.042 0.066  0.157
## AFF  ->  PI         0.555          0.554        0.031  18.133 0.503  0.604
# to inspect the Bootstrapped Structural loadings
summary_boot$bootstrapped_loadings  
##               Original Est. Bootstrap Mean Bootstrap SD T Stat. 5% CI 95% CI
## PI1  ->  PI           0.954          0.953        0.005 204.402 0.945  0.961
## PI2  ->  PI           0.961          0.961        0.004 252.291 0.954  0.967
## PI3  ->  PI           0.946          0.946        0.006 158.747 0.936  0.955
## ATT1  ->  ATT         0.951          0.951        0.004 224.009 0.944  0.958
## ATT2  ->  ATT         0.939          0.939        0.009 109.963 0.924  0.952
## ATT3  ->  ATT         0.905          0.905        0.010  92.792 0.888  0.920
## SN1  ->  SN           0.929          0.929        0.006 145.914 0.918  0.939
## SN2  ->  SN           0.943          0.943        0.006 158.861 0.932  0.952
## SN3  ->  SN           0.926          0.926        0.007 132.918 0.914  0.937
## PBC2  ->  PBC         0.893          0.893        0.010  93.733 0.877  0.908
## PBC3  ->  PBC         0.891          0.891        0.010  87.279 0.873  0.906
## AF1  ->  AFF          0.738          0.738        0.019  38.030 0.704  0.768
## AF2  ->  AFF          0.884          0.884        0.009 103.643 0.869  0.897
## AF3  ->  AFF          0.803          0.803        0.018  44.274 0.771  0.831

STEP 3: Assess the model’s explanatory power

# to inspect the r^square
summary_simple$paths # check for direct effects
##           PI
## R^2    0.746
## AdjR^2 0.745
## ATT    0.194
## SN     0.130
## PBC    0.112
## AFF    0.555
# CONCLUSION: PI model,R2 =0.746; paths coefficients: ATT=0.194, PBC=0.112, SN=0.130,AFF = 0.555
# inspect the effect size 
### 0.00 - 0.02 = No/very weak effect
### 0.02 to 0.15 = Small effect 
### 0.15 to 0.35 = Medium effect 
### 0.35 to 0.50 = Large effect
summary_simple$fSquare  #CONCLUSION: large effect (AFF),medium (), small(ATT,SN,PBC), no/very weak()
##       ATT    SN   PBC   AFF    PI
## ATT 0.000 0.000 0.000 0.000 0.077
## SN  0.000 0.000 0.000 0.000 0.033
## PBC 0.000 0.000 0.000 0.000 0.022
## AFF 0.000 0.000 0.000 0.000 0.580
## PI  0.000 0.000 0.000 0.000 0.000

STEP 4: Assess the model’s predictive power

  1. if majority of PLS out-of-sample indicators have RMSE/MAE values< LM benchmark =medium predictive power
  2. if minority of PLS out-of-sample indicators have RMSE/MAE values< LM benchmark =low predictive power # STEP 4a: to generate the model predictions based on PLS estimate
predict_model<- predict_pls(
  model=simple_model,
  technique = predict_DA,
  noFolds = 10,
  reps = 10
)
# compare  PLS out-of-sample metrics: to LM out-of-sample metrics
# summarise the prediction results
summary_predict<- summary(predict_model)
summary_predict  
## 
## PLS in-sample metrics:
##        PI1   PI2   PI3
## RMSE 0.569 0.562 0.543
## MAE  0.424 0.419 0.405
## 
## PLS out-of-sample metrics:
##        PI1   PI2   PI3
## RMSE 0.573 0.565 0.546
## MAE  0.427 0.422 0.408
## 
## LM in-sample metrics:
##        PI1   PI2   PI3
## RMSE 0.559 0.548 0.519
## MAE  0.404 0.396 0.376
## 
## LM out-of-sample metrics:
##        PI1   PI2   PI3
## RMSE 0.574 0.562 0.528
## MAE  0.414 0.404 0.383
## 
## Construct Level metrics:
##             PI
## IS_MSE  0.2535
## IS_MAE  0.3725
## OOS_MSE 0.2562
## OOS_MAE 0.3748
## overfit 0.0108
# Conclusion PLSpredict indicates that while the model explains purchase intention well in-sample, it shows limited out-of-sample predictive accuracy and does not outperform the linear benchmark, which is typical for attitudinal intention models.

STEP 4b: to analyse the distribution of prediction error

  1. -0.5 to 0.5 → roughly symmetric (acceptable for normality).
  2. -1 to -0.5 → moderate skew.
  3. < -1 → highly skewed.
library(moments)
# All indicators
indicators <- c(paste0("PI",1:3), paste0("ATT",1:3), paste0("SN",1:3),
                paste0("PBC",2:3), paste0("AF",1:3))
# Skewness
skew_values <- sapply(my_data[indicators], skewness, na.rm = TRUE)
# mostly moderate negative skew.
# Shapiro-Wilk p-values
shapiro_p <- sapply(my_data[indicators], function(x) shapiro.test(x)$p.value)
# All p-values are extremely small (< 0.05). all indicators are “statistically non-normal”, but this is normal in large samples.
# Combine results
results <- data.frame(Indicator = indicators, Skewness = skew_values, Shapiro_p = shapiro_p)
print(results) #Shapiro-Wilk is not reliable for large N — rely on skewness and practical judgment.
##      Indicator    Skewness    Shapiro_p
## PI1        PI1 -0.58208631 1.437934e-27
## PI2        PI2 -0.57712795 2.198353e-27
## PI3        PI3 -0.63672682 6.417538e-28
## ATT1      ATT1 -0.52195984 1.734718e-28
## ATT2      ATT2 -0.55803035 1.969654e-28
## ATT3      ATT3 -0.37466091 2.241768e-29
## SN1        SN1 -0.15909899 1.315768e-27
## SN2        SN2 -0.18785450 2.464034e-29
## SN3        SN3 -0.27877487 3.100212e-30
## PBC2      PBC2 -0.18079183 5.620343e-29
## PBC3      PBC3 -0.20067175 3.553573e-27
## AF1        AF1 -0.81989060 2.737072e-29
## AF2        AF2 -0.27560308 3.580737e-25
## AF3        AF3 -0.04715377 5.882178e-24
#RESULTS:All indicators showed slight negative skewness. Shapiro–Wilk tests indicated non-normal distributions (p < .001)
# Recommendation: Use MAE for PLSpredict metrics and interpret with skewness in mind.

####OR PLOT TO CHECK SKEWNESS#####
## to plot and see for each indicators
par(mfrow=c(1,2))
plot(summary_predict,
     indicator = "PI2")
plot(summary_predict,
     indicator = "PI3")

par(mfrow=c(1,1))

10. ASSESSING RELIABILITY AND VALIDITY OF ESTIMATED MODEL

STEP 1: Assess the indicator reliability: how much of each indicator’s variance is explained by construct

# inspect the construct loadings metrics:ideally be ≥ 0.70, with 0.60–0.70 acceptable and < 0.60 considered problematic.
summary_simple$loadings #(indicator loading should be > 0.708)
##        ATT    SN   PBC   AFF    PI
## PI1  0.000 0.000 0.000 0.000 0.954
## PI2  0.000 0.000 0.000 0.000 0.961
## PI3  0.000 0.000 0.000 0.000 0.946
## ATT1 0.951 0.000 0.000 0.000 0.000
## ATT2 0.939 0.000 0.000 0.000 0.000
## ATT3 0.905 0.000 0.000 0.000 0.000
## SN1  0.000 0.929 0.000 0.000 0.000
## SN2  0.000 0.943 0.000 0.000 0.000
## SN3  0.000 0.926 0.000 0.000 0.000
## PBC2 0.000 0.000 0.893 0.000 0.000
## PBC3 0.000 0.000 0.891 0.000 0.000
## AF1  0.000 0.000 0.000 0.738 0.000
## AF2  0.000 0.000 0.000 0.884 0.000
## AF3  0.000 0.000 0.000 0.803 0.000
# Conclusion: all indicators are >0.708
summary_simple$loadings^2 #(indicator reliability should be>0.5)
##        ATT    SN   PBC   AFF    PI
## PI1  0.000 0.000 0.000 0.000 0.909
## PI2  0.000 0.000 0.000 0.000 0.923
## PI3  0.000 0.000 0.000 0.000 0.896
## ATT1 0.905 0.000 0.000 0.000 0.000
## ATT2 0.882 0.000 0.000 0.000 0.000
## ATT3 0.819 0.000 0.000 0.000 0.000
## SN1  0.000 0.863 0.000 0.000 0.000
## SN2  0.000 0.889 0.000 0.000 0.000
## SN3  0.000 0.857 0.000 0.000 0.000
## PBC2 0.000 0.000 0.798 0.000 0.000
## PBC3 0.000 0.000 0.794 0.000 0.000
## AF1  0.000 0.000 0.000 0.544 0.000
## AF2  0.000 0.000 0.000 0.781 0.000
## AF3  0.000 0.000 0.000 0.645 0.000
# Conclusion: all indicators are > 0.5. No issues of non-reliability of indicators

STEP 2: Assess the internal consistency (construct) reliability

# to inspect composite reliability rhoc of estimated model
summary_simple$reliability ### Note: only PBC has alpha<0.7 in the original model (not good);so PBC1 was removed
##     alpha  rhoC   AVE  rhoA
## ATT 0.924 0.952 0.869 0.927
## SN  0.925 0.952 0.870 0.926
## PBC 0.744 0.886 0.796 0.744
## AFF 0.737 0.851 0.657 0.745
## PI  0.950 0.968 0.909 0.950
## 
## Alpha, rhoC, and rhoA should exceed 0.7 while AVE should exceed 0.5
# rhoa values should be between alpha and rhoc
# Conclusion : all are relaible 
# to plot reliability chart
plot(summary_simple$reliability)  #horizontal blue line is the threshold

# STEP 3: Assess the convergent validity - Validity assessment is AVE. - Average variance extracted (AVE) = SUM OF SQUARED LOADINGS/NO OF INDICATORS (>=0.50 is acceptable).

summary_simple$reliability # Conclusion: all AVE values are > 0.5:good
##     alpha  rhoC   AVE  rhoA
## ATT 0.924 0.952 0.869 0.927
## SN  0.925 0.952 0.870 0.926
## PBC 0.744 0.886 0.796 0.744
## AFF 0.737 0.851 0.657 0.745
## PI  0.950 0.968 0.909 0.950
## 
## Alpha, rhoC, and rhoA should exceed 0.7 while AVE should exceed 0.5

STEP 4: Assess the discriminant validity

  1. AVE must be higher than the squared interconstruct correlation.
summary_simple$validity$fl_criteria #first value in each column should be higher than other values below
##       ATT    SN   PBC   AFF    PI
## ATT 0.932     .     .     .     .
## SN  0.595 0.933     .     .     .
## PBC 0.616 0.626 0.892     .     .
## AFF 0.593 0.609 0.656 0.810     .
## PI  0.669 0.653 0.676 0.822 0.954
## 
## FL Criteria table reports square root of AVE on the diagonal and construct correlations on the lower triangle.

STEP 4b: Heterotrait-monotrait ratio (HTMT) [Henseler et al., 2015]is alternative to above criticised measure

# to inspect Henseler proposal
summary_simple$validity$htmt #all of the values should be <0.90
##       ATT    SN   PBC   AFF PI
## ATT     .     .     .     .  .
## SN  0.643     .     .     .  .
## PBC 0.743 0.754     .     .  .
## AFF 0.704 0.733 0.882     .  .
## PI  0.713 0.696 0.804 0.971  .

STEP 4c: Crossloadings for assessment of discriminant validity

summary_simple$validity$cross_loadings  #loadings values for each indicators should be the highest at its own construct and not other constructs
##        ATT    SN   PBC   AFF    PI
## PI1  0.630 0.614 0.631 0.778 0.954
## PI2  0.628 0.624 0.647 0.782 0.961
## PI3  0.655 0.630 0.655 0.792 0.946
## ATT1 0.951 0.561 0.574 0.568 0.642
## ATT2 0.939 0.571 0.569 0.565 0.635
## ATT3 0.905 0.533 0.580 0.522 0.591
## SN1  0.592 0.929 0.593 0.570 0.615
## SN2  0.524 0.943 0.564 0.552 0.588
## SN3  0.548 0.926 0.593 0.581 0.623
## PBC2 0.584 0.542 0.893 0.548 0.606
## PBC3 0.515 0.575 0.891 0.623 0.601
## AF1  0.594 0.434 0.474 0.738 0.692
## AF2  0.480 0.570 0.609 0.884 0.725
## AF3  0.338 0.466 0.501 0.803 0.555

STEP 5: Bootstrapping HTMT results (to see if HTMT values are significantly different from 1 or a lower threshold like 0.9/0.85)

# extract bootstrapped htmt
summary_boot$bootstrapped_HTMT  #there should be no 1 in the CI=NO ISSUES OF DISCRIMINALITY
##              Original Est. Bootstrap Mean Bootstrap SD T Stat. 5% CI 95% CI
## ATT  ->  SN          0.643          0.643        0.025  25.724 0.601  0.683
## ATT  ->  PBC         0.743          0.744        0.029  25.601 0.695  0.790
## ATT  ->  AFF         0.704          0.705        0.032  22.237 0.651  0.756
## ATT  ->  PI          0.713          0.713        0.023  30.341 0.673  0.750
## SN  ->  PBC          0.754          0.754        0.028  26.780 0.707  0.799
## SN  ->  AFF          0.733          0.734        0.029  25.175 0.684  0.780
## SN  ->  PI           0.696          0.696        0.024  29.249 0.656  0.734
## PBC  ->  AFF         0.882          0.882        0.032  27.178 0.828  0.934
## PBC  ->  PI          0.804          0.804        0.025  32.760 0.763  0.844
## AFF  ->  PI          0.971          0.971        0.014  69.453 0.948  0.994

11. Plotting, Printing and Exporting Results

# exporitng
# write.csv(x=summary_boot$bootstrapped_loadings, file = "boot_loadings.csv")
# to plot the constructs' internal consistency reliabilities
plot(summary_simple$reliability)

# to plot pls estimated model
plot(simple_model)
# to plot bootstrapped pls estimated model
plot(boot_simple) #shows the significant variables

MEDIATING EFFECT ANALYSIS

# to create reflective mm (no need to write mode_A)
simple_mm<- constructs(
  composite("PI", multi_items("PI",1:3)), 
  composite("ATT", multi_items("ATT",1:3)),
  composite("SN", multi_items("SN",1:3)),
  composite("PBC", multi_items("PBC",2:3)),   #PBC1 was removed because loading=0.540 and alpha< 0.7its removal has a better effect on reliability and validity metrics/content validity (<0.708 recommendation limit)
  composite("AFF", multi_items("AF",1:3))
)
simple_mm
## $composite
## [1] "PI"  "PI1" "A"   "PI"  "PI2" "A"   "PI"  "PI3" "A"  
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## $composite
## [1] "ATT"  "ATT1" "A"    "ATT"  "ATT2" "A"    "ATT"  "ATT3" "A"   
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## $composite
## [1] "SN"  "SN1" "A"   "SN"  "SN2" "A"   "SN"  "SN3" "A"  
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## $composite
## [1] "PBC"  "PBC2" "A"    "PBC"  "PBC3" "A"   
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## $composite
## [1] "AFF" "AF1" "A"   "AFF" "AF2" "A"   "AFF" "AF3" "A"  
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## attr(,"class")
## [1] "list"              "measurement_model" "seminr_model"

2. Create structural model

# to create sm for indirect efffects
simple_sm <- relationships(
  paths(from = c("ATT","SN","PBC","AFF"), to = "PI"),
  paths(from = "AFF", to = c("ATT","SN","PBC"))
)
simple_sm
##      source target
## [1,] "ATT"  "PI"  
## [2,] "SN"   "PI"  
## [3,] "PBC"  "PI"  
## [4,] "AFF"  "PI"  
## [5,] "AFF"  "ATT" 
## [6,] "AFF"  "SN"  
## [7,] "AFF"  "PBC" 
## attr(,"class")
## [1] "matrix"           "array"            "structural_model" "seminr_model"

3. Estimate the structural model

# to estimate the model
simple_model <- estimate_pls(data = my_data,
                             measurement_model = simple_mm,
                             structural_model = simple_sm,
                             inner_weights = path_weighting,
                             missing = mean_replacement,
                             missing_value = "-99"
)
## Generating the seminr model
## All 999 observations are valid.
# summary()
summary_simple <- summary(simple_model)  #shows the path coefficients and reliability
plot(simple_model) #β IS PATH COEFFICIENT ; λ IS outer loadings

4. Check for indirect effects

summary_simple$total_indirect_effects
##       ATT    SN   PBC   AFF    PI
## ATT 0.000 0.000 0.000 0.000 0.000
## SN  0.000 0.000 0.000 0.000 0.000
## PBC 0.000 0.000 0.000 0.000 0.000
## AFF 0.000 0.000 0.000 0.000 0.269
## PI  0.000 0.000 0.000 0.000 0.000
# Conclusion: Only AFF shows a non-zero indirect effect on Purchase Intention (PI) (β = 0.269), indicating the presence of mediation

5. Bootstrap estimated model

boot_simple <- bootstrap_model(
  seminr_model = simple_model,
  nboot = 10000,
  cores = NULL,
  seed = 123
)
## Bootstrapping model using seminr...
## SEMinR Model successfully bootstrapped

6. Inspect significance of indirect effects

distal <- "AFF"
mediators <- c("ATT","SN","PBC")
target <- "PI"

for (f in distal) for (m in mediators) {
  specific_effect_significance(boot_simple, from = f, through = m, to = target, alpha = 0.05)
}
lapply(c("ATT","SN","PBC"), function(m) specific_effect_significance(boot_simple, from="AFF", through=m, to="PI", alpha=0.05))
## [[1]]
##  Original Est. Bootstrap Mean   Bootstrap SD        T Stat.        2.5% CI 
##     0.11728110     0.11780374     0.01716785     6.83143626     0.08533884 
##       97.5% CI 
##     0.15208106 
## 
## [[2]]
##  Original Est. Bootstrap Mean   Bootstrap SD        T Stat.        2.5% CI 
##     0.07925994     0.07923070     0.01761300     4.50008152     0.04557675 
##       97.5% CI 
##     0.11483830 
## 
## [[3]]
##  Original Est. Bootstrap Mean   Bootstrap SD        T Stat.        2.5% CI 
##     0.07233320     0.07254192     0.01884230     3.83887228     0.03606383 
##       97.5% CI 
##     0.10981183
# to inspect indirect effects
summary_boot_med<-summary(boot_simple)
summary_boot_med$bootstrapped_paths 
##              Original Est. Bootstrap Mean Bootstrap SD T Stat. 2.5% CI 97.5% CI
## ATT  ->  PI          0.199          0.200        0.026   7.694   0.149    0.250
## SN  ->  PI           0.130          0.130        0.028   4.641   0.075    0.185
## PBC  ->  PI          0.110          0.110        0.028   3.955   0.056    0.165
## AFF  ->  ATT         0.589          0.590        0.027  21.835   0.534    0.640
## AFF  ->  SN          0.609          0.609        0.025  23.973   0.558    0.657
## AFF  ->  PBC         0.657          0.657        0.024  27.197   0.607    0.703
## AFF  ->  PI          0.551          0.550        0.031  17.805   0.488    0.609

7. Inspect significance of direct effects

# to inspect direct effects
summary_simple$paths
##           PI   ATT    SN   PBC
## R^2    0.744 0.347 0.371 0.432
## AdjR^2 0.743 0.346 0.370 0.431
## ATT    0.199     .     .     .
## SN     0.130     .     .     .
## PBC    0.110     .     .     .
## AFF    0.551 0.589 0.609 0.657
# to inspect the confidence intervals for direct effects
summary_boot$bootstrapped_paths   #if significant if t-stat >1.96 and there is no zeros between CI, then it shows partial mediation
##             Original Est. Bootstrap Mean Bootstrap SD T Stat. 5% CI 95% CI
## ATT  ->  PI         0.194          0.194        0.025   7.706 0.152  0.236
## SN  ->  PI          0.130          0.130        0.028   4.670 0.085  0.176
## PBC  ->  PI         0.112          0.112        0.028   4.042 0.066  0.157
## AFF  ->  PI         0.555          0.554        0.031  18.133 0.503  0.604

8.Inspect the sign of the mediation

# FOR AFF
summary_simple$paths["AFF","ATT"]*summary_simple$paths["AFF","PI"]*summary_simple$paths["AFF","PI"]
## [1] 0.1787081
summary_simple$paths["AFF","SN"]*summary_simple$paths["AFF","PI"]*summary_simple$paths["AFF","PI"]
## [1] 0.184843
summary_simple$paths["AFF","PBC"]*summary_simple$paths["AFF","PI"]*summary_simple$paths["AFF","PI"]
## [1] 0.1994204

9.Plot estimated and bootstrapped model

plot(simple_model)
plot(boot_simple)

MODERATION ANALYSIS (2 stage approach- Chin, Marcolin adn Newsted’s 20033)

# create interaction (two-stage recommended for reflective composites)
simple_mm <- constructs(
  composite("PI", multi_items("PI",1:3)), 
  composite("ATT", multi_items("ATT",1:3)),
  composite("SN", multi_items("SN",1:3)),
  composite("PBC", multi_items("PBC",2:3)), 
  composite("AFF", multi_items("AF",1:3)),
  interaction_term(iv = "ATT",moderator = "AFF",method = two_stage),
  interaction_term(iv = "SN",moderator = "AFF",method = two_stage),
  interaction_term(iv = "PBC",moderator = "AFF",method = two_stage)
)
simple_mm
## $composite
## [1] "PI"  "PI1" "A"   "PI"  "PI2" "A"   "PI"  "PI3" "A"  
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## $composite
## [1] "ATT"  "ATT1" "A"    "ATT"  "ATT2" "A"    "ATT"  "ATT3" "A"   
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## $composite
## [1] "SN"  "SN1" "A"   "SN"  "SN2" "A"   "SN"  "SN3" "A"  
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## $composite
## [1] "PBC"  "PBC2" "A"    "PBC"  "PBC3" "A"   
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## $composite
## [1] "AFF" "AF1" "A"   "AFF" "AF2" "A"   "AFF" "AF3" "A"  
## attr(,"class")
## [1] "character" "construct" "composite"
## 
## $two_stage_interaction
## function (data, mmMatrix, structural_model, ints, estimate_first_stage, 
##     ...) 
## {
##     interaction_name <- paste(iv, moderator, sep = "*")
##     structural_model <- structural_model[!grepl("\\*", structural_model[, 
##         "source"]), ]
##     measurement_mode_scheme <- sapply(unique(c(structural_model[, 
##         1], structural_model[, 2])), get_measure_mode, mmMatrix, 
##         USE.NAMES = TRUE)
##     first_stage <- estimate_first_stage(data = data, smMatrix = structural_model, 
##         mmMatrix = mmMatrix, measurement_mode_scheme = measurement_mode_scheme, 
##         ...)
##     interaction_term <- as.matrix(first_stage$construct_scores[, 
##         iv] * first_stage$construct_scores[, moderator], ncol = 1)[, 
##         , drop = FALSE]
##     colnames(interaction_term) <- c(paste(interaction_name, "_intxn", 
##         sep = ""))
##     intxn_mm <- matrix(measure_interaction(interaction_name, 
##         interaction_term, weights), ncol = 3, byrow = TRUE)
##     return(list(name = interaction_name, data = interaction_term[, 
##         1, drop = FALSE], mm = intxn_mm))
## }
## <bytecode: 0x0000020f042b2930>
## <environment: 0x0000020f042bbc28>
## attr(,"class")
## [1] "function"              "interaction"           "two_stage_interaction"
## 
## $two_stage_interaction
## function (data, mmMatrix, structural_model, ints, estimate_first_stage, 
##     ...) 
## {
##     interaction_name <- paste(iv, moderator, sep = "*")
##     structural_model <- structural_model[!grepl("\\*", structural_model[, 
##         "source"]), ]
##     measurement_mode_scheme <- sapply(unique(c(structural_model[, 
##         1], structural_model[, 2])), get_measure_mode, mmMatrix, 
##         USE.NAMES = TRUE)
##     first_stage <- estimate_first_stage(data = data, smMatrix = structural_model, 
##         mmMatrix = mmMatrix, measurement_mode_scheme = measurement_mode_scheme, 
##         ...)
##     interaction_term <- as.matrix(first_stage$construct_scores[, 
##         iv] * first_stage$construct_scores[, moderator], ncol = 1)[, 
##         , drop = FALSE]
##     colnames(interaction_term) <- c(paste(interaction_name, "_intxn", 
##         sep = ""))
##     intxn_mm <- matrix(measure_interaction(interaction_name, 
##         interaction_term, weights), ncol = 3, byrow = TRUE)
##     return(list(name = interaction_name, data = interaction_term[, 
##         1, drop = FALSE], mm = intxn_mm))
## }
## <bytecode: 0x0000020f042b2930>
## <environment: 0x0000020f042bcd00>
## attr(,"class")
## [1] "function"              "interaction"           "two_stage_interaction"
## 
## $two_stage_interaction
## function (data, mmMatrix, structural_model, ints, estimate_first_stage, 
##     ...) 
## {
##     interaction_name <- paste(iv, moderator, sep = "*")
##     structural_model <- structural_model[!grepl("\\*", structural_model[, 
##         "source"]), ]
##     measurement_mode_scheme <- sapply(unique(c(structural_model[, 
##         1], structural_model[, 2])), get_measure_mode, mmMatrix, 
##         USE.NAMES = TRUE)
##     first_stage <- estimate_first_stage(data = data, smMatrix = structural_model, 
##         mmMatrix = mmMatrix, measurement_mode_scheme = measurement_mode_scheme, 
##         ...)
##     interaction_term <- as.matrix(first_stage$construct_scores[, 
##         iv] * first_stage$construct_scores[, moderator], ncol = 1)[, 
##         , drop = FALSE]
##     colnames(interaction_term) <- c(paste(interaction_name, "_intxn", 
##         sep = ""))
##     intxn_mm <- matrix(measure_interaction(interaction_name, 
##         interaction_term, weights), ncol = 3, byrow = TRUE)
##     return(list(name = interaction_name, data = interaction_term[, 
##         1, drop = FALSE], mm = intxn_mm))
## }
## <bytecode: 0x0000020f042b2930>
## <environment: 0x0000020f042b6720>
## attr(,"class")
## [1] "function"              "interaction"           "two_stage_interaction"
## 
## attr(,"class")
## [1] "list"              "measurement_model" "seminr_model"

2. Create the sm

simple_sm <- relationships(
  paths(from = c("ATT","SN","PBC","AFF","ATT*AFF","SN*AFF","PBC*AFF"), to = "PI")
)
simple_sm
##      source    target
## [1,] "ATT"     "PI"  
## [2,] "SN"      "PI"  
## [3,] "PBC"     "PI"  
## [4,] "AFF"     "PI"  
## [5,] "ATT*AFF" "PI"  
## [6,] "SN*AFF"  "PI"  
## [7,] "PBC*AFF" "PI"  
## attr(,"class")
## [1] "matrix"           "array"            "structural_model" "seminr_model"

3. Estimate the model

simple_mod_model <- estimate_pls(data = my_data,simple_mm,simple_sm
)
## Generating the seminr model
## All 999 observations are valid.
# to summarise
summary_mod_simple <- summary(simple_mod_model)
summary_mod_simple
## 
## Results from  package seminr (2.3.7)
## 
## Path Coefficients:
##             PI
## R^2      0.750
## AdjR^2   0.748
## ATT      0.193
## SN       0.125
## PBC      0.115
## AFF      0.544
## ATT*AFF  0.005
## SN*AFF  -0.020
## PBC*AFF -0.034
## 
## Reliability:
##         alpha  rhoC   AVE  rhoA
## ATT     0.924 0.952 0.869 0.927
## SN      0.925 0.952 0.870 0.926
## PBC     0.744 0.886 0.796 0.744
## AFF     0.737 0.851 0.657 0.745
## ATT*AFF 1.000 1.000 1.000 1.000
## SN*AFF  1.000 1.000 1.000 1.000
## PBC*AFF 1.000 1.000 1.000 1.000
## PI      0.950 0.968 0.909 0.950
## 
## Alpha, rhoC, and rhoA should exceed 0.7 while AVE should exceed 0.5

4. Bootstrap moderating model

boot_mod_simple <- bootstrap_model(
  seminr_model = simple_mod_model,
  nboot = 10000,
  cores = NULL,
  seed = 123
)
## Bootstrapping model using seminr...
## SEMinR Model successfully bootstrapped
# to inspect bootstrapped paths
summary_mod_boot<-summary(boot_mod_simple, alpha=0.05)
summary_mod_boot$bootstrapped_paths
##                 Original Est. Bootstrap Mean Bootstrap SD T Stat. 2.5% CI
## ATT  ->  PI             0.193          0.194        0.025   7.800   0.146
## SN  ->  PI              0.125          0.125        0.028   4.467   0.071
## PBC  ->  PI             0.115          0.116        0.027   4.211   0.062
## AFF  ->  PI             0.544          0.543        0.031  17.793   0.482
## ATT*AFF  ->  PI         0.005          0.006        0.021   0.240  -0.036
## SN*AFF  ->  PI         -0.020         -0.020        0.022  -0.925  -0.061
## PBC*AFF  ->  PI        -0.034         -0.035        0.018  -1.867  -0.072
##                 97.5% CI
## ATT  ->  PI        0.243
## SN  ->  PI         0.181
## PBC  ->  PI        0.169
## AFF  ->  PI        0.601
## ATT*AFF  ->  PI    0.049
## SN*AFF  ->  PI     0.025
## PBC*AFF  ->  PI   -0.000
#significant ATT*AFF->  PI has -0.033 and ATT  ->  PI  has 0.174
#Interpretation: The interaction term-ATT*WFL has a -ve effect on PI, While the simple effect ATT is +VE for average level of WFL
#Lower levels of WFL (for every standard deviation unit decrease of WFL), the relationship between ATT and PI increases the size of the interaction term(i.e 0.174-(-0.033)=0.207)

5. Compute f2 for each endogenous construct

# Extract R2 values
r2_included  <- summary_mod_simple$paths
# = 0.750
r2_excluded  <- summary_simple$paths
# =0.744
# Calculate f2
f2 = (0.750 - 0.744) / (1 - 0.750)
f2  #0.024
## [1] 0.024
#use kenny 2018 proposition to determine effects

6.Create simple slope analysis plot

slope_analysis(moderated_model = simple_mod_model,
               dv="PI",
               moderator = "AFF",
               iv="ATT",
               leg_place = "bottomright")

# check the steepness of the curve
slope_analysis(moderated_model = simple_mod_model,
               dv="PI",
               moderator = "AFF",
               iv="SN",
               leg_place = "bottomright")

# check the steepness of the curve
slope_analysis(moderated_model = simple_mod_model,
               dv="PI",
               moderator = "AFF",
               iv="PBC",
               leg_place = "bottomright")

# check the steepness of the curve