Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
fbfe21c
Merge pull request #81 from sem-in-r/master
NicholasDanks Sep 11, 2018
231ea12
Made bootstrap reproducible.
NicholasDanks Sep 11, 2018
cdf2837
Merge pull request #82 from sem-in-r/reproducibility
NicholasDanks Sep 11, 2018
2c71430
Modified all expect_equal() tests to have a tolerance of 0.00001 for …
NicholasDanks Sep 17, 2018
888cefd
Merge pull request #83 from sem-in-r/reproducibility
NicholasDanks Sep 17, 2018
47034dc
Merge branch 'master' into develop
soumyaray Oct 11, 2018
e6a24cd
Correcting for single item bug fix in Issue #84
NicholasDanks Oct 10, 2018
d37cafa
Changed logic in PLSc
NicholasDanks Oct 10, 2018
ea71b61
create demo for single item interactions
soumyaray Oct 11, 2018
2492384
Adresses Issue #84 single item interaction bug
NicholasDanks Oct 11, 2018
5015a62
Coerce rhoA to 1 for all interactions for calculation of PLSc
NicholasDanks Oct 11, 2018
1a7aa1a
bumped version and date.
NicholasDanks Oct 11, 2018
1266061
Changed version number
NicholasDanks Oct 11, 2018
4310d01
Unsure about how to report reliabilities for consistent interactions.
NicholasDanks Oct 18, 2018
df1002f
Remove this demo
NicholasDanks Oct 18, 2018
66340a3
Added tests to address Issue #84 Single item interaction bug
NicholasDanks Oct 18, 2018
770148c
Merge pull request #86 from sem-in-r/single_item_interactions
NicholasDanks Oct 18, 2018
61e3976
Bumped version number, date and added cran-comments. Amended the vign…
NicholasDanks Oct 18, 2018
6dc7c33
Merge pull request #87 from sem-in-r/Release_0.5.3
NicholasDanks Oct 19, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Package: seminr
Type: Package
Title: Domain-Specific Language for Building PLS Structural Equation Models
Version: 0.5.2
Date: 2018-09-19
Version: 0.5.3
Date: 2018-10-18
Authors@R: c(person("Soumya", "Ray",
email = "soumya.ray@gmail.com", role = c("aut", "ths")),
person("Nicholas", "Danks",
Expand Down
9 changes: 8 additions & 1 deletion R/consistent.R
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ PLSc <- function(seminr_model) {

# Calculate rho_A for adjustments and adjust the correlation matrix
rho <- rho_A(seminr_model)
### Coerce interactions to rhoA of 1
rho[grepl("\\*", rownames(rho)),] <- 1
adjustment <- sqrt(rho %*% t(rho))
diag(adjustment) <- 1
adj_construct_score_cors <- stats::cor(seminr_model$construct_scores) / adjustment
Expand Down Expand Up @@ -102,8 +104,13 @@ PLSc <- function(seminr_model) {

# Function to implement PLSc as per Dijkstra, T. K., & Henseler, J. (2015). Consistent Partial Least Squares Path Modeling, 39(X).
model_consistent <- function(seminr_model) {
# if(!is.null(seminr_model$mobi_xm) && ("C" %in% seminr_model$mmMatrix[,"type"])) {
# cat("Models with interactions cannot be estimated as PLS consistent and therefore no adjustment for PLS consistent has been made\n")
# }
if(!is.null(seminr_model$mobi_xm) && ("C" %in% seminr_model$mmMatrix[,"type"])) {
cat("Models with interactions cannot be estimated as PLS consistent and therefore no adjustment for PLS consistent has been made\n")
cat("Models with interactions can be estimated as PLS consistent, but are subject to some bias as per Becker et al. (2018)
'Estimating Moderating Effects in PLS-SEM and PLSc-SEM: Interaction Term Generation*Data Treatment'\n")
seminr_model <- PLSc(seminr_model)
}
if(is.null(seminr_model$mobi_xm) && ("C" %in% seminr_model$mmMatrix[,"type"])) {
seminr_model <- PLSc(seminr_model)
Expand Down
2 changes: 2 additions & 0 deletions R/evaluation.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
evaluate_model <- function(seminr_model) {
rel <- reliability(seminr_model)
val <- validity(seminr_model)
# Coerce reliability of interaction to 1
#rel[grepl("\\*", rownames(rel)),] <- 1
out <- list(rel,val)
names(out) <- c("reliability","validity")
return(out)
Expand Down
22 changes: 16 additions & 6 deletions R/interactions.R
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ interactions <- function(...) {
interaction_ortho <- function(construct1, construct2) {
function(data, mm) {
interaction_name <- paste(construct1, construct2, sep="*")
iv1_items <- mm[mm[, "construct"] == construct1, ][, "measurement"]
iv2_items <- mm[mm[, "construct"] == construct2, ][, "measurement"]
iv1_items <- mm[mm[, "construct"] == construct1, "measurement"]
iv2_items <- mm[mm[, "construct"] == construct2, "measurement"]

iv1_data <- as.data.frame(scale(data[iv1_items]))
iv2_data <- as.data.frame(scale(data[iv2_items]))
Expand All @@ -100,9 +100,14 @@ interaction_ortho <- function(construct1, construct2) {
iv2_data*col
}

name_items <- function(item_name) {
sapply(iv2_items, function(item2, item1 = item_name) paste(item1, item2, sep = "*"))
}

multiples_list <- lapply(iv1_data, mult)
interaction_data <- do.call("cbind", multiples_list)
colnames(interaction_data) <- gsub("\\.", "\\*", colnames(interaction_data))
#colnames(interaction_data) <- gsub("\\.", "\\*", colnames(interaction_data))
colnames(interaction_data) <- as.vector(sapply(iv1_items, name_items))

# Create formula
frmla <- stats::as.formula(paste("interaction_data[,i]",paste(as.vector(c(iv1_items,iv2_items)), collapse ="+"), sep = " ~ "))
Expand Down Expand Up @@ -159,8 +164,8 @@ interaction_ortho <- function(construct1, construct2) {
interaction_scaled <- function(construct1, construct2) {
function(data, mm) {
interaction_name <- paste(construct1, construct2, sep="*")
iv1_items <- mm[mm[, "construct"] == construct1, ][, "measurement"]
iv2_items <- mm[mm[, "construct"] == construct2, ][, "measurement"]
iv1_items <- mm[mm[, "construct"] == construct1, "measurement"]
iv2_items <- mm[mm[, "construct"] == construct2, "measurement"]

iv1_data <- as.data.frame(scale(data[iv1_items]))
iv2_data <- as.data.frame(scale(data[iv2_items]))
Expand All @@ -169,9 +174,14 @@ interaction_scaled <- function(construct1, construct2) {
iv2_data*col
}

name_items <- function(item_name) {
sapply(iv2_items, function(item2, item1 = item_name) paste(item1, item2, sep = "*"))
}

multiples_list <- lapply(iv1_data, mult)
interaction_data <- do.call("cbind", multiples_list)
colnames(interaction_data) <- gsub("\\.", "\\*", colnames(interaction_data))
#colnames(interaction_data) <- gsub("\\.", "\\*", colnames(interaction_data))
colnames(interaction_data) <- as.vector(sapply(iv1_items, name_items))

return(list(name = interaction_name, data = interaction_data))
}
Expand Down
18 changes: 3 additions & 15 deletions cran-comments.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
## Resubmission
This is a resubmission. In this version I have:

## Attended to a CRAN error:
We see such failures occasionally: for the record this time it is

SEMinR Model succesfully bootstrapped── 1. Failure: Seminr evaluates the factor discriminant validity p_values correc
diff[1, 2] is not strictly less than 0.1. Difference: 0.000314

Seems you failed to heed the warnings in §1.6 of 'Writing R Extensions': please re-read it and correct ASAP (CRAN is shut until Sep 10) and before Sep 21 to safely retain the package on CRAN.

Also try a spell checker --- it is 'successfully'.

--
Brian D. Ripley, ripley@stats.ox.ac.uk
Emeritus Professor of Applied Statistics, University of Oxford

Specifically, we updated the bootstrap method to take a seed for reproducability and added a tolerance of 0.0001 for floating point calculation tests. All tests including random processes such as bootstrapping were made reproducible.
## Attended to a user-reported error:
Single-item interactions were generating a bug in the code.
Issue #84 on https://github.com/sem-in-r/seminr/issues/84

## Test environments
* macOS Sierra 10.12.6 (on travis-ci), R 3.5.0
Expand Down
3 changes: 2 additions & 1 deletion inst/doc/SEMinR.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ mobi_pls <- estimate_pls(data = mobi,

Dijkstra and Henseler (2015) offer an adjustment to generate consistent weight and path estimates of common factors estimated using PLSPM. SEMinR automatically adjusts for consistent estimates of coefficients for common-factors defined using `reflective()`.

Note: At this point, SEMinR does not adjust for PLSc on models with interactions involving common-factors. Thus in models including common-factors and interactions, the coefficient of common-factors will be subject to bias.
Note: SEMinR does adjust for PLSc on models with interactions involving common-factors. Models with interactions can be estimated as PLS consistent, but are subject to some bias as per Becker et al. (2018). In small sample sizes, bootstrapping such a PLSc model with interactions can cause errors.

## Bootstrapping the model for significance

Expand Down Expand Up @@ -415,6 +415,7 @@ summary(boot_mobi_pls)

## References

* Becker et al. (2018). Estimating Moderating Effects in PLS-SEM and PLSc-SEM: Interaction Term Generation*Data Treatment
* Dijkstra, T. K., & Henseler, J. (2015). Consistent Partial Least Squares Path Modeling, MIS Quarterly Vol. 39(X).
* Dillon, W. R, and M. Goldstein. 1987. Multivariate Analysis: Methods, and Applications. Biometrical Journal 29 (6): 750–756.
* Fornell, C. and D. F. Larcker (February 1981). Evaluating structural equation models with unobservable variables and measurement error, Journal of Marketing Research, 18, pp. 39-5)
Expand Down
23 changes: 12 additions & 11 deletions inst/doc/SEMinR.html
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ <h3>Describe all model interactions with <code>interactions()</code></h3>
#&gt; intxns_list &lt;- lapply(all_intxns, create_interaction)
#&gt; return(intxns_list)
#&gt; }
#&gt; &lt;environment: 0x1149fa470&gt;</code></pre>
#&gt; &lt;environment: 0x10e7240d0&gt;</code></pre>
<p>Not that these functions themselves return functions that are not resolved until passed as a parameter to the <code>estimate_pls()</code> function for model estimation.</p>
</div>
<div id="describe-an-interaction-with-interaction_ortho-or-interaction_scaled" class="section level3">
Expand Down Expand Up @@ -399,7 +399,7 @@ <h2>PLS SEM Model Estimation</h2>
<div id="consistent-pls-plsc-for-common-factors" class="section level3">
<h3>Consistent PLS (PLSc) for common-factors</h3>
<p>Dijkstra and Henseler (2015) offer an adjustment to generate consistent weight and path estimates of common factors estimated using PLSPM. SEMinR automatically adjusts for consistent estimates of coefficients for common-factors defined using <code>reflective()</code>.</p>
<p>Note: At this point, SEMinR does not adjust for PLSc on models with interactions involving common-factors. Thus in models including common-factors and interactions, the coefficient of common-factors will be subject to bias.</p>
<p>Note: SEMinR does adjust for PLSc on models with interactions involving common-factors. Models with interactions can be estimated as PLS consistent, but are subject to some bias as per Becker et al. (2018). In small sample sizes, bootstrapping such a PLSc model with interactions can cause errors.</p>
</div>
</div>
<div id="bootstrapping-the-model-for-significance" class="section level2">
Expand All @@ -420,7 +420,7 @@ <h2>Bootstrapping the model for significance</h2>
nboot = 1000,
cores = 2)
#&gt; Bootstrapping model using seminr...
#&gt; SEMinR Model succesfully bootstrapped</code></pre>
#&gt; SEMinR Model successfully bootstrapped</code></pre>
<p>Notably, bootstrapping can also be meaningfully applied to models containing interaction terms and readjusts the interaction term (Henseler and Chin 2010) for every sub-sample. This leads to slightly increased processing times, but provides accurate estimations.</p>
</div>
<div id="reporting-the-pls-sem-model" class="section level2">
Expand Down Expand Up @@ -480,19 +480,19 @@ <h3>Reporting the bootstrapped <code>boot_seminr_model</code></h3>
#&gt;
#&gt; Structural Path t-values:
#&gt; Satisfaction
#&gt; Image 8.031
#&gt; Expectation 2.847
#&gt; Value 4.496
#&gt; Image*Expectation 0.936
#&gt; Image*Value 0.050
#&gt; Image 7.954
#&gt; Expectation 2.754
#&gt; Value 4.590
#&gt; Image*Expectation 0.997
#&gt; Image*Value 0.032
#&gt;
#&gt; Structural Path p-values:
#&gt; Satisfaction
#&gt; Image 0.000
#&gt; Expectation 0.005
#&gt; Expectation 0.006
#&gt; Value 0.000
#&gt; Image*Expectation 0.349
#&gt; Image*Value 0.960</code></pre>
#&gt; Image*Expectation 0.319
#&gt; Image*Value 0.974</code></pre>
<ol start="2" style="list-style-type: decimal">
<li><code>boot_model_summary &lt;- summary(boot_seminr_model)</code> returns an object of class <code>summary.boot_seminr_model</code> which contains the following accessible objects:
<ul>
Expand All @@ -506,6 +506,7 @@ <h3>Reporting the bootstrapped <code>boot_seminr_model</code></h3>
<div id="references" class="section level2">
<h2>References</h2>
<ul>
<li>Becker et al. (2018). Estimating Moderating Effects in PLS-SEM and PLSc-SEM: Interaction Term Generation*Data Treatment</li>
<li>Dijkstra, T. K., &amp; Henseler, J. (2015). Consistent Partial Least Squares Path Modeling, MIS Quarterly Vol. 39(X).</li>
<li>Dillon, W. R, and M. Goldstein. 1987. Multivariate Analysis: Methods, and Applications. Biometrical Journal 29 (6): 750–756.</li>
<li>Fornell, C. and D. F. Larcker (February 1981). Evaluating structural equation models with unobservable variables and measurement error, Journal of Marketing Research, 18, pp. 39-5)</li>
Expand Down
7 changes: 7 additions & 0 deletions tests/fixtures/plsc-interaction-paths.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"","Satisfaction"
"R^2",0.889
"AdjR^2",0.888
"Image",0.737
"Expectation",0.042
"Value",0.247
"Image*Expectation",-0.137
6 changes: 6 additions & 0 deletions tests/fixtures/plsc-interaction-reliability.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"","rhoC","AVE","rhoA"
"Image",NA,0.354977797487875,0.745311533816804
"Expectation",NA,1,1
"Value",NA,0.720468175631135,0.857495343869267
"Image*Expectation",0.779196115356173,0.440631377299172,1.6920045542643
"Satisfaction",NA,0.541895003066141,0.785065531561592
53 changes: 53 additions & 0 deletions tests/testthat/test-consistent-interactions.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
context("SEMinR correctly estimates PLSc for a simple model with interaction\n")

# Test cases
## Simple case
# Creating our measurement model
mobi_mm <- constructs(
reflective("Image", multi_items("IMAG", 1:5)),
reflective("Expectation", single_item("CUEX3")),
reflective("Value", multi_items("PERV", 1:2)),
reflective("Satisfaction", multi_items("CUSA", 1:3))
)

# Interaction constructs must be created after the measurement model is defined.
# We are using the orthogonalization method as per Henseler & Chin (2010)
mobi_xm <- interactions(
interaction_ortho("Image", "Expectation")
)

# Structural model
# note: interactions should be the names of its main constructs joined by a '*' in between.
mobi_sm <- relationships(
paths(to = "Satisfaction",
from = c("Image", "Expectation", "Value",
"Image*Expectation")
)
)

# Load data, assemble model, and estimate using simplePLS
mobi_pls <- estimate_pls(data = mobi,
measurement_model = mobi_mm,
interactions = mobi_xm,
structural_model = mobi_sm)
# Load outputs
sum <- summary(mobi_pls)

## Output originally created using following lines
# write.csv(sum$paths, file = "tests/fixtures/plsc-interaction-paths.csv")
# write.csv(sum$reliability, file = "tests/fixtures/plsc-interaction-reliability.csv")

# Load controls
paths_control <- as.matrix(read.csv("../fixtures/plsc-interaction-paths.csv", row.names = 1))
reliability_control <- as.matrix(read.csv("../fixtures/plsc-interaction-reliability.csv", row.names = 1))

# Testing

test_that("Seminr estimates paths and R2 correctly\n", {
expect_equal(sum$paths, paths_control, tolerance = 0.00001)
})

test_that("Seminr estimates rhoA, AVE, rhoC (reliability) correctly\n", {
expect_equal(sum$reliability, reliability_control, tolerance = 0.00001)
})

3 changes: 2 additions & 1 deletion vignettes/SEMinR.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ mobi_pls <- estimate_pls(data = mobi,

Dijkstra and Henseler (2015) offer an adjustment to generate consistent weight and path estimates of common factors estimated using PLSPM. SEMinR automatically adjusts for consistent estimates of coefficients for common-factors defined using `reflective()`.

Note: At this point, SEMinR does not adjust for PLSc on models with interactions involving common-factors. Thus in models including common-factors and interactions, the coefficient of common-factors will be subject to bias.
Note: SEMinR does adjust for PLSc on models with interactions involving common-factors. Models with interactions can be estimated as PLS consistent, but are subject to some bias as per Becker et al. (2018). In small sample sizes, bootstrapping such a PLSc model with interactions can cause errors.

## Bootstrapping the model for significance

Expand Down Expand Up @@ -415,6 +415,7 @@ summary(boot_mobi_pls)

## References

* Becker et al. (2018). Estimating Moderating Effects in PLS-SEM and PLSc-SEM: Interaction Term Generation*Data Treatment
* Dijkstra, T. K., & Henseler, J. (2015). Consistent Partial Least Squares Path Modeling, MIS Quarterly Vol. 39(X).
* Dillon, W. R, and M. Goldstein. 1987. Multivariate Analysis: Methods, and Applications. Biometrical Journal 29 (6): 750–756.
* Fornell, C. and D. F. Larcker (February 1981). Evaluating structural equation models with unobservable variables and measurement error, Journal of Marketing Research, 18, pp. 39-5)
Expand Down