codemark 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/codemark/rmd_to_r.rb +2 -1
- data/lib/codemark/version.rb +1 -1
- data/spec/codemark_spec.rb +14 -0
- data/spec/fixtures/model-spec.R +271 -0
- data/spec/fixtures/model-spec.Rmd +299 -0
- data/spec/fixtures/sem-intro.R +39 -6
- data/spec/fixtures/sem-intro.Rmd +46 -11
- data/spec/spec_helper.rb +10 -0
- metadata +9 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bffb893a2827f10d055586cb6611fb018e4dd5d764ae93998639683998a6ab44
|
4
|
+
data.tar.gz: 8843c925fe441a75285b4f8c9301f25dfc49bdd4010066b87d4124a0aea87d5f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e7ba662e2cc135dcd1ce87bd98b7c0c5e039571f54e107a90906fe4450b2c9ad9d85555d9d4b0e7b200ddbbe0436ccae0aec0b47e28bf073dc333be4ed770d4
|
7
|
+
data.tar.gz: 101c2b7ff450c654ffc0cfb383cbbf911f39b9cd3f283b70c8d4a8bcae02413d8bc9151125e2f4d58b43fcd14f108cc3799d7a4d7c9c0e97b0e5a0c0fcfca292
|
data/lib/codemark/rmd_to_r.rb
CHANGED
@@ -6,7 +6,8 @@ module CodeMark
|
|
6
6
|
class MarkdownToR < Redcarpet::Render::Base
|
7
7
|
def preprocess(full_document)
|
8
8
|
# strip headers
|
9
|
-
headers_rx = "^---\n([
|
9
|
+
# headers_rx = "^---\n([\sa-zA-Z0-9_]+:.[^\n]+\n)+---\n"
|
10
|
+
headers_rx = "^---\n.*---\n"
|
10
11
|
regx = /(?<headers>#{headers_rx})(?<body>.*)/m
|
11
12
|
doc = full_document.match(regx)
|
12
13
|
doc[:body]
|
data/lib/codemark/version.rb
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Create correct R file' do
|
4
|
+
describe 'When we convert a known Rmd file' do
|
5
|
+
it 'should create known R output' do
|
6
|
+
rmd = Redcarpet::Markdown.new(CodeMark::MarkdownToR.new, extensions = {})
|
7
|
+
r_script = rmd.render(INTRO_RMD)
|
8
|
+
_(r_script).must_equal(INTRO_R)
|
9
|
+
|
10
|
+
r_script = rmd.render(MODEL_RMD)
|
11
|
+
_(r_script).must_equal(MODEL_R)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,271 @@
|
|
1
|
+
#* Introduction to Model Specification
|
2
|
+
|
3
|
+
#* Specifying the Measurement Model
|
4
|
+
|
5
|
+
influence_mm <- constructs(
|
6
|
+
# specifications of your various constructs go here
|
7
|
+
)
|
8
|
+
|
9
|
+
# Note that in the above code, we are capturing our definition of all our
|
10
|
+
# constructs in a variable called `influence_mm` for later use. Within the
|
11
|
+
# `constructs()` function, we must define each of our constructs.
|
12
|
+
|
13
|
+
# Constructs can be either *common factors* or *composites*, and SEMinR allows
|
14
|
+
# your models to have one or both types of constructs in your models if your
|
15
|
+
# estimation method permits it.
|
16
|
+
|
17
|
+
#* Common-Factor Models
|
18
|
+
|
19
|
+
# Common factors are latent, unmeasurable concepts whose variance is reflected
|
20
|
+
# in base measurement items, which in turn can be thought of as symptoms or
|
21
|
+
# results of the underlying factor. Common factors are specified in SEMinR using
|
22
|
+
# the `reflective()` function:
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
# Reflective function example:
|
27
|
+
influence_mm <- constructs(
|
28
|
+
reflective("PL", multi_items("pl_", 1:4)),
|
29
|
+
reflective("SIC", multi_items("sic_", 1:7)),
|
30
|
+
reflective("PI", multi_items("pi_", 1:5)))
|
31
|
+
|
32
|
+
# Note the that the `reflective()` function requires two parameters: -
|
33
|
+
# `construct_name`: the name of the construct, such as `"PL"` above -
|
34
|
+
# `item_names`: the names of the items for that construct
|
35
|
+
|
36
|
+
# The item names could be named separately and combined using the `c()`
|
37
|
+
# function of R as follow:
|
38
|
+
|
39
|
+
reflective("PL", c("pl_1", "pl_2", "pl_3", "pl_4"))
|
40
|
+
|
41
|
+
# However, typing the items separately can feel repetitive and present
|
42
|
+
# opportunities for typos. Thus, SEMinR offers the `multi_items()` function that
|
43
|
+
# can capture multiple repetitive item names as a simple sequence:
|
44
|
+
|
45
|
+
reflective("PL", multi_items("pl_", 1:4))
|
46
|
+
|
47
|
+
#* Composite Models
|
48
|
+
|
49
|
+
# In contrast, composites derive their meaning from their measurement items,
|
50
|
+
# and so are modeled as merely a weighted average of their items. Composites are
|
51
|
+
# specified in SEMinR using the `composite()` function. We can redefine the
|
52
|
+
# earlier constructs as composites:
|
53
|
+
|
54
|
+
influence_mm <- constructs(
|
55
|
+
composite("PL", multi_items("pl_", 1:4)),
|
56
|
+
composite("SIC", multi_items("sic_", 1:7)),
|
57
|
+
composite("PI", multi_items("pi_", 1:5)))
|
58
|
+
|
59
|
+
# Note the that the `composite()` function can take the following parameters: -
|
60
|
+
# `construct_name`: the name of the construct, such as `"PL"` above -
|
61
|
+
# `item_names`: the names of the items for that construct - `weights`:
|
62
|
+
# optionally specify how items of a construct should be weighted in taking their
|
63
|
+
# average (defaults to `correlation_weights`)
|
64
|
+
|
65
|
+
# Composites have scores that are computed by taking a weighted average of
|
66
|
+
# their items. There are two possible weighting schemes that SEMinR supports:
|
67
|
+
|
68
|
+
#** Correlation weighting
|
69
|
+
|
70
|
+
# The default weighting scheme for items of composites is to use their
|
71
|
+
# individual correlations with the overall composite as their weight:
|
72
|
+
|
73
|
+
composite("PL", multi_items("pl_", 1:4), weights = correlation_weights)
|
74
|
+
|
75
|
+
#** Regression weighting
|
76
|
+
|
77
|
+
# Alternatively, items of a composite can be regressed over their composite,
|
78
|
+
# and their regression coefficients can be used as their weights:
|
79
|
+
|
80
|
+
composite("PL", multi_items("pl_", 1:4), weights = regression_weights)
|
81
|
+
|
82
|
+
#* Structural Models
|
83
|
+
|
84
|
+
# The relationships between constructs are defined within the `relationships()`
|
85
|
+
# function, using the `paths()` function for groups of causal paths.
|
86
|
+
|
87
|
+
influence_sm <- relationships(
|
88
|
+
paths(from = "SIC", to = c("PL", "PI")),
|
89
|
+
paths(from = c("SIC", "PL"), to = "PI"))
|
90
|
+
|
91
|
+
# The above set of relationships is saved in the `influence_sm` object for
|
92
|
+
# later estimation.
|
93
|
+
|
94
|
+
# The individual causal paths are specified in the `paths()` functions above.
|
95
|
+
# Note that groups of paths can be specified together if they share the same
|
96
|
+
# antecedent or outcome construct. For example, the following code defines two
|
97
|
+
# causal paths, both from the `SIC` construct with one going to the `PL`
|
98
|
+
# construct and one to the `PI` construct.
|
99
|
+
|
100
|
+
paths(from = "SIC", to = c("PL", "PI"))
|
101
|
+
|
102
|
+
#* Estimation Methods
|
103
|
+
|
104
|
+
# There are two dominant sets of methods for estimating and evaluating
|
105
|
+
# constructs or entire SEMs: covariance-based estimation or partial least
|
106
|
+
# squares modeling.
|
107
|
+
|
108
|
+
#** Covariance-based Estimation
|
109
|
+
|
110
|
+
# Covariance-based methods are preferred when all constructs are common
|
111
|
+
# factors. SEMinR supports evaluating the measurement model of common factors
|
112
|
+
# using confirmatory factor analysis (CFA), and the structural model using
|
113
|
+
# covariance-based structural equation modeling (CBSEM)
|
114
|
+
|
115
|
+
#*** Confirmatory Factor Analysis
|
116
|
+
|
117
|
+
# A common validation of the measurement of common factor models is conducting
|
118
|
+
# a confirmatory factor analysis (CFA). SEMinR can use the `Lavaan` package to
|
119
|
+
# estimate parameters of a measurement model using CFA:
|
120
|
+
|
121
|
+
influence_mm <- constructs(
|
122
|
+
reflective("PL", multi_items("pl_", 1:4)),
|
123
|
+
reflective("SIC", multi_items("sic_", 1:7)),
|
124
|
+
reflective("PI", multi_items("pi_", 1:5)))
|
125
|
+
|
126
|
+
influencer_data <- read.csv("data/influencer_data_book_final.csv")
|
127
|
+
cfa_model <- estimate_cfa(data = influencer_data, influence_mm)
|
128
|
+
|
129
|
+
cat(cfa_model$lavaan_model)
|
130
|
+
|
131
|
+
cfa_report <- summary(cfa_model)
|
132
|
+
|
133
|
+
# The summary contains many useful results that researchers will want to
|
134
|
+
# analyze and report:
|
135
|
+
|
136
|
+
cfa_report$loadings
|
137
|
+
|
138
|
+
|
139
|
+
|
140
|
+
# Quality Metrics:
|
141
|
+
cfa_report$quality$fit
|
142
|
+
cfa_report$quality$reliability
|
143
|
+
|
144
|
+
# Correlations:
|
145
|
+
cfa_report$descriptives$correlations$constructs
|
146
|
+
round( cfa_report$descriptives$correlations$items, 2)
|
147
|
+
|
148
|
+
#*** Common-Factor Structural Models
|
149
|
+
|
150
|
+
# With a common-factor measurement model in place, you may define and estimate
|
151
|
+
# a structural model. The preferred method of estimating common factor SEMs is
|
152
|
+
# using covariance-based SEM — we one again leverage the powerful `Lavaan`
|
153
|
+
# package to estimate for CBSEM.
|
154
|
+
|
155
|
+
influence_sm <- relationships(
|
156
|
+
paths(from = c("PL", "SIC"), to = "PI"))
|
157
|
+
|
158
|
+
cbsem_model <- estimate_cbsem(influencer_data, influence_mm, influence_sm)
|
159
|
+
|
160
|
+
plot(cbsem_model$construct_scores[, c("PL", "PI")])
|
161
|
+
|
162
|
+
# However, a full report of results comes again from the `summary()`:
|
163
|
+
|
164
|
+
cbsem_report <- summary(cbsem_model)
|
165
|
+
|
166
|
+
# This summary object will now contain all essential metrics, including fit
|
167
|
+
# indices that researchers wish to report. There are many fit metrics reported
|
168
|
+
# so here we will show only a subset of 10 criteria from all the fit metrics:
|
169
|
+
|
170
|
+
cbsem_report$quality$fit$all[1:10]
|
171
|
+
|
172
|
+
cbsem_report$quality$fit$curated
|
173
|
+
|
174
|
+
#** Partial Least Squares
|
175
|
+
|
176
|
+
# Partial Least Squares Path Modeling (PLS-PM) is often the preferred method to
|
177
|
+
# estimate composite models. PLS-PM does not support estimating measurement
|
178
|
+
# models alone; rather, the measurement model and structural model are estimated
|
179
|
+
# together.
|
180
|
+
|
181
|
+
influence_mm <- constructs(
|
182
|
+
composite("PL", multi_items("pl_", 1:4)),
|
183
|
+
composite("SIC", multi_items("sic_", 1:7)),
|
184
|
+
composite("PI", multi_items("pi_", 1:5)))
|
185
|
+
|
186
|
+
influence_sm <- relationships(
|
187
|
+
paths(from = c("PL", "SIC"), to = "PI"))
|
188
|
+
|
189
|
+
pls_model <- estimate_pls(influencer_data, influence_mm, influence_sm)
|
190
|
+
|
191
|
+
plot(pls_model$construct_scores[, c("PL", "PI")])
|
192
|
+
|
193
|
+
# A full report with more extensive is once again available using the
|
194
|
+
# `summary()` function:
|
195
|
+
|
196
|
+
summary(pls_model)
|
197
|
+
|
198
|
+
plot(pls_model)
|
199
|
+
|
200
|
+
#* Reusability and Composability
|
201
|
+
|
202
|
+
# The syntax for SEMinR allows researchers to create reusable and composable
|
203
|
+
# blocks of code. For example, one can use the same measurement model for
|
204
|
+
# multiple structural models, such as a proposed model and an alternative model.
|
205
|
+
|
206
|
+
influence_mm <- constructs(
|
207
|
+
reflective("PL", multi_items("pl_", 1:4)),
|
208
|
+
reflective("SIC", multi_items("sic_", 1:7)),
|
209
|
+
reflective("PQ", multi_items("pq_", 1:4)),
|
210
|
+
reflective("PIC", multi_items("pic_", 1:5)),
|
211
|
+
reflective("PI", multi_items("pi_", 1:5)),
|
212
|
+
reflective("WTP", single_item("wtp")))
|
213
|
+
|
214
|
+
proposed_sm <- relationships(
|
215
|
+
paths(from = c("PL", "SIC"), to = c("PQ", "PIC")),
|
216
|
+
paths(from = c("PQ", "PIC"), to = c("PI", "WTP")))
|
217
|
+
|
218
|
+
alternative_sm <- relationships(
|
219
|
+
paths(from = c("PL", "SIC"), to = c("PI", "WTP")))
|
220
|
+
|
221
|
+
proposed_model <- estimate_cbsem(influencer_data, influence_mm, proposed_sm)
|
222
|
+
alternative_model <- estimate_cbsem(influencer_data, influence_mm, alternative_sm)
|
223
|
+
|
224
|
+
# As you get more comfortable with R, you will find even more ways to make your
|
225
|
+
# model syntax elegant and readable. The following example shows how to create
|
226
|
+
# named groups of constructs to make the structural models highly readable:
|
227
|
+
|
228
|
+
|
229
|
+
|
230
|
+
# Assuming measurement model and constructs are already defined...
|
231
|
+
antecedents <- c("PL", "SIC")
|
232
|
+
mediators <- c("PQ", "PIC")
|
233
|
+
outcomes <- c("PI", "WTP")
|
234
|
+
|
235
|
+
proposed_sm <- relationships(
|
236
|
+
paths(from = antecedents, to = mediators),
|
237
|
+
paths(from = mediators, to = outcomes))
|
238
|
+
|
239
|
+
alternative_sm <- relationships(
|
240
|
+
paths(from = antecedents, to = outcomes))
|
241
|
+
|
242
|
+
proposed_model <- estimate_cbsem(influencer_data, influence_mm, proposed_sm)
|
243
|
+
alternative_model <- estimate_cbsem(influencer_data, influence_mm, alternative_sm)
|
244
|
+
|
245
|
+
# There are many more options and outputs you can avail in SEMinR, but I hope
|
246
|
+
# this gives a gentle introduction to major topics. Please see our Advanced
|
247
|
+
# Topics booklet for more details.
|
248
|
+
|
249
|
+
#* Join us
|
250
|
+
|
251
|
+
# We recommend you join our community of users and developers on various social
|
252
|
+
# media and collaborative platforms.
|
253
|
+
|
254
|
+
#** Collaboration and Feedback
|
255
|
+
|
256
|
+
# We have a Github repository where you can see our latest instructions:
|
257
|
+
|
258
|
+
# https://github.com/sem-in-r/seminr
|
259
|
+
|
260
|
+
# Please use this repository to report suspected bugs that you wish us to track
|
261
|
+
# and fix. You will have to create a Github account to report such issues:
|
262
|
+
|
263
|
+
# https://github.com/sem-in-r/seminr/issues
|
264
|
+
|
265
|
+
#** Social Media
|
266
|
+
|
267
|
+
# We have a Facebook group of like-minded researchers where we ask questions
|
268
|
+
# about SEMinR and also keep abreast of developments around SEM.
|
269
|
+
|
270
|
+
# https://www.facebook.com/groups/seminr/
|
271
|
+
|
@@ -0,0 +1,299 @@
|
|
1
|
+
---
|
2
|
+
title: "Model Specification"
|
3
|
+
author: "Soumya Ray, Nicholas Danks"
|
4
|
+
date: "4/27/2021"
|
5
|
+
output:
|
6
|
+
pdf_document:
|
7
|
+
toc: true
|
8
|
+
toc_depth: 4
|
9
|
+
number_sections: true
|
10
|
+
always_allow_html: true
|
11
|
+
---
|
12
|
+
\newpage
|
13
|
+
|
14
|
+
# Introduction to Model Specification
|
15
|
+
|
16
|
+
```{r, echo=FALSE}
|
17
|
+
library(seminr)
|
18
|
+
```
|
19
|
+
|
20
|
+
In the introduction, we saw how the syntax of SEMinR mirrors the langauge of SEM practitioners. It's time to dig deeper into the different kinds of modeling schemes that SEMinR allows. This booklet will introduce you to the basic syntax for defining various types of models and estimating results.
|
21
|
+
|
22
|
+
# Specifying the Measurement Model
|
23
|
+
|
24
|
+
Constructs are the concepts that we wish to statistically represent. They are grouped together in SEMinR syntax using the `constructs()` function:
|
25
|
+
|
26
|
+
```{r, eval=FALSE}
|
27
|
+
influence_mm <- constructs(
|
28
|
+
# specifications of your various constructs go here
|
29
|
+
)
|
30
|
+
```
|
31
|
+
|
32
|
+
Note that in the above code, we are capturing our definition of all our constructs in a variable called `influence_mm` for later use. Within the `constructs()` function, we must define each of our constructs.
|
33
|
+
|
34
|
+
Constructs can be either *common factors* or *composites*, and SEMinR allows your models to have one or both types of constructs in your models if your estimation method permits it.
|
35
|
+
|
36
|
+
# Common-Factor Models
|
37
|
+
|
38
|
+
Common factors are latent, unmeasurable concepts whose variance is reflected in base measurement items, which in turn can be thought of as symptoms or results of the underlying factor. Common factors are specified in SEMinR using the `reflective()` function:
|
39
|
+
|
40
|
+
```{r, eval=FALSE}
|
41
|
+
# Reflective function example:
|
42
|
+
influence_mm <- constructs(
|
43
|
+
reflective("PL", multi_items("pl_", 1:4)),
|
44
|
+
reflective("SIC", multi_items("sic_", 1:7)),
|
45
|
+
reflective("PI", multi_items("pi_", 1:5)))
|
46
|
+
```
|
47
|
+
|
48
|
+
Note the that the `reflective()` function requires two parameters:
|
49
|
+
- `construct_name`: the name of the construct, such as `"PL"` above
|
50
|
+
- `item_names`: the names of the items for that construct
|
51
|
+
|
52
|
+
The item names could be named separately and combined using the `c()` function of R as follow:
|
53
|
+
|
54
|
+
```{r, eval=FALSE}
|
55
|
+
reflective("PL", c("pl_1", "pl_2", "pl_3", "pl_4"))
|
56
|
+
```
|
57
|
+
|
58
|
+
However, typing the items separately can feel repetitive and present opportunities for typos. Thus, SEMinR offers the `multi_items()` function that can capture multiple repetitive item names as a simple sequence:
|
59
|
+
|
60
|
+
```{r, eval=FALSE}
|
61
|
+
reflective("PL", multi_items("pl_", 1:4))
|
62
|
+
```
|
63
|
+
|
64
|
+
\newpage
|
65
|
+
# Composite Models
|
66
|
+
|
67
|
+
In contrast, composites derive their meaning from their measurement items, and so are modeled as merely a weighted average of their items. Composites are specified in SEMinR using the `composite()` function. We can redefine the earlier constructs as composites:
|
68
|
+
|
69
|
+
```{r, eval=FALSE}
|
70
|
+
influence_mm <- constructs(
|
71
|
+
composite("PL", multi_items("pl_", 1:4)),
|
72
|
+
composite("SIC", multi_items("sic_", 1:7)),
|
73
|
+
composite("PI", multi_items("pi_", 1:5)))
|
74
|
+
```
|
75
|
+
|
76
|
+
Note the that the `composite()` function can take the following parameters:
|
77
|
+
- `construct_name`: the name of the construct, such as `"PL"` above
|
78
|
+
- `item_names`: the names of the items for that construct
|
79
|
+
- `weights`: optionally specify how items of a construct should be weighted in taking their average (defaults to `correlation_weights`)
|
80
|
+
|
81
|
+
Composites have scores that are computed by taking a weighted average of their items. There are two possible weighting schemes that SEMinR supports:
|
82
|
+
|
83
|
+
## Correlation weighting
|
84
|
+
|
85
|
+
The default weighting scheme for items of composites is to use their individual correlations with the overall composite as their weight:
|
86
|
+
|
87
|
+
```{r, eval=FALSE}
|
88
|
+
composite("PL", multi_items("pl_", 1:4), weights = correlation_weights)
|
89
|
+
```
|
90
|
+
|
91
|
+
## Regression weighting
|
92
|
+
|
93
|
+
Alternatively, items of a composite can be regressed over their composite, and their regression coefficients can be used as their weights:
|
94
|
+
|
95
|
+
```{r, eval=FALSE}
|
96
|
+
composite("PL", multi_items("pl_", 1:4), weights = regression_weights)
|
97
|
+
```
|
98
|
+
|
99
|
+
# Structural Models
|
100
|
+
|
101
|
+
The relationships between constructs are defined within the `relationships()` function, using the `paths()` function for groups of causal paths.
|
102
|
+
|
103
|
+
```{r eval=FALSE}
|
104
|
+
influence_sm <- relationships(
|
105
|
+
paths(from = "SIC", to = c("PL", "PI")),
|
106
|
+
paths(from = c("SIC", "PL"), to = "PI"))
|
107
|
+
```
|
108
|
+
|
109
|
+
The above set of relationships is saved in the `influence_sm` object for later estimation.
|
110
|
+
|
111
|
+
The individual causal paths are specified in the `paths()` functions above. Note that groups of paths can be specified together if they share the same antecedent or outcome construct. For example, the following code defines two causal paths, both from the `SIC` construct with one going to the `PL` construct and one to the `PI` construct.
|
112
|
+
|
113
|
+
```{r eval=FALSE}
|
114
|
+
paths(from = "SIC", to = c("PL", "PI"))
|
115
|
+
```
|
116
|
+
|
117
|
+
\newpage
|
118
|
+
# Estimation Methods
|
119
|
+
|
120
|
+
There are two dominant sets of methods for estimating and evaluating constructs or entire SEMs: covariance-based estimation or partial least squares modeling.
|
121
|
+
|
122
|
+
## Covariance-based Estimation
|
123
|
+
|
124
|
+
Covariance-based methods are preferred when all constructs are common factors. SEMinR supports evaluating the measurement model of common factors using confirmatory factor analysis (CFA), and the structural model using covariance-based structural equation modeling (CBSEM)
|
125
|
+
|
126
|
+
### Confirmatory Factor Analysis
|
127
|
+
|
128
|
+
A common validation of the measurement of common factor models is conducting a confirmatory factor analysis (CFA). SEMinR can use the `Lavaan` package to estimate parameters of a measurement model using CFA:
|
129
|
+
|
130
|
+
```{r}
|
131
|
+
influence_mm <- constructs(
|
132
|
+
reflective("PL", multi_items("pl_", 1:4)),
|
133
|
+
reflective("SIC", multi_items("sic_", 1:7)),
|
134
|
+
reflective("PI", multi_items("pi_", 1:5)))
|
135
|
+
|
136
|
+
influencer_data <- read.csv("data/influencer_data_book_final.csv")
|
137
|
+
cfa_model <- estimate_cfa(data = influencer_data, influence_mm)
|
138
|
+
```
|
139
|
+
If you are familiar with the `Lavaan` package for CFA/CBSEM in R, then the syntax that SEMinR uses to define your measurement model for `Lavaan` is available in the returned object and might be of interest to you:
|
140
|
+
|
141
|
+
```{r}
|
142
|
+
cat(cfa_model$lavaan_model)
|
143
|
+
```
|
144
|
+
A full report of the CFA estimation is made available when you run the `summary()`:
|
145
|
+
|
146
|
+
```{r}
|
147
|
+
cfa_report <- summary(cfa_model)
|
148
|
+
```
|
149
|
+
|
150
|
+
The summary contains many useful results that researchers will want to analyze and report:
|
151
|
+
|
152
|
+
```{r}
|
153
|
+
cfa_report$loadings
|
154
|
+
```
|
155
|
+
|
156
|
+
You may try looking deeper into some of the summary objects to find interesting details:
|
157
|
+
```{r, eval=FALSE}
|
158
|
+
# Quality Metrics:
|
159
|
+
cfa_report$quality$fit
|
160
|
+
cfa_report$quality$reliability
|
161
|
+
|
162
|
+
# Correlations:
|
163
|
+
cfa_report$descriptives$correlations$constructs
|
164
|
+
round( cfa_report$descriptives$correlations$items, 2)
|
165
|
+
```
|
166
|
+
|
167
|
+
### Common-Factor Structural Models
|
168
|
+
|
169
|
+
With a common-factor measurement model in place, you may define and estimate a structural model. The preferred method of estimating common factor SEMs is using covariance-based SEM — we one again leverage the powerful `Lavaan` package to estimate for CBSEM.
|
170
|
+
|
171
|
+
```{r}
|
172
|
+
influence_sm <- relationships(
|
173
|
+
paths(from = c("PL", "SIC"), to = "PI"))
|
174
|
+
|
175
|
+
cbsem_model <- estimate_cbsem(influencer_data, influence_mm, influence_sm)
|
176
|
+
```
|
177
|
+
As before, you the object returned in CBSEM estimation contains some useful or interesting details. In particular, one can get or plot the *estimated* construct scores (note that CBSEM does not produce determinible scores so these are estimated) as scatterplot.
|
178
|
+
|
179
|
+
```{r}
|
180
|
+
plot(cbsem_model$construct_scores[, c("PL", "PI")])
|
181
|
+
```
|
182
|
+
|
183
|
+
However, a full report of results comes again from the `summary()`:
|
184
|
+
|
185
|
+
```{r}
|
186
|
+
cbsem_report <- summary(cbsem_model)
|
187
|
+
```
|
188
|
+
|
189
|
+
This summary object will now contain all essential metrics, including fit indices that researchers wish to report. There are many fit metrics reported so here we will show only a subset of 10 criteria from all the fit metrics:
|
190
|
+
|
191
|
+
```{r}
|
192
|
+
cbsem_report$quality$fit$all[1:10]
|
193
|
+
```
|
194
|
+
|
195
|
+
SEMinR produces a curated set of fit indices that are either popular in the literature and the more robust fit indices:
|
196
|
+
```{r}
|
197
|
+
cbsem_report$quality$fit$curated
|
198
|
+
```
|
199
|
+
|
200
|
+
\newpage
|
201
|
+
## Partial Least Squares
|
202
|
+
|
203
|
+
Partial Least Squares Path Modeling (PLS-PM) is often the preferred method to estimate composite models. PLS-PM does not support estimating measurement models alone; rather, the measurement model and structural model are estimated together.
|
204
|
+
|
205
|
+
```{r}
|
206
|
+
influence_mm <- constructs(
|
207
|
+
composite("PL", multi_items("pl_", 1:4)),
|
208
|
+
composite("SIC", multi_items("sic_", 1:7)),
|
209
|
+
composite("PI", multi_items("pi_", 1:5)))
|
210
|
+
|
211
|
+
influence_sm <- relationships(
|
212
|
+
paths(from = c("PL", "SIC"), to = "PI"))
|
213
|
+
|
214
|
+
pls_model <- estimate_pls(influencer_data, influence_mm, influence_sm)
|
215
|
+
```
|
216
|
+
The estimated object contains several details that may interest researchers, such as estimated path coefficients:
|
217
|
+
|
218
|
+
```{r}
|
219
|
+
plot(pls_model$construct_scores[, c("PL", "PI")])
|
220
|
+
```
|
221
|
+
|
222
|
+
A full report with more extensive is once again available using the `summary()` function:
|
223
|
+
|
224
|
+
```{r}
|
225
|
+
summary(pls_model)
|
226
|
+
```
|
227
|
+
And finally, we can visualize our results:
|
228
|
+
|
229
|
+
```{r}
|
230
|
+
plot(pls_model)
|
231
|
+
```
|
232
|
+
|
233
|
+
\newpage
|
234
|
+
# Reusability and Composability
|
235
|
+
|
236
|
+
The syntax for SEMinR allows researchers to create reusable and composable blocks of code. For example, one can use the same measurement model for multiple structural models, such as a proposed model and an alternative model.
|
237
|
+
|
238
|
+
```{r, eval=FALSE}
|
239
|
+
influence_mm <- constructs(
|
240
|
+
reflective("PL", multi_items("pl_", 1:4)),
|
241
|
+
reflective("SIC", multi_items("sic_", 1:7)),
|
242
|
+
reflective("PQ", multi_items("pq_", 1:4)),
|
243
|
+
reflective("PIC", multi_items("pic_", 1:5)),
|
244
|
+
reflective("PI", multi_items("pi_", 1:5)),
|
245
|
+
reflective("WTP", single_item("wtp")))
|
246
|
+
|
247
|
+
proposed_sm <- relationships(
|
248
|
+
paths(from = c("PL", "SIC"), to = c("PQ", "PIC")),
|
249
|
+
paths(from = c("PQ", "PIC"), to = c("PI", "WTP")))
|
250
|
+
|
251
|
+
alternative_sm <- relationships(
|
252
|
+
paths(from = c("PL", "SIC"), to = c("PI", "WTP")))
|
253
|
+
|
254
|
+
proposed_model <- estimate_cbsem(influencer_data, influence_mm, proposed_sm)
|
255
|
+
alternative_model <- estimate_cbsem(influencer_data, influence_mm, alternative_sm)
|
256
|
+
```
|
257
|
+
|
258
|
+
As you get more comfortable with R, you will find even more ways to make your model syntax elegant and readable. The following example shows how to create named groups of constructs to make the structural models highly readable:
|
259
|
+
|
260
|
+
```{r, eval=FALSE}
|
261
|
+
# Assuming measurement model and constructs are already defined...
|
262
|
+
|
263
|
+
antecedents <- c("PL", "SIC")
|
264
|
+
mediators <- c("PQ", "PIC")
|
265
|
+
outcomes <- c("PI", "WTP")
|
266
|
+
|
267
|
+
proposed_sm <- relationships(
|
268
|
+
paths(from = antecedents, to = mediators),
|
269
|
+
paths(from = mediators, to = outcomes))
|
270
|
+
|
271
|
+
alternative_sm <- relationships(
|
272
|
+
paths(from = antecedents, to = outcomes))
|
273
|
+
|
274
|
+
proposed_model <- estimate_cbsem(influencer_data, influence_mm, proposed_sm)
|
275
|
+
alternative_model <- estimate_cbsem(influencer_data, influence_mm, alternative_sm)
|
276
|
+
```
|
277
|
+
|
278
|
+
There are many more options and outputs you can avail in SEMinR, but I hope this gives a gentle introduction to major topics. Please see our Advanced Topics booklet for more details.
|
279
|
+
|
280
|
+
\newpage
|
281
|
+
# Join us
|
282
|
+
|
283
|
+
We recommend you join our community of users and developers on various social media and collaborative platforms.
|
284
|
+
|
285
|
+
## Collaboration and Feedback
|
286
|
+
|
287
|
+
We have a Github repository where you can see our latest instructions:
|
288
|
+
|
289
|
+
https://github.com/sem-in-r/seminr
|
290
|
+
|
291
|
+
Please use this repository to report suspected bugs that you wish us to track and fix. You will have to create a Github account to report such issues:
|
292
|
+
|
293
|
+
https://github.com/sem-in-r/seminr/issues
|
294
|
+
|
295
|
+
## Social Media
|
296
|
+
|
297
|
+
We have a Facebook group of like-minded researchers where we ask questions about SEMinR and also keep abreast of developments around SEM.
|
298
|
+
|
299
|
+
https://www.facebook.com/groups/seminr/
|
data/spec/fixtures/sem-intro.R
CHANGED
@@ -4,6 +4,8 @@
|
|
4
4
|
# [Swirl](https://swirlstats.com/students.html) tutorials in RStudio. Here, we
|
5
5
|
# review the most basic essentials to R.
|
6
6
|
|
7
|
+
#** R Basics
|
8
|
+
|
7
9
|
# Variables: R allows you to store data, values, and results of your analyses
|
8
10
|
# in variables. Here is an example of how to assign values to variables:
|
9
11
|
|
@@ -33,7 +35,7 @@ construct_names[2]
|
|
33
35
|
|
34
36
|
construct_definition$items
|
35
37
|
|
36
|
-
# Operations
|
38
|
+
# **Operations**: Simple mathematical operations can be computed on values
|
37
39
|
# (numbers, words, etc.) or on variables. R is specially suited to performing
|
38
40
|
# operations on vectors (like our `numbers` from above).
|
39
41
|
|
@@ -43,10 +45,23 @@ numbers <- 1:5
|
|
43
45
|
|
44
46
|
numbers^2
|
45
47
|
|
46
|
-
# Functions
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
48
|
+
# **Functions**: Purposeful sequence of operations that are encapsulated in R
|
49
|
+
# code. Functions can be called by their name and supplying them with any input
|
50
|
+
# necessary for them to run. Functions typically return results that can be
|
51
|
+
# assigned to a variable. Some functions also output reports to the screen.
|
52
|
+
|
53
|
+
seq(1, 5)
|
54
|
+
|
55
|
+
sum(numbers)
|
56
|
+
|
57
|
+
help(seq)
|
58
|
+
?seq
|
59
|
+
|
60
|
+
#** Example: Regression analysis
|
61
|
+
|
62
|
+
# The following code runs a short regression analysis on data, and shows us a
|
63
|
+
# short, simple workflow. Note that comments (descriptive text that does not
|
64
|
+
# run) is prefixed with a pound sign ("#").
|
50
65
|
|
51
66
|
|
52
67
|
|
@@ -80,10 +95,28 @@ regr_report$r.squared
|
|
80
95
|
# parameters of an SEM can then be **estimated** and **visualized** by the
|
81
96
|
# SEMinR package.
|
82
97
|
|
83
|
-
#*
|
98
|
+
#* Installing and Using SEMinR
|
99
|
+
|
100
|
+
install.packages("seminr")
|
101
|
+
|
102
|
+
# You are done! You do not have to run that function call again unless you want
|
103
|
+
# to update SEMinR on your local machine to a newer version.
|
104
|
+
|
105
|
+
# However, everytime you restart RStudio to work on an SEM project, you must
|
106
|
+
# *load* the SEMinR package back into RStudio:
|
84
107
|
|
85
108
|
library(seminr)
|
86
109
|
|
110
|
+
# From here,you are ready to write and run code that defines and estimates your
|
111
|
+
# SEM models.
|
112
|
+
|
113
|
+
#* Measurement Model
|
114
|
+
|
115
|
+
# We can define the measurement model of an SEM simply by describing each
|
116
|
+
# construct by its set of *measurement items* that *reflect* the underlying
|
117
|
+
# concept. Let's see a simplified example from the Influencer model and dataset
|
118
|
+
# we will use:
|
119
|
+
|
87
120
|
influence_mm <- constructs(
|
88
121
|
reflective("PL", multi_items("pl_", 1:4)),
|
89
122
|
reflective("PQ", multi_items("pq_", 1:4)),
|
data/spec/fixtures/sem-intro.Rmd
CHANGED
@@ -10,6 +10,8 @@ always_allow_html: true
|
|
10
10
|
|
11
11
|
The best way to learn R from scratch is by installing and running the [Swirl](https://swirlstats.com/students.html) tutorials in RStudio. Here, we review the most basic essentials to R.
|
12
12
|
|
13
|
+
## R Basics
|
14
|
+
|
13
15
|
Variables: R allows you to store data, values, and results of your analyses in variables. Here is an example of how to assign values to variables:
|
14
16
|
|
15
17
|
```{r}
|
@@ -40,7 +42,9 @@ construct_names[2]
|
|
40
42
|
construct_definition$items
|
41
43
|
```
|
42
44
|
|
43
|
-
|
45
|
+
\newpage
|
46
|
+
|
47
|
+
**Operations**: Simple mathematical operations can be computed on values (numbers, words, etc.) or on variables. R is specially suited to performing operations on vectors (like our `numbers` from above).
|
44
48
|
|
45
49
|
```{r, }
|
46
50
|
5 * 2
|
@@ -50,7 +54,21 @@ numbers <- 1:5
|
|
50
54
|
numbers^2
|
51
55
|
```
|
52
56
|
|
53
|
-
Functions
|
57
|
+
**Functions**: Purposeful sequence of operations that are encapsulated in R code. Functions can be called by their name and supplying them with any input necessary for them to run. Functions typically return results that can be assigned to a variable. Some functions also output reports to the screen.
|
58
|
+
|
59
|
+
```{r, }
|
60
|
+
seq(1, 5)
|
61
|
+
|
62
|
+
sum(numbers)
|
63
|
+
|
64
|
+
help(seq)
|
65
|
+
?seq
|
66
|
+
```
|
67
|
+
|
68
|
+
|
69
|
+
## Example: Regression analysis
|
70
|
+
|
71
|
+
The following code runs a short regression analysis on data, and shows us a short, simple workflow. Note that comments (descriptive text that does not run) is prefixed with a pound sign ("#").
|
54
72
|
|
55
73
|
```{r}
|
56
74
|
# load data from a file into a variable using the "read.csv" function
|
@@ -93,16 +111,36 @@ influence_model <- specify_model(influence_mm, influence_sm)
|
|
93
111
|
influence_model_plot <- plot(influence_model)
|
94
112
|
save_plot("figures/influencer_model_plot.png", influence_model_plot)
|
95
113
|
```
|
96
|
-
|
114
|
+
|
115
|
+
```{r simpleModel, fig.align = 'center', out.width = "30%", fig.cap = "Simplified Influencer Model", echo = F}
|
97
116
|
knitr::include_graphics("figures/influencer_model_plot.png")
|
98
117
|
```
|
99
118
|
|
100
|
-
|
119
|
+
\newpage
|
120
|
+
|
121
|
+
# Installing and Using SEMinR
|
122
|
+
|
123
|
+
To install SEMinR in RStudio, simply use the following function call:
|
124
|
+
|
125
|
+
```{r, eval=FALSE}
|
126
|
+
install.packages("seminr")
|
127
|
+
```
|
128
|
+
|
129
|
+
You are done! You do not have to run that function call again unless you want to update SEMinR on your local machine to a newer version.
|
130
|
+
|
131
|
+
However, everytime you restart RStudio to work on an SEM project, you must *load* the SEMinR package back into RStudio:
|
101
132
|
|
102
|
-
We can define the measurement model of an SEM simply by describing each construct by its set of *measurement items* that *reflect* the underlying concept. Let's see a simplified example from the Influencer model and dataset we will use:
|
103
133
|
```{r}
|
104
134
|
library(seminr)
|
135
|
+
```
|
136
|
+
|
137
|
+
From here,you are ready to write and run code that defines and estimates your SEM models.
|
138
|
+
|
139
|
+
# Measurement Model
|
140
|
+
|
141
|
+
We can define the measurement model of an SEM simply by describing each construct by its set of *measurement items* that *reflect* the underlying concept. Let's see a simplified example from the Influencer model and dataset we will use:
|
105
142
|
|
143
|
+
```{r}
|
106
144
|
influence_mm <- constructs(
|
107
145
|
reflective("PL", multi_items("pl_", 1:4)),
|
108
146
|
reflective("PQ", multi_items("pq_", 1:4)),
|
@@ -146,8 +184,6 @@ The `influence_model` object in which the estimation is stored does not contain
|
|
146
184
|
influence_summary <- summary(influence_model)
|
147
185
|
```
|
148
186
|
|
149
|
-
\newpage
|
150
|
-
|
151
187
|
The `influence_summary` object holds a wealth of other estimated values that researchers might wish to inspect or report. For example, researchers applying CB-SEM are typically interested in the quality of the estimation, including details of how well the SEM model *fits* the data (we show only a part of the full fit report below):
|
152
188
|
|
153
189
|
```{r eval=FALSE, echo=TRUE}
|
@@ -180,6 +216,7 @@ Researchers often find that it is helpful to get a high-level glimpse of their m
|
|
180
216
|
plot(influence_model)
|
181
217
|
```
|
182
218
|
|
219
|
+
|
183
220
|
```{r echo=FALSE, results='hide', cache=TRUE}
|
184
221
|
png(filename = "figures/influence_estimated_plot.png", width = 900, height=600)
|
185
222
|
plot(influence_model)
|
@@ -194,7 +231,7 @@ We hope this brief introduction gives you a sense of how SEMinR fits into your S
|
|
194
231
|
|
195
232
|
# Join us
|
196
233
|
|
197
|
-
|
234
|
+
Join our community of users and developers on various social media and collaborative platforms to discuss issues, share ideas, and request new features.
|
198
235
|
|
199
236
|
## Collaboration and Feedback
|
200
237
|
|
@@ -208,6 +245,4 @@ https://github.com/sem-in-r/seminr/issues
|
|
208
245
|
|
209
246
|
## Social Media
|
210
247
|
|
211
|
-
We have a Facebook group of like-minded researchers where we ask questions about SEMinR and also keep abreast of developments around SEM.
|
212
|
-
|
213
|
-
https://www.facebook.com/groups/seminr/
|
248
|
+
We have a Facebook group of like-minded researchers where we ask questions about SEMinR and also keep abreast of developments around SEM: https://www.facebook.com/groups/seminr/
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'minitest/rg'
|
3
|
+
|
4
|
+
require './lib/codemark.rb'
|
5
|
+
|
6
|
+
INTRO_RMD = File.read("./spec/fixtures/sem-intro.Rmd")
|
7
|
+
INTRO_R = File.read("./spec/fixtures/sem-intro.R")
|
8
|
+
|
9
|
+
MODEL_RMD = File.read("./spec/fixtures/model-spec.Rmd")
|
10
|
+
MODEL_R = File.read("./spec/fixtures/model-spec.R")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: codemark
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Soumya Ray
|
@@ -103,8 +103,12 @@ files:
|
|
103
103
|
- lib/codemark.rb
|
104
104
|
- lib/codemark/rmd_to_r.rb
|
105
105
|
- lib/codemark/version.rb
|
106
|
+
- spec/codemark_spec.rb
|
107
|
+
- spec/fixtures/model-spec.R
|
108
|
+
- spec/fixtures/model-spec.Rmd
|
106
109
|
- spec/fixtures/sem-intro.R
|
107
110
|
- spec/fixtures/sem-intro.Rmd
|
111
|
+
- spec/spec_helper.rb
|
108
112
|
homepage: https://github.com/soumyaray/codemark
|
109
113
|
licenses:
|
110
114
|
- MIT
|
@@ -129,5 +133,9 @@ signing_key:
|
|
129
133
|
specification_version: 4
|
130
134
|
summary: Converts RMarkdown files to pure R scripts
|
131
135
|
test_files:
|
136
|
+
- spec/codemark_spec.rb
|
137
|
+
- spec/fixtures/model-spec.R
|
138
|
+
- spec/fixtures/model-spec.Rmd
|
132
139
|
- spec/fixtures/sem-intro.R
|
133
140
|
- spec/fixtures/sem-intro.Rmd
|
141
|
+
- spec/spec_helper.rb
|