diff --git a/README.md b/README.md index 7be83bf4..a3138c9d 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ To read the guides (vignettes) on how to use the functions, you can build the vi remotes::install_github("sfcheung/semptools", build_vignettes = TRUE) ``` -You can also find the guides under *Articles* of the [Github page](https://sfcheung.github.io/semptools/) of this package. +You can also find the guides under [*Articles*](https://sfcheung.github.io/semptools/articles/) of the [Github page](https://sfcheung.github.io/semptools/) of this package. # Background @@ -43,54 +43,108 @@ You can also find the guides under *Articles* of the [Github page](https://sfche # Philosophy -We think about the tasks we usually want to do with an `semPlot::semPaths()` graph, and write one function for each task. We write the functions such that all of them work by postprocessing a `semPlot::semPaths()` graph: receive an `semPlot::semPaths()` graph, modify it, and return a modified `semPlot::semPaths()` graph. This also allows users to use the `%>%` (pipe) operator from the `magrittr` package or -the native pipe operator `|>` available since R 4.1.x to chain together modifications. For example: +We though about the tasks we usually want to do with a `semPlot::semPaths()` graph, and wrote one function for each task. We wrote the functions such that all of them work by postprocessing a `semPlot::semPaths()` graph: receive a `semPlot::semPaths()` graph, modify it, and return a modified `semPlot::semPaths()` graph. This also allows users to use the +the R pipe operator `|>` available since R 4.1.x (or the `%>%` operator from the `magrittr` package) to chain together modifications. For example: ```r -modified_graph <- original_graph %>% - task_1() %>% - task_2(other_arguments) %>% +modified_graph <- original_graph |> + task_1() |> + task_2(other_arguments) |> task_3() ``` -In psychology, two typical models are confirmatory factor analysis model and structural models with latent factors. Therefore, we also wrote two functions, one for each model, that can combine several common tasks together, such as specifying the positions of the latent factors and adjusting the positions of the indicators. +In psychology, two typical models are confirmatory factor analysis model and structural models with latent factors. Therefore, we also wrote two functions, `set_cfa_layout()` and `set_sem_layout()`, that can combine several common tasks together, such as specifying the positions of the latent factors and adjusting the positions of the indicators. -We also write the functions in a way that users do not need to know the technical detail (e.g., the position of the path in the list of all paths). For example, if a user wants to move the path coefficient of the path from `x` to `y` closer to `y`, the user only needs to tell the function that it is the path from `x` to `y`. The function will find which path it is in the `qgraph` object. +We also wrote the functions in a way that users do not need to know the technical detail (e.g., the position of the path in the list of all paths). For example, if a user wants to move the path coefficient of the path from `x` to `y` closer to `y`, the user only needs to tell the function that it is the path from `x` to `y`. The function will find which path it is in the `qgraph` object. # What we have so far -These are some of the functions included so far +These are some functions included so far: + +## Add elements based on parameter estimates - `mark_se()`: Add the standard errors to parameter estimates. +- `mark_ci()`: Add the confidence intervals to parameter estimates. + - `mark_sig()`: Add asterisks ("\*", "\*\*", "\*\*\*") based on $p$-values of parameter estimates. - `add_rsq()`: Add R-squares (and remove the error variances) to endogenous variables. +## Edit lines ("edges", such as paths, covariances, and error variances) + - `rotate_resid()`: Rotate the residuals of selected variables. - `set_curve()`: Change the curvature of selected paths. - `set_edge_color()`: Change the colors of selected paths. -- `set_edge_attribute()`: Change the named attributes of selected paths. +- `set_edge_line_type()`, `set_edge_line_width()`: Change the line types + (e.g., solid, dashed, dotted) and line widths of selected paths. + +- `set_edge_label()`, `set_edge_label_bg()`, `set_edge_label_size()`: + Change the labels of selected paths directly. - `set_edge_label_position()`: Move the parameter labels of selected paths along the paths. +- `safe_edge_label_position()`: Try to move edge labels (e.g., regression coefficients) to prevent overlapping of labels. + +- `safe_resid_position()`: Try to rotate residuals of nodes to prevent overlapping. + +- `set_edge_attribute()`: A generic function to change + any named attributes of selected paths. + +## Edit variables ("nodes", the "squares" and "circles") + - `change_node_label()`: Change the labels of nodes. -- `set_node_attribute()`: Change the named attributes of selected nodes. +- `set_node_label_color()`, `set_node_label_size()`: Change + the colors and sizes of the labels of selected nodes. + +- `set_node_color()`, `set_node_height()`, `set_node_shape()`, + `set_node_size()`, `set_node_width()`: Change the aesthetic + aspects of selected nodes. + +- `set_node_border_color()`, `set_node_border_width()`: Change + the colors and widths of the borders of nodes (e.g., the + color and width of the line of a square). - `drop_nodes()` and `keep_nodes()`: Drop or keeps nodes (e.g., drop all control variables). +- `move_node()`: "Move" (change the positions of) selected nodes. + +- `node_labels_equal_scale()`: Make all labels of nodes have the same font size. + +- `set_node_attribute()`: A generic function to change + any named attributes of selected nodes. + +## Common layouts + - `set_cfa_layout()`: A function for typical confirmatory factor analysis models. It can be used for specifying the orders of the indicators and factors, specifying the positions of the factors, setting the curvatures of the interfactor covariances, set the position of all loadings, and setting the orientation of the model (down, left, up, or right). - `set_sem_layout()`: A function for typical SEM models. It can be used for specifying the orders of the indicators and factors, specifying the positions of the factors using a grid, specifying the orientation of each factor's indicators (down, left, up, right), fine tuning the positions of indicators of selected factor, setting the curvatures of selected paths, and specifying the position of all or selected loadings. +- `quick_simple_mediation()`, `quick_serial_mediation()`, and +`quick_parallel_mediation()`: Functions for common mediation models. +They will try to set the positions of nodes automatically. The positions +of nodes can be adjusted by `move_node()` to achieve the desired layout. + +## Miscellaneous helpers + +- `layout_matrix()`: A helper to specify how to place the nodes. + +- `set_graph_margins()`: Change the margins of a plot. + - `rescale_layout()`: Rescale a plot to fit the plot area. See the [Get Started](https://sfcheung.github.io/semptools/articles/semptools.html) to learn more about these and other functions. +## Multigroup models and list of models + +Since version 0.3.3.17, most functions support figures of +multigroup models, which are stored as a list of `qgraph` +plots. + # Status This package is still under development. There will be bugs, and there are limitations. Please diff --git a/vignettes/semptools.Rmd b/vignettes/semptools.Rmd index f4df2937..73746535 100644 --- a/vignettes/semptools.Rmd +++ b/vignettes/semptools.Rmd @@ -37,7 +37,7 @@ generated by `semPlot::semPaths()`. The following sections were written to be self-contained, with some elements repeated, such that each of them can be read individually. -# Mark all parameter estimates by asterisks based on p-Value: `mark_sig` +# Mark all parameter estimates by asterisks based on p-values: `mark_sig()` Let us consider a simple path analysis model: @@ -59,15 +59,17 @@ library(semPlot) m <- matrix(c("x1", NA, NA, NA, NA, "x3", NA, "x4", "x2", NA, NA, NA), byrow = TRUE, 3, 4) -p_pa <- semPaths(fit_pa, whatLabels = "est", - sizeMan = 10, - edge.label.cex = 1.15, - style = "ram", - nCharNodes = 0, nCharEdges = 0, - layout = m) +p_pa <- semPaths( + fit_pa, whatLabels = "est", + sizeMan = 10, + edge.label.cex = 1.15, + style = "ram", + nCharNodes = 0, + nCharEdges = 0, + layout = m) ``` -We know from the `lavaan::lavaan()` output that some paths are significant +We know from the `lavaan::sem()` output that some paths are significant and some are not. In some disciplines, asterisks are conventionally added indicate this. However, `semPlot::semPaths()` does not do this. We can use `mark_sig()` to add asterisks @@ -75,12 +77,16 @@ based on the p-values of the free parameters. ```{r} library(semptools) -p_pa2 <- mark_sig(p_pa, fit_pa) +p_pa2 <- mark_sig( + p_pa, + fit_pa +) plot(p_pa2) ``` -The first argument, `semPaths_plot`, is the output from `semPaths::semPlot()`. -The second argument, `object`, is the `lavaan::lavaan()` output used to +- The first argument, `semPaths_plot`, is the output from `semPaths::semPlot()`. + +- The second argument, `object`, is the `lavaan::lavaan()` output used to generate the plot. This output is needed to extract the *p*-values. The default labels follow the common convention: "\*" for *p* less than .05, @@ -89,11 +95,16 @@ changed by the argument `alpha` (this must be named as the it is not the second argument). E.g.: ```{r} -p_pa3 <- mark_sig(p_pa, fit_pa, alpha = c("(n.s.)" = 1.00, "*" = .01)) +p_pa3 <- mark_sig( + p_pa, + fit_pa, + alpha = c(" (n.s.)" = 1.00, + "*" = .01) +) plot(p_pa3) ``` -# Add standard error estimates to parameter estimates: `mark_se` +# Add standard error estimates or confidence interval: `mark_se()` and `mark_ci()` Let us consider a simple path analysis model: @@ -104,7 +115,10 @@ mod_pa <- x3 ~ x1 + x2 x4 ~ x1 + x3 ' -fit_pa <- lavaan::sem(mod_pa, pa_example) +fit_pa <- lavaan::sem( + mod_pa, + pa_example +) parameterEstimates(fit_pa) ``` @@ -115,44 +129,62 @@ library(semPlot) m <- matrix(c("x1", NA, NA, NA, NA, "x3", NA, "x4", "x2", NA, NA, NA), byrow = TRUE, 3, 4) -p_pa <- semPaths(fit_pa, whatLabels = "est", - sizeMan = 10, - edge.label.cex = 1.15, - style = "ram", - nCharNodes = 0, nCharEdges = 0, - layout = m) +p_pa <- semPaths( + fit_pa, + whatLabels = "est", + sizeMan = 10, + edge.label.cex = 1.15, + style = "ram", + nCharNodes = 0, + nCharEdges = 0, + layout = m +) ``` We can use `mark_se()` to add the standard errors for the parameter estimates: ```{r} library(semptools) -p_pa2 <- mark_se(p_pa, fit_pa) +p_pa2 <- mark_se( + p_pa, + fit_pa +) plot(p_pa2) ``` -The first argument, `semPaths_plot`, is the output from `semPaths::semPlot()`. -The second argument, `object`, is the `lavaan::lavaan()` output used to -generate the plot. This output is needed to extra the standard errors. +- The first argument, `semPaths_plot`, is the output from `semPaths::semPlot()`. + +- The second argument, `object`, is the `lavaan::sem()` output used to +generate the plot. This output is needed to extract the standard errors. By default, the standard errors are enclosed by parentheses and appended to -the parameter estimates, separated by one space. The argument `sep` can be +the parameter estimates, separated by one space. + +The argument `sep` can be used to use another separator. For example, if `"\n"` is used, the standard errors will be displayed below the corresponding parameter estimates. ```{r} -p_pa2 <- mark_se(p_pa, fit_pa, sep = "\n") +p_pa2 <- mark_se( + p_pa, + fit_pa, + sep = "\n" +) plot(p_pa2) ``` Similarly, one can use `mark_ci()` to add confidence intervals: ```{r} -p_pa2_ci <- mark_ci(p_pa, fit_pa, sep = "\n") +p_pa2_ci <- mark_ci( + p_pa, + fit_pa, + sep = "\n" +) plot(p_pa2_ci) ``` -# Rotate the residuals of selected variables: `rotate_resid` +# Rotate the residuals: `rotate_resid()` and `safe_resid_position()` Let us consider a simple path analysis model: @@ -163,7 +195,10 @@ mod_pa <- x3 ~ x1 + x2 x4 ~ x1 + x3 ' -fit_pa <- lavaan::sem(mod_pa, pa_example) +fit_pa <- lavaan::sem( + mod_pa, + pa_example +) ``` This is the plot from `semPlot::semPaths()`. @@ -173,12 +208,16 @@ library(semPlot) m <- matrix(c("x1", NA, NA, NA, NA, "x3", NA, "x4", "x2", NA, NA, NA), byrow = TRUE, 3, 4) -p_pa <- semPaths(fit_pa, whatLabels = "est", - sizeMan = 10, - edge.label.cex = 1.15, - style = "ram", - nCharNodes = 0, nCharEdges = 0, - layout = m) +p_pa <- semPaths( + fit_pa, + whatLabels = "est", + sizeMan = 10, + edge.label.cex = 1.15, + style = "ram", + nCharNodes = 0, + nCharEdges = 0, + layout = m +) ``` Suppose we want to rotate the residuals of some variables to improve readability. @@ -197,27 +236,42 @@ position is negative. Therefore, top-right is 45, top-left is -45, and left is -90. We then use `rotate_resid()` to post-process the `semPlot::semPaths()` output. -The first argument, `semPaths_plot`, is the `semPlot::semPaths()` output. -The second argument, `rotate_resid_list`, is the vector to specify how the + +- The first argument, `semPaths_plot`, is the `semPlot::semPaths()` output. + +- The second argument, `rotate_resid_list`, is the vector to specify how the residuals should be rotated. The name is the node for which the residual will be rotated, and the value is the degree of rotation. + For example, to achieve -the results described above, the vector is `c(x3 = 45, x4 = -45, x2 = -90)`: +the results described above, the vector is `c(x3 = 135, x4 = 180, x2 = -90)`: ```{r} library(semptools) -my_rotate_resid_list <- c(x3 = 45, - x4 = -45, +my_rotate_resid_list <- c(x3 = 135, + x4 = 180, x2 = -90) -p_pa3 <- rotate_resid(p_pa, my_rotate_resid_list) +p_pa3 <- rotate_resid( + p_pa, + my_rotate_resid_list +) plot(p_pa3) ``` (Note: This function accepts named vectors since version 0.2.8. Lists of named -list are still supported but not suggested. Please see `?rotate_resid` on +list are still supported but not recommended. Please see `?rotate_resid` on how to use lists of named list.) -# Set the curve attributes of selected arrows: `set_curve` +If we just want to try preventing overlapping in labels, +we can use `safe_resid_position()`, which will try to +rotate residuals automatically: + +```{r} +p_pa4 <- safe_resid_position(p_pa) +plot(p_pa4) +``` + +# Set the curve attributes: `set_curve()` Let us consider a simple path analysis model: @@ -228,7 +282,10 @@ mod_pa <- x3 ~ x1 + x2 x4 ~ x1 + x3 ' -fit_pa <- lavaan::sem(mod_pa, pa_example) +fit_pa <- lavaan::sem( + mod_pa, + pa_example +) ``` This is the plot from `semPaths`. @@ -238,12 +295,16 @@ library(semPlot) m <- matrix(c("x1", NA, NA, NA, NA, "x3", NA, "x4", "x2", NA, NA, NA), byrow = TRUE, 3, 4) -p_pa <- semPaths(fit_pa, whatLabels = "est", - sizeMan = 10, - edge.label.cex = 1.15, - style = "ram", - nCharNodes = 0, nCharEdges = 0, - layout = m) +p_pa <- semPaths( + fit_pa, + whatLabels = "est", + sizeMan = 10, + edge.label.cex = 1.15, + style = "ram", + nCharNodes = 0, + nCharEdges = 0, + layout = m +) ``` Suppose we want to change the curvature of these two arrows (`edges`): @@ -253,9 +314,12 @@ Suppose we want to change the curvature of these two arrows (`edges`): - Have the `x4 ~ x1` path curved upward. We then use `set_curve()` to post-process the `semPlot::semPaths()` output. -The first -argument, `semPaths_plot`, is the `semPlot::semPaths()` output. The second argument, ` -curve_list`, is the list to specify the new curvature of the selected arrows. + +- The first + argument, `semPaths_plot`, is the `semPlot::semPaths()` output. + +- The second argument, `curve_list`, is the vector or list to specify + the new curvature of the selected arrows. The "name" of each element is of the same form as `lhs-op-rhs` as in `lavaan::lavaan()` model syntax. In `lavaan`, @@ -265,12 +329,15 @@ the element is `"y ~ x" = -3`. Note that whether `~` or `~~` is used does not matter. To achieve the changes described above, we can use -`c("x2 ~~ x1" = -3, "x4 ~ x1" = 2)`, as shown below: +`c("x2 ~~ x1" = -2, "x4 ~ x1" = 1)`, as shown below: ```{r} -my_curve_list <- c("x2 ~~ x1" = -3, - "x4 ~ x1" = 2) -p_pa3 <- set_curve(p_pa, my_curve_list) +my_curve_list <- c("x2 ~~ x1" = -2, + "x4 ~ x1" = 1) +p_pa3 <- set_curve( + p_pa, + my_curve_list +) plot(p_pa3) ``` @@ -290,7 +357,7 @@ arrows of the `qgraph` object will be updated. list are still supported but not suggested. Please see `?set_curve` on how to use lists of named list.) -# Set the positions of parameters of selected arrows: `set_edge_label_position` +# Set the positions of parameters: `set_edge_label_position()` Let us consider a simple path analysis model: @@ -301,7 +368,10 @@ mod_pa <- x3 ~ x1 + x2 x4 ~ x1 + x3 ' -fit_pa <- lavaan::sem(mod_pa, pa_example) +fit_pa <- lavaan::sem( + mod_pa, + pa_example +) ``` This is the plot from `semPlot::semPaths()`. @@ -311,12 +381,16 @@ library(semPlot) m <- matrix(c("x1", NA, NA, NA, NA, "x3", NA, "x4", "x2", NA, NA, NA), byrow = TRUE, 3, 4) -p_pa <- semPaths(fit_pa, whatLabels = "est", - sizeMan = 10, - edge.label.cex = 1.15, - style = "ram", - nCharNodes = 0, nCharEdges = 0, - layout = m) +p_pa <- semPaths( + fit_pa, + whatLabels = "est", + sizeMan = 10, + edge.label.cex = 1.15, + style = "ram", + nCharNodes = 0, + nCharEdges = 0, + layout = m +) ``` Suppose we want to move the parameter estimates this way: @@ -329,28 +403,33 @@ Suppose we want to move the parameter estimates this way: We can use `set_edge_label_position()` to post-process the `semPlot::semPaths` output. -The first argument, `semPaths_plot`, is the `semPlot::semPaths()` output. -The second -argument, `position_list`, is the list to specify the new position of the + +- The first argument, `semPaths_plot`, is the `semPlot::semPaths()` output. + +- The second +argument, `position_list`, is the vector or list to specify the new position of the selected arrows. We can use a named vector to specify the changes. The "name" of each element is of the same form as `lhs-op-rhs` as in `lavaan::lavaan()` model syntax. In `lavaan`, `y ~ x` denotes an arrow from `x` to `y`. Therefore, if we want -to change the curvature of the path *from* `x` *to* `y` to -3, then -the element is `"y ~ x" = -3`. Note that whether `~` or `~~` is used +to set the position of the parameter of path *from* `x` *to* `y` to .25, then +the element is `"y ~ x" = .25`. Note that whether `~` or `~~` is used does not matter. Therefore, the changes described above can be specified by -`c("x2 ~~ x1" = -3, "x4 ~ x1" = 2)`, as shown below: +`c("x3 ~~ x1" = .25, "x3 ~ x2" = .25, "x4 ~ x1" = .7)`, as shown below: ```{r} library(semptools) my_position_list <- c("x3 ~ x1" = .25, "x3 ~ x2" = .25, "x4 ~ x1" = .75) -p_pa3 <- set_edge_label_position(p_pa, my_position_list) +p_pa3 <- set_edge_label_position( + p_pa, + my_position_list +) plot(p_pa3) ``` @@ -359,7 +438,7 @@ list are still supported but not suggested. Please see `?set_edge_label_position` on how to use lists of named list.) -# Change one or more node labels: `change_node_label` +# Change one or more node labels: `change_node_label()` `semPlot::semPaths()` supports changing the labels of nodes when generating a plot through the argument `nodeLabels`. However, if we @@ -369,8 +448,9 @@ then we cannot use `nodeLabels` because these functions do not (yet) know how to map a user-defined label to the variables in the `lavaan` output. One solution is to use `semptools` functions to process the `qgraph` -generated by `semPlot::semPaths()`, and change the node labels in +generated by `semPlot::semPaths()`, and change the node labels in the *last step* to create the final plot. + This can be done by `change_node_label()`. Let us consider a simple path analysis model in which we use `marg_sig()` @@ -385,17 +465,28 @@ mod_pa <- x3 ~ x1 + x2 x4 ~ x1 + x3 ' -fit_pa <- lavaan::sem(mod_pa, pa_example) +fit_pa <- lavaan::sem( + mod_pa, + pa_example +) m <- matrix(c("x1", NA, NA, NA, NA, "x3", NA, "x4", "x2", NA, NA, NA), byrow = TRUE, 3, 4) -p_pa <- semPaths(fit_pa, whatLabels = "est", - sizeMan = 10, - edge.label.cex = 1.15, - style = "ram", - nCharNodes = 0, nCharEdges = 0, - layout = m) -p_pa2 <- mark_sig(p_pa, fit_pa, alpha = c("(n.s.)" = 1.00, "*" = .01)) +p_pa <- semPaths( + fit_pa, + whatLabels = "est", + sizeMan = 10, + edge.label.cex = 1.15, + style = "ram", + nCharNodes = 0, + nCharEdges = 0, + layout = m +) +p_pa2 <- mark_sig( + p_pa, + fit_pa, + alpha = c(" (n.s.)" = 1.00, "*" = .01) +) plot(p_pa2) ``` @@ -404,12 +495,14 @@ Suppose we want change `x1`, `x2`, `x3`, and `x4` to `Attitude`, above, by `change_node_label()` as below: ```{r} -p_pa3 <- change_node_label(p_pa2, - c(x1 = "Attitude", - x2 = "SbjNorm", - x3 = "Intention", - x4 = "Behavior"), - label.cex = 1.1) +p_pa3 <- change_node_label( + p_pa2, + c(x1 = "Attitude", + x2 = "SbjNorm", + x3 = "Intention", + x4 = "Behavior"), + label.cex = 1.1 +) plot(p_pa3) ``` @@ -435,7 +528,10 @@ mod_pa <- x3 ~ x1 + x2 x4 ~ x1 + x3 ' -fit_pa <- lavaan::sem(mod_pa, pa_example) +fit_pa <- lavaan::sem( + mod_pa, + pa_example +) ``` This is the initial plot: @@ -445,12 +541,16 @@ library(semPlot) m <- matrix(c("x1", NA, NA, NA, NA, "x3", NA, "x4", "x2", NA, NA, NA), byrow = TRUE, 3, 4) -p_pa <- semPaths(fit_pa, whatLabels = "est", - sizeMan = 10, - edge.label.cex = 1.15, - style = "ram", - nCharNodes = 0, nCharEdges = 0, - layout = m) +p_pa <- semPaths( + fit_pa, + whatLabels = "est", + sizeMan = 10, + edge.label.cex = 1.15, + style = "ram", + nCharNodes = 0, + nCharEdges = 0, + layout = m +) ``` We will do this: @@ -465,43 +565,43 @@ We will do this: - Move the parameter estimate of the `x4 ~ x1` path closer to `x4`. -```{r eval = FALSE} -my_position_list <- c("x4 ~ x1" = .75) -my_curve_list <- c("x2 ~ x1" = -2) -my_rotate_resid_list <- c(x1 = 0, x2 = 180, x3 = 140, x4 = 140) -my_position_list <- c("x4 ~ x1" = .65) -# If R version 4.1.0 or above -p_pa3 <- p_pa |> set_curve(my_curve_list) |> - rotate_resid(my_rotate_resid_list) |> - mark_sig(fit_pa) |> - mark_se(fit_pa, sep = "\n") |> - set_edge_label_position(my_position_list) +```{r eval = TRUE} +p_pa3 <- p_pa |> + set_curve(c("x2 ~ x1" = -2)) |> + rotate_resid(c(x1 = 0, x2 = 180, x3 = 140, x4 = 140)) |> + mark_sig(fit_pa) |> + mark_se(fit_pa, sep = "\n") |> + set_edge_label_position(c("x4 ~ x1" = .65)) |> + change_node_label(c(x1 = "Attitude", + x2 = "SbjNorm", + x3 = "Intention", + x4 = "Behavior")) plot(p_pa3) ``` ```{r echo = FALSE} -my_position_list <- c("x4 ~ x1" = .75) -my_curve_list <- c("x2 ~ x1" = -2) -my_rotate_resid_list <- c(x1 = 0, x2 = 180, x3 = 140, x4 = 140) -my_position_list <- c("x4 ~ x1" = .65) -# if ((compareVersion(as.character(getRversion()), "4.1.0")) >= 0) { -# p_pa3 <- p_pa |> set_curve(my_curve_list) |> -# rotate_resid(my_rotate_resid_list) |> -# mark_sig(fit_pa) |> -# mark_se(fit_pa, sep = "\n") |> +# my_position_list <- c("x4 ~ x1" = .75) +# my_curve_list <- c("x2 ~ x1" = -2) +# my_rotate_resid_list <- c(x1 = 0, x2 = 180, x3 = 140, x4 = 140) +# my_position_list <- c("x4 ~ x1" = .65) +# # if ((compareVersion(as.character(getRversion()), "4.1.0")) >= 0) { +# # p_pa3 <- p_pa |> set_curve(my_curve_list) |> +# # rotate_resid(my_rotate_resid_list) |> +# # mark_sig(fit_pa) |> +# # mark_se(fit_pa, sep = "\n") |> +# # set_edge_label_position(my_position_list) +# # } else { +# require(magrittr) +# p_pa3 <- p_pa %>% set_curve(my_curve_list) %>% +# rotate_resid(my_rotate_resid_list) %>% +# mark_sig(fit_pa) %>% +# mark_se(fit_pa, sep = "\n") %>% # set_edge_label_position(my_position_list) -# } else { - require(magrittr) - p_pa3 <- p_pa %>% set_curve(my_curve_list) %>% - rotate_resid(my_rotate_resid_list) %>% - mark_sig(fit_pa) %>% - mark_se(fit_pa, sep = "\n") %>% - set_edge_label_position(my_position_list) - # } -plot(p_pa3) +# # } +# plot(p_pa3) ``` -For most of the functions, the necessary argument beside the `semPlot::semPaths` +For most of the functions, the necessary argument beside the `semPlot::semPaths()` output, if any, is the second element. Therefore, they can be included as unnamed arguments. For the third and other optional arguments, such as `sep` for `mark_se()`, it is better to name them.