├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ ├── check-standard.yaml │ └── test-coverage.yaml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONDUCT.md ├── CRAN-SUBMISSION ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── NEWS.md ├── R ├── as.tidyLPA.r ├── calc_functions.R ├── compare-solutions.R ├── data-documentation.R ├── data-mac.R ├── empathy.R ├── estimate-profiles-mclust.R ├── estimate-profiles-mplus.R ├── estimate-profiles-openmx.R ├── estimate-profiles.R ├── helpers.R ├── id_edu.R ├── missing_data.R ├── openmx.R ├── plot-bivariate.R ├── plot-mixture_densities.R ├── plot-profiles.R ├── plot.tidyLPA.R └── tidylpa.r ├── README.Rmd ├── README.md ├── SUPPORT.md ├── cran-comments.md ├── data ├── curry_mac.csv ├── empathy.csv ├── id_edu.csv └── pisaUSA15.rda ├── docs ├── 404.html ├── CODE_OF_CONDUCT.html ├── CONDUCT.html ├── LICENSE-text.html ├── LICENSE.html ├── README-unnamed-chunk-3-1.png ├── README-unnamed-chunk-4-1.png ├── SUPPORT.html ├── articles │ ├── Introduction_to_tidyLPA.html │ ├── Introduction_to_tidyLPA_files │ │ ├── figure-html │ │ │ ├── unnamed-chunk-10-1.png │ │ │ ├── unnamed-chunk-10-2.png │ │ │ ├── unnamed-chunk-11-1.png │ │ │ ├── unnamed-chunk-11-2.png │ │ │ ├── unnamed-chunk-12-1.png │ │ │ ├── unnamed-chunk-12-2.png │ │ │ ├── unnamed-chunk-2-1.png │ │ │ ├── unnamed-chunk-3-1.png │ │ │ ├── unnamed-chunk-4-1.png │ │ │ ├── unnamed-chunk-5-1.png │ │ │ ├── unnamed-chunk-6-1.png │ │ │ ├── unnamed-chunk-7-1.png │ │ │ ├── unnamed-chunk-8-1.png │ │ │ ├── unnamed-chunk-8-2.png │ │ │ ├── unnamed-chunk-9-1.png │ │ │ └── unnamed-chunk-9-2.png │ │ └── header-attrs-2.6 │ │ │ └── header-attrs.js │ ├── benchmarking-mclust-and-mplus.html │ ├── benchmarking-mclust-and-mplus_files │ │ └── header-attrs-2.6 │ │ │ └── header-attrs.js │ ├── brief-overview.html │ ├── comparing-mclust-and-mplus-output.html │ ├── index.html │ ├── introduction-to-major-changes.html │ ├── introduction-to-major-changes_files │ │ └── figure-html │ │ │ └── unnamed-chunk-3-1.png │ ├── notes-on-model-selection.html │ └── rsconnect │ │ └── documents │ │ └── notes-on-model-selection.html ├── authors.html ├── bootstrap-toc.css ├── bootstrap-toc.js ├── docsearch.css ├── docsearch.js ├── index.html ├── jquery.sticky-kit.min.js ├── link.svg ├── man │ └── figures │ │ ├── README-unnamed-chunk-3-1.png │ │ ├── README-unnamed-chunk-4-1.png │ │ ├── README-unnamed-chunk-5-1.png │ │ └── README-unnamed-chunk-6-1.png ├── news │ └── index.html ├── notes.html ├── paper.html ├── pkgdown.css ├── pkgdown.js ├── pkgdown.yml ├── reference │ ├── AHP.html │ ├── Rplot001.png │ ├── Rplot002.png │ ├── as.tidyLPA.html │ ├── bootstrap_lrt-deprecated.html │ ├── bootstrap_lrt.html │ ├── calc_lrt.html │ ├── compare_solutions-1.png │ ├── compare_solutions-2.png │ ├── compare_solutions.html │ ├── compare_solutions_lpa-2.png │ ├── compare_solutions_lpa.html │ ├── compare_solutions_mplus-deprecated.html │ ├── compare_solutions_mplus.html │ ├── create_profiles_mplus.html │ ├── curry_mac.html │ ├── empathy.html │ ├── estimate_profiles.html │ ├── estimate_profiles_lpa.html │ ├── estimate_profiles_mclust.html │ ├── estimate_profiles_mplus-deprecated.html │ ├── estimate_profiles_mplus.html │ ├── estimate_profiles_mplus2.html │ ├── estimate_profiles_openmx.html │ ├── extract_LL_mplus.html │ ├── extract_mplus_summary.html │ ├── figures │ │ ├── README-unnamed-chunk-3-1.png │ │ ├── README-unnamed-chunk-4-1.png │ │ ├── README-unnamed-chunk-5-1.png │ │ ├── README-unnamed-chunk-6-1.png │ │ └── README-unnamed-chunk-7-1.png │ ├── get_data.html │ ├── get_estimates.html │ ├── get_fit.html │ ├── id_edu.html │ ├── index.html │ ├── mplusAvailable.html │ ├── pipe.html │ ├── pisaUSA15.html │ ├── plot_bivariate.html │ ├── plot_density.html │ ├── plot_profiles-1.png │ ├── plot_profiles-11.png │ ├── plot_profiles-14.png │ ├── plot_profiles-2.png │ ├── plot_profiles-7.png │ ├── plot_profiles.html │ ├── plot_profiles_lpa.html │ ├── plot_profiles_mplus-deprecated.html │ ├── plot_profiles_mplus.html │ ├── poms.html │ ├── print.tidyLPA.html │ ├── print.tidyProfile.html │ ├── reexports.html │ ├── single_imputation.html │ ├── tidyLPA-deprecated.html │ └── tidyLPA.html └── sitemap.xml ├── inst └── CITATION ├── man-roxygen └── template-plot-profiles.R ├── man ├── .Rapp.history ├── AHP.Rd ├── as.tidyLPA.Rd ├── calc_lrt.Rd ├── compare_solutions.Rd ├── curry_mac.Rd ├── empathy.Rd ├── estimate_profiles.Rd ├── estimate_profiles_mclust.Rd ├── estimate_profiles_mplus2.Rd ├── estimate_profiles_openmx.Rd ├── figures │ ├── README-unnamed-chunk-3-1.png │ ├── README-unnamed-chunk-4-1.png │ ├── README-unnamed-chunk-5-1.png │ ├── README-unnamed-chunk-6-1.png │ └── README-unnamed-chunk-7-1.png ├── get_data.Rd ├── get_estimates.Rd ├── get_fit.Rd ├── id_edu.Rd ├── pipe.Rd ├── pisaUSA15.Rd ├── poms.Rd ├── print.tidyLPA.Rd ├── print.tidyProfile.Rd ├── reexports.Rd ├── single_imputation.Rd └── tidyLPA.Rd ├── r-references.bib ├── tests ├── testthat.R └── testthat │ ├── test-compare-fit-stats.R │ ├── test-compare-solutions.R │ ├── test-estimate-profiles-mclust.R │ ├── test-local-estimate-profiles-mplus.R │ ├── test-local-estimate_profiles_mplus2-arguments.R │ ├── test-local-plot-profiles-mplus.R │ ├── test-pipe.R │ ├── test-plot-mixtures.R │ └── test-plot-profiles.R ├── tidyLPA.Rproj └── vignettes ├── .gitignore ├── Introduction_to_tidyLPA.Rmd └── benchmarking-mclust-and-mplus.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^ampps-paper\.tex$ 2 | ^ampps-paper\.pdf$ 3 | ^ampps-paper\.Rmd$ 4 | ^doc$ 5 | ^Meta$ 6 | ^man-roxygen$ 7 | ^.*\.Rproj$ 8 | ^\.Rproj\.user$ 9 | ^CONDUCT\.md$ 10 | ^README\.Rmd$ 11 | ^docs$ 12 | ^cran-comments\.md$ 13 | ^LICENSE\.md$ 14 | ^CODE_OF_CONDUCT\.md$ 15 | ^CONTRIBUTING\.md$ 16 | ^CRAN-RELEASE$ 17 | ^SUPPORT\.md$ 18 | .bib 19 | ^paper.md$ 20 | ^paper.Rmd$ 21 | ^paper.pdf$ 22 | ^paper.docx$ 23 | ^notes.md$ 24 | ^.*\.out$ 25 | ^.*\.inp$ 26 | ^.*\.dat$ 27 | ^.*\.log$ 28 | ^.*\.RData$ 29 | ^\.github$ 30 | ^CRAN-SUBMISSION$ 31 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: macos-latest, r: 'release'} 22 | - {os: windows-latest, r: 'release'} 23 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 24 | - {os: ubuntu-latest, r: 'release'} 25 | - {os: ubuntu-latest, r: 'oldrel-1'} 26 | 27 | env: 28 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 29 | R_KEEP_PKG_SOURCE: yes 30 | 31 | steps: 32 | - uses: actions/checkout@v4 33 | 34 | - uses: r-lib/actions/setup-pandoc@v2 35 | 36 | - uses: r-lib/actions/setup-r@v2 37 | with: 38 | r-version: ${{ matrix.config.r }} 39 | http-user-agent: ${{ matrix.config.http-user-agent }} 40 | use-public-rspm: true 41 | 42 | - uses: r-lib/actions/setup-r-dependencies@v2 43 | with: 44 | extra-packages: any::rcmdcheck 45 | needs: check 46 | 47 | - uses: r-lib/actions/check-r-package@v2 48 | with: 49 | upload-snapshots: true 50 | -------------------------------------------------------------------------------- /.github/workflows/check-standard.yaml: -------------------------------------------------------------------------------- 1 | # For help debugging build failures open an issue on the RStudio community with the 'github-actions' tag. 2 | # https://community.rstudio.com/new-topic?category=Package%20development&tags=github-actions 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | pull_request: 9 | branches: 10 | - main 11 | - master 12 | 13 | name: R-CMD-check 14 | 15 | jobs: 16 | R-CMD-check: 17 | runs-on: ${{ matrix.config.os }} 18 | 19 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 20 | 21 | strategy: 22 | fail-fast: false 23 | matrix: 24 | config: 25 | - {os: windows-latest, r: 'release'} 26 | - {os: macOS-latest, r: 'release'} 27 | - {os: ubuntu-20.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} 28 | - {os: ubuntu-20.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} 29 | 30 | env: 31 | R_REMOTES_NO_ERRORS_FROM_WARNINGS: true 32 | RSPM: ${{ matrix.config.rspm }} 33 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 34 | 35 | steps: 36 | - uses: actions/checkout@v2 37 | 38 | - uses: r-lib/actions/setup-r@v1 39 | with: 40 | r-version: ${{ matrix.config.r }} 41 | 42 | - uses: r-lib/actions/setup-pandoc@v1 43 | 44 | - name: Query dependencies 45 | run: | 46 | install.packages('remotes') 47 | saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2) 48 | writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") 49 | shell: Rscript {0} 50 | 51 | - name: Cache R packages 52 | if: runner.os != 'Windows' 53 | uses: actions/cache@v2 54 | with: 55 | path: ${{ env.R_LIBS_USER }} 56 | key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} 57 | restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- 58 | 59 | - name: Install system dependencies 60 | if: runner.os == 'Linux' 61 | run: | 62 | while read -r cmd 63 | do 64 | eval sudo $cmd 65 | done < <(Rscript -e 'writeLines(remotes::system_requirements("ubuntu", "20.04"))') 66 | 67 | - name: Install dependencies 68 | run: | 69 | remotes::install_deps(dependencies = TRUE) 70 | remotes::install_cran("rcmdcheck") 71 | shell: Rscript {0} 72 | 73 | - name: Check 74 | env: 75 | _R_CHECK_CRAN_INCOMING_REMOTE_: false 76 | run: rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran"), error_on = "warning", check_dir = "check") 77 | shell: Rscript {0} 78 | 79 | - name: Upload check results 80 | if: failure() 81 | uses: actions/upload-artifact@main 82 | with: 83 | name: ${{ runner.os }}-r${{ matrix.config.r }}-results 84 | path: check 85 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: test-coverage 10 | 11 | jobs: 12 | test-coverage: 13 | runs-on: ubuntu-latest 14 | env: 15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | 20 | - uses: r-lib/actions/setup-r@v2 21 | with: 22 | use-public-rspm: true 23 | 24 | - uses: r-lib/actions/setup-r-dependencies@v2 25 | with: 26 | extra-packages: any::covr 27 | needs: coverage 28 | 29 | - name: Test coverage 30 | run: | 31 | covr::codecov( 32 | quiet = FALSE, 33 | clean = FALSE, 34 | install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package") 35 | ) 36 | shell: Rscript {0} 37 | 38 | - name: Show testthat output 39 | if: always() 40 | run: | 41 | ## -------------------------------------------------------------------- 42 | find ${{ runner.temp }}/package -name 'testthat.Rout*' -exec cat '{}' \; || true 43 | shell: bash 44 | 45 | - name: Upload test results 46 | if: failure() 47 | uses: actions/upload-artifact@v4 48 | with: 49 | name: coverage-test-failures 50 | path: ${{ runner.temp }}/package 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | inst/doc 2 | r-references.bib 3 | ampps* 4 | Meta 5 | doc 6 | notes.md 7 | .Rproj.user 8 | .Rhistory 9 | .RData 10 | .Ruserdata 11 | iMplusThreadResults6.out 12 | binary/ 13 | *.out 14 | *.inp 15 | *.dat 16 | *.txt 17 | *.log 18 | analysis-for-paper.r 19 | ex-data.csv 20 | tests/test_local.R 21 | *.RData 22 | /doc/ 23 | /Meta/ 24 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who 4 | contribute through reporting issues, posting feature requests, updating documentation, 5 | submitting pull requests or patches, and other activities. 6 | 7 | We are committed to making participation in this project a harassment-free experience for 8 | everyone, regardless of level of experience, gender, gender identity and expression, 9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 10 | 11 | Examples of unacceptable behavior by participants include the use of sexual language or 12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment, 13 | insults, or other unprofessional conduct. 14 | 15 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed 18 | from the project team. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 21 | opening an issue or contacting one or more of the project maintainers. 22 | 23 | This Code of Conduct is adapted from the Contributor Covenant 24 | (http://contributor-covenant.org), version 1.0.0, available at 25 | http://contributor-covenant.org/version/1/0/0/ 26 | -------------------------------------------------------------------------------- /CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who 4 | contribute through reporting issues, posting feature requests, updating documentation, 5 | submitting pull requests or patches, and other activities. 6 | 7 | We are committed to making participation in this project a harassment-free experience for 8 | everyone, regardless of level of experience, gender, gender identity and expression, 9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 10 | 11 | Examples of unacceptable behavior by participants include the use of sexual language or 12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment, 13 | insults, or other unprofessional conduct. 14 | 15 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed 18 | from the project team. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 21 | opening an issue or contacting one or more of the project maintainers. 22 | 23 | This Code of Conduct is adapted from the Contributor Covenant 24 | (http://contributor-covenant.org), version 1.0.0, available at 25 | http://contributor-covenant.org/version/1/0/0/ 26 | -------------------------------------------------------------------------------- /CRAN-SUBMISSION: -------------------------------------------------------------------------------- 1 | Version: 2.0.1 2 | Date: 2023-04-10 13:14:32 UTC 3 | SHA: e62d7a92eb4877dead2159f4d40c778524f1a448 4 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Type: Package 2 | Package: tidyLPA 3 | Title: Easily Carry Out Latent Profile Analysis (LPA) Using 4 | Open-Source or Commercial Software 5 | Version: 2.0.1 6 | Authors@R: 7 | c(person(given = c("Joshua", "M"), 8 | family = "Rosenberg", 9 | role = c("aut", "cre"), 10 | email = "jmrosenberg@utk.edu"), 11 | person(given = "Caspar", 12 | family = "van Lissa", 13 | role = "aut", 14 | email = "c.j.vanlissa@uu.nl"), 15 | person(given = c("Jennifer", "A"), 16 | family = "Schmidt", 17 | role = "ctb", 18 | email = "jaschmid@msu.edu"), 19 | person(given = c("Patrick", "N"), 20 | family = "Beymer", 21 | role = "ctb", 22 | email = "beymerpa@msu.edu"), 23 | person(given = "Daniel", 24 | family = "Anderson", 25 | role = "ctb", 26 | email = "daniela@uoregon.edu"), 27 | person(given = c("Matthew", "J."), 28 | family = "Schell", 29 | role = "ctb", 30 | email = "schellma@msu.edu")) 31 | Maintainer: Joshua M Rosenberg 32 | Description: Easily carry out latent profile analysis ("LPA"), determine the 33 | correct number of classes based on best practices, and tabulate and plot the 34 | results. Provides functionality to estimate commonly-specified models with 35 | free means, variances, and covariances for each profile. Follows a tidy 36 | approach, in that output is in the form of a data frame that can 37 | subsequently be computed on. Models can be estimated using the free open 38 | source 'R' packages 'Mclust' and 'OpenMx', or using the commercial program 39 | 'MPlus', via the 'MplusAutomation' package. 40 | License: MIT + file LICENSE 41 | URL: https://data-edu.github.io/tidyLPA/ 42 | BugReports: https://github.com/data-edu/tidyLPA/issues 43 | Depends: 44 | R (>= 2.10), 45 | tidySEM (>= 0.2.0), 46 | OpenMx, 47 | lavaan 48 | Imports: 49 | dplyr, 50 | ggplot2, 51 | gtable, 52 | grid, 53 | mclust, 54 | methods, 55 | MplusAutomation, 56 | tibble 57 | Suggests: 58 | knitr, 59 | lme4, 60 | missForest, 61 | parallel, 62 | pillar, 63 | rmarkdown, 64 | testthat, 65 | mix 66 | VignetteBuilder: 67 | knitr 68 | Encoding: UTF-8 69 | LazyData: true 70 | RoxygenNote: 7.2.3 71 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2019 2 | COPYRIGHT HOLDER: Joshua M. Rosenberg, Caspar J. van Lissa, Patrick N. Beymer, Daniel Anderson, Jennifer A. Schmidt, and Matthew J. Schell 3 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(estimate_profiles,data.frame) 4 | S3method(estimate_profiles,default) 5 | S3method(estimate_profiles,matrix) 6 | S3method(estimate_profiles,numeric) 7 | S3method(get_data,tidyLPA) 8 | S3method(get_data,tidyProfile) 9 | S3method(get_estimates,tidyLPA) 10 | S3method(get_estimates,tidyProfile) 11 | S3method(get_fit,tidyLPA) 12 | S3method(get_fit,tidyProfile) 13 | S3method(plot,bestLPA) 14 | S3method(plot,tidyLPA) 15 | S3method(plot_bivariate,tidyLPA) 16 | S3method(plot_bivariate,tidyProfile) 17 | S3method(plot_density,tidyLPA) 18 | S3method(plot_density,tidyProfile) 19 | S3method(plot_profiles,tidyLPA) 20 | S3method(plot_profiles,tidyProfile) 21 | S3method(print,LRT) 22 | S3method(print,bestLPA) 23 | S3method(print,tidyLPA) 24 | S3method(print,tidyProfile) 25 | export("%>%") 26 | export(AHP) 27 | export(calc_lrt) 28 | export(compare_solutions) 29 | export(estimate_profiles) 30 | export(get_data) 31 | export(get_estimates) 32 | export(get_fit) 33 | export(plot_bivariate) 34 | export(plot_density) 35 | export(plot_profiles) 36 | export(poms) 37 | export(single_imputation) 38 | import(MplusAutomation) 39 | import(ggplot2) 40 | import(grid) 41 | import(gtable) 42 | import(mclust) 43 | import(tibble) 44 | importFrom(MplusAutomation,mplusAvailable) 45 | importFrom(OpenMx,mxAutoStart) 46 | importFrom(OpenMx,mxCompare) 47 | importFrom(OpenMx,mxData) 48 | importFrom(OpenMx,mxExpectationMixture) 49 | importFrom(OpenMx,mxFitFunctionML) 50 | importFrom(OpenMx,mxFitFunctionMultigroup) 51 | importFrom(OpenMx,mxMatrix) 52 | importFrom(OpenMx,mxModel) 53 | importFrom(OpenMx,mxPath) 54 | importFrom(OpenMx,mxRun) 55 | importFrom(OpenMx,mxTryHard) 56 | importFrom(OpenMx,omxAssignFirstParameters) 57 | importFrom(dplyr,"%>%") 58 | importFrom(lavaan,lavaanify) 59 | importFrom(lavaan,mplus2lavaan.modelSyntax) 60 | importFrom(methods,hasArg) 61 | importFrom(stats,complete.cases) 62 | importFrom(stats,cutree) 63 | importFrom(stats,density) 64 | importFrom(stats,dist) 65 | importFrom(stats,hclust) 66 | importFrom(stats,na.omit) 67 | importFrom(stats,pchisq) 68 | importFrom(stats,pnorm) 69 | importFrom(stats,qnorm) 70 | importFrom(stats,quantile) 71 | importFrom(stats,reshape) 72 | importFrom(stats,sd) 73 | importFrom(tidySEM,class_prob) 74 | importFrom(tidySEM,descriptives) 75 | importFrom(tidySEM,plot_bivariate) 76 | importFrom(tidySEM,plot_density) 77 | importFrom(tidySEM,plot_profiles) 78 | importFrom(tidySEM,table_results) 79 | importFrom(utils,capture.output) 80 | importFrom(utils,getFromNamespace) 81 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # tidyLPA 2.0.0 2 | 3 | * Add support for OpenMx 4 | 5 | # tidyLPA 1.1.0 6 | 7 | * Minor edits to introduction to tidyLPA vignette and README 8 | 9 | # tidyLPA 1.0.9 10 | 11 | * Fix issue where single column DF when using package = "MplusAutomation" would 12 | lead to duplicate NAMES = in Mplus syntax 13 | 14 | # tidyLPA 1.0.8 15 | * pass ... to mclust correctly 16 | * update for v 4.0 17 | 18 | # tidyLPA 1.0.7 19 | * Update package start-up message 20 | 21 | # tidyLPA 1.0.6 22 | * Correction citation to refer to JOSS paper 23 | 24 | # tidyLPA 1.0.5 25 | * Add C. J. van Lissa as author on JOSS paper 26 | * Fix bug re. passing additional parameters to mplusObject() 27 | * Add function to calculate Lo-Mendell-Rubin LR test 28 | * Add plot_bivariate function 29 | * Set default for plot_profiles(add_line = FALSE), because the line does not 30 | convey any meaningful information 31 | * Add curry_mac data 32 | * remove messages about depracated functions 33 | 34 | # tidyLPA 1.0.4 35 | * add data for paper 36 | * wrap mclust to handle errors better 37 | 38 | # tidyLPA 1.0.3 39 | 40 | * Fix bug when mclust model does not converge 41 | * improve `get_data()` so it returns data in long form 42 | * change message on load 43 | * change vignette titles 44 | * fix bug where `single_imputation` fails if there is no missing data 45 | * added details to `estimate_profiles()` on what models cannot be fit with mclust 46 | * added results of benchmarking as a new vignette 47 | * updated README with new updates 48 | 49 | # tidyLPA 1.0.1 50 | 51 | * Important bug fix for calculation of prob_min and prob_max for Mclust 52 | 53 | # tidyLPA 1.0.0 54 | 55 | * major, breaking changes detailed in the vignette [here](https://data-edu.github.io/tidyLPA/articles/introduction-to-major-changes.html) 56 | 57 | # tidyLPA 0.2.4 58 | 59 | * minor bug fixes 60 | * last update before transitioning to development version presently at https://github.com/cjvanlissa/tidyLPA 61 | * thank you to Qingyao Z. and @frigoli for correcting an error in the vignette and to others who submitted issues/identified bugs 62 | 63 | # tidyLPA 0.2.3 64 | 65 | * update to plot_profiles_mplus() 66 | * add option to specify latent vars 67 | * add message/vignette for major changes to come 68 | 69 | # tidyLPA 0.2.2 70 | 71 | * patch minor issue with model specification 72 | 73 | # tidyLPA 0.2.1 74 | 75 | * minor changes and bug fixes 76 | * addition of new reference to JOSS paper 77 | 78 | # tidyLPA 0.2.0 79 | 80 | ## Major breaking change: 81 | 82 | * change how models are specified; instead of using the model argument, whether and how the variances are covariances are estimated are passed the the variances and covariances argument; there are details in the readme and vignette and if a model argument is passed to a function, a message is returned describing how to specify the model using the variances and covariances arguments 83 | 84 | ## Major change 85 | 86 | * change the compare_solutions_mplus() functions Mplus to still allow for the specification of six models, but to use the same four as compare_solutions() (which uses the mclust package, not MPlus) by default 87 | 88 | ## Minor changes 89 | 90 | * improve NAMESPACE documentation 91 | * add option to return original data frame for functions that use MPlus 92 | * add option to use missing data for functions that use MPlus 93 | * add tidylpa@googlegroups.com mailing list address to README as preferred contact method 94 | * remove deprecated function (to extract key statistics from an MPlus model) 95 | * make it so that a data frame with fit and other statistics is returned by default from compare_solutions_mplus() 96 | * added new values to the statistics returned by compare_solutions_mplus(): 97 | - the cell size (the number of observations associated with each profile) 98 | - the number of times the log-likelihood was replicated, based on the number of optimization steps 99 | - Approximate Weight of Evidence (AWE) criterion 100 | - the number of parameters estimated 101 | * remove the messages about the software being in beta 102 | * how the Mplus syntax is generated was substantially changed/improved; thanks @gbiele 103 | 104 | ## Bug fixes 105 | 106 | * change include_LMR argument to include VLMR 107 | * remove scale_fill_brewer("", type = "qual", palette = "Set3") so that solutions with larger numbers of profiles may be plotted 108 | * fix issue where lines longer than 90 characters (i.e., when there are many variables) cause an error 109 | 110 | # tidyLPA 0.1.3 111 | 112 | * improve plot_profiles() plots, including plotting bootstrapped standard when mclust output is directly used (thanks @cjvanlissa) & updated vignette with example of this 113 | * improve output from compare_solutions_mplus (thanks @DJAnderson07) 114 | * add function, extract_LL_mplus(), to extract log-likelihoods from models fit witsah estimate_profiles_mplus() 115 | * update documentation for pisaUSA15 dataset 116 | * improve compare_solutions_mplus() so it more reliably handles errors 117 | * improve vignette (thanks @oreojo for suggestion to mention that this package works best for continuous variables) 118 | * add URLs for package and bug reports to DESCRIPTION 119 | * add C.J. van Lissa and Daniel John Anderson as contributors 120 | 121 | # tidyLPA 0.1.2 122 | 123 | Fix: 124 | 125 | * Specify version 0.7 of MplusAutomation in Imports to address error 126 | 127 | Minor updates: 128 | 129 | * Update README and Vignette 130 | * Update function names to include MPlus 131 | * Export %>% from magrittr (so it does not need to be loaded from dplyr) 132 | * Correct name of title for vignette 133 | * Update function names 134 | * Change output of estimate_profiles_mplus() to be returned with return(), instead of with invisible() 135 | 136 | # tidyLPA 0.1.1 137 | 138 | * Added a `NEWS.md` file to track changes to the package. 139 | -------------------------------------------------------------------------------- /R/as.tidyLPA.r: -------------------------------------------------------------------------------- 1 | #' @title Convert Mplus output to object of class 'tidyLPA' 2 | #' @description Takes a list of Mplus output files of class \code{modelList}, 3 | #' containing only mixture models with a single categorical latent variable, and 4 | #' converts it to an object of class \code{tidyLPA}. 5 | #' @param modelList A list of class \code{modelList}, as generated by 6 | #' \code{\link[MplusAutomation]{readModels}}. 7 | #' @return A list of class \code{tidyLPA}. 8 | #' @author Caspar J. van Lissa 9 | #' @examples 10 | #' \dontrun{ 11 | #' library(MplusAutomation) 12 | #' createMixtures(classes = 1:4, filename_stem = "cars", 13 | #' model_overall = "wt ON drat;", 14 | #' model_class_specific = "wt; qsec;", 15 | #' rdata = mtcars, 16 | #' usevariables = c("wt", "qsec", "drat"), 17 | #' OUTPUT = "standardized") 18 | #' runModels(replaceOutfile = "modifiedDate") 19 | #' cars_results <- readModels(filefilter = "cars") 20 | #' results_tidyLPA <- as.tidyLPA(cars_results) 21 | #' results_tidyLPA 22 | #' plot(results_tidyLPA) 23 | #' plot_profiles(results_tidyLPA) # Throws error; missing column 'Classes' 24 | #' } 25 | #' @rdname as.tidyLPA 26 | #' @keywords internal 27 | 28 | as.tidyLPA <- function(modelList) { 29 | # Check if mplusModel is of class mplus.model 30 | if (!(inherits(modelList, "mplus.model") | 31 | all(sapply(modelList, function(x) { 32 | inherits(x, "mplus.model") 33 | })))) { 34 | stop( 35 | "as.tidyLPA requires an object of class 'mplus.model' or a list of mplus.models as its first argument." 36 | ) 37 | } 38 | if (inherits(modelList, "mplus.model")) { 39 | modelList <- list(Model_1 = modelList) 40 | } 41 | # Check if mplusModel is a mixture model 42 | mixtures <- sapply(modelList, function(x) { 43 | !is.null(x$input$analysis[["type"]]) 44 | }) 45 | mixtures[which(mixtures)] <- 46 | sapply(modelList[which(mixtures)], function(x) { 47 | grepl("mixture", tolower(x$input$analysis$type)) 48 | }) 49 | if (!any(mixtures)) 50 | stop( 51 | "plot_profiles requires a list of mixture models, or one mixture model, as its first argument." 52 | ) 53 | if (any(!mixtures)) 54 | warning( 55 | "Some output files were excluded because they are not mixture models; specifically: ", 56 | paste(names(mixtures)[which(!mixtures)], collapse = ", "), 57 | call. = FALSE 58 | ) 59 | # Remove models which are not type "mixture" 60 | modelList <- modelList[which(mixtures)] 61 | # Check if all models were run on the same dataset 62 | if (length(unique(sapply(modelList, function(x) { 63 | x$input$data$file 64 | }))) > 1) { 65 | stop("Models were not all run on the same data file.") 66 | } 67 | # Check if any models have missing columns (result of nonconvergence) 68 | missing_cols <- 69 | sapply(modelList, function(x) { 70 | length(names(x$parameters[["unstandardized"]])) 71 | }) 72 | missing_cols <- which(missing_cols != max(missing_cols)) 73 | if (length(missing_cols) > 0) { 74 | warning( 75 | "Some models had missing columns in the coefficients section. This likely indicates a convergence problem. These models were dropped: ", 76 | paste(names(modelList)[missing_cols], collapse = ", "), 77 | call. = FALSE 78 | ) 79 | modelList <- modelList[-missing_cols] 80 | } 81 | # Prepare plot data 82 | # Get coefficients 83 | missing_coefficients <- 84 | which(sapply(modelList, function(x) { 85 | is.null(x$parameters[["unstandardized"]]) 86 | })) 87 | if (length(missing_coefficients > 0)) { 88 | warning( 89 | "Some models were missing the unstandardized coefficients. Please request these coefficients from Mplus.", 90 | call. = FALSE, 91 | immediate. = TRUE 92 | ) 93 | modelList <- modelList[-missing_coefficients] 94 | } 95 | if (length(modelList) < 1) 96 | stop("No models left to convert to tidyLPA.", call. = FALSE) 97 | 98 | # Try to figure out what kind of model it was 99 | # lapply(modelList, function(x){ 100 | # class_specific <- which(grepl("\\d%", x$input$model)) 101 | # }) 102 | 103 | model_numbers <- 104 | paste0("unknown_model_", as.numeric(factor(sapply(modelList, function(x) { 105 | end_first_class <- grep("#2%", x$input$model) 106 | end_first_class <- 107 | ifelse(length(end_first_class) == 0, 108 | length(x$input$model), 109 | end_first_class - 1) 110 | paste(x$input$model[1:end_first_class], collapse = "") 111 | })))) 112 | 113 | out_list <- lapply(modelList, function(x) { 114 | this_class <- nrow(x$class_counts$modelEstimated) 115 | this_model <- 99 116 | 117 | out <- list(model = x) 118 | out$fit <- 119 | c(Model = this_model, 120 | Classes = this_class, 121 | calc_fitindices(out$model)) 122 | out$estimates <- estimates(out$model) 123 | out$estimates$Model <- this_model 124 | out$estimates$Classes <- this_class 125 | 126 | #paste0("Model ", this_model, ", ", this_class, " classes") 127 | out$dff <- out$model$savedata 128 | out$dff$model_number <- this_model 129 | out$dff$classes_number <- this_class 130 | out$dff <- 131 | out$dff[, c((ncol(out$dff) - 1), ncol(out$dff), 1:(ncol(out$dff) - 2))] 132 | if(names(out$dff)[length(names(out$dff))] == "C"){ 133 | names(out$dff)[length(names(out$dff))] <- "Class" 134 | } 135 | #if(simplify) out$model <- NULL 136 | class(out) <- 137 | c("tidyProfile.mplus", "tidyProfile", "list") 138 | out 139 | }) 140 | 141 | class(out_list) <- c("tidyLPA", "list") 142 | names(out_list) <- 143 | paste("model_", 144 | model_numbers, 145 | "_class_", 146 | sapply(out_list, function(x) { 147 | x$fit["Classes"] 148 | }), 149 | sep = "") 150 | out_list 151 | } 152 | -------------------------------------------------------------------------------- /R/compare-solutions.R: -------------------------------------------------------------------------------- 1 | #' Compare latent profile models 2 | #' 3 | #' Takes an object of class 'tidyLPA', containing multiple latent profile models 4 | #' with different number of classes or model specifications, and helps select 5 | #' the optimal number of classes and model specification. 6 | #' @param x An object of class 'tidyLPA'. 7 | #' @param statistics Character vector. Which statistics to examine for 8 | #' determining the optimal model. Defaults to 'BIC'. 9 | #' @return An object of class 'bestLPA' and 'list', containing a tibble of fits 10 | #' 'fits', a named vector 'best', indicating which model fit best according to 11 | #' each fit index, a numeric vector 'AHP' indicating the best model according to 12 | #' the \code{\link{AHP}}, an object 'plot' of class 'ggplot', and a numeric 13 | #' vector 'statistics' corresponding to argument of the same name. 14 | #' @author Caspar J. van Lissa 15 | #' @examples 16 | #' iris_subset <- sample(nrow(iris), 20) # so examples execute quickly 17 | #' results <- iris %>% 18 | #' subset(select = c("Sepal.Length", "Sepal.Width", 19 | #' "Petal.Length", "Petal.Width")) %>% 20 | #' estimate_profiles(1:3) %>% 21 | #' compare_solutions() 22 | #' @export 23 | compare_solutions <- function(x, statistics = "BIC") { 24 | deprecated_arguments(c( 25 | "n_profiles_range" = "compare_solutions no longer conducts the analysis; it merely compares the results of an analysis conducted using 'estimate_profiles' (run: ?estimate_profiles for documentation).", 26 | "return_table" = "compare_solutions returns both a table ($fits) and a plot ($plot).", 27 | "models" = "compare_solutions no longer conducts the analysis; it merely compares the results of an analysis conducted using 'estimate_profiles' (run: ?estimate_profiles for documentation).", 28 | "model" = "compare_solutions no longer conducts the analysis; it merely compares the results of an analysis conducted using 'estimate_profiles' (run: ?estimate_profiles for documentation).", 29 | "toreturn" = "compare_solutions no longer conducts the analysis; it merely compares the results of an analysis conducted using 'estimate_profiles' (run: ?estimate_profiles for documentation).", 30 | "return_posterior_probs" = "compare_solutions no longer conducts the analysis; it merely compares the results of an analysis conducted using 'estimate_profiles' (run: ?estimate_profiles for documentation).", 31 | "return_original_df" = "compare_solutions no longer conducts the analysis; it merely compares the results of an analysis conducted using 'estimate_profiles' (run: ?estimate_profiles for documentation).", 32 | "prior_control" = "compare_solutions no longer conducts the analysis; it merely compares the results of an analysis conducted using 'estimate_profiles' (run: ?estimate_profiles for documentation).", 33 | "print_which_stats" = "compare_solutions no longer conducts the analysis; it merely compares the results of an analysis conducted using 'estimate_profiles' (run: ?estimate_profiles for documentation).", 34 | "center_raw_data" = "compare_solutions no longer conducts the analysis; it merely compares the results of an analysis conducted using 'estimate_profiles' (run: ?estimate_profiles for documentation).", 35 | "scale_raw_data" = "compare_solutions no longer conducts the analysis; it merely compares the results of an analysis conducted using 'estimate_profiles' (run: ?estimate_profiles for documentation)." 36 | )) 37 | 38 | fits <- get_fit(x) 39 | error_models <- is.na(fits$LogLik) 40 | if(sum(!error_models) < 2) stop("In order to compare_solutions, the tidyLPA object must contain more than one model.") 41 | fit_indices <- c("LogLik" = 1, "AIC" = -1, "AWE" = -1, "BIC" = -1, "CAIC" = -1, "CLC" = -1, "KIC" = -1, "SABIC" = -1, "ICL" = 1) 42 | max_these <- matrix(rep(fit_indices, nrow(fits)), nrow = nrow(fits), byrow = TRUE) 43 | best_model <- apply(max_these * fits[, names(fit_indices)], 2, which.max) 44 | 45 | AHP_best <- c(1:nrow(fits))[!error_models][AHP(fits[!error_models, ])] 46 | 47 | # Check fits for problems ------------------------------------------------- 48 | 49 | warnings <- sapply(x, function(x){!is.null(x[["warnings"]])}) 50 | if(any(warnings)){ 51 | fits$Warnings <- ifelse(warnings, "Warning", NA) 52 | warning("\nOne or more analyses resulted in warnings! Examine these analyses carefully: ", 53 | paste(names(x)[which(warnings)], collapse = ", "), 54 | call. = FALSE) 55 | } 56 | 57 | best_model <- apply(max_these * fits[, names(fit_indices)], 2, which.max) 58 | 59 | # Check for problems with comparing solutions ----------------------------- 60 | 61 | if(length(unique(fits$Classes)) > 1){ 62 | if(any(best_model == min(fits$Classes))){ 63 | warning("The solution with the minimum number of classes under consideration was considered to be the best solution according to one or more fit indices. Examine your results with care", ifelse(min(fits$Classes == 1), "; mixture modeling might be unnecessary.", "; consider adding a smaller number of classes."), call. = FALSE) 64 | } 65 | if(any(best_model == max(fits$Classes))){ 66 | warning("The solution with the maximum number of classes under consideration was considered to be the best solution according to one or more fit indices. Examine your results with care and consider estimating more classes.", call. = FALSE) 67 | } 68 | } 69 | 70 | out <- list(fits = fits, best = best_model, AHP = AHP_best, statistics = statistics) 71 | class(out) <- c("bestLPA", class(out)) 72 | out 73 | } 74 | 75 | #' @method print bestLPA 76 | #' @export 77 | print.bestLPA <- function(x, digits = 3, na.print = "", ...){ 78 | cat("Compare tidyLPA solutions:\n\n") 79 | stats <- x$statistics 80 | if("Warnings" %in% names(x$fits)){ 81 | fit_cols <- c("Model", "Classes", stats, "Warnings") 82 | } else { 83 | fit_cols <- c("Model", "Classes", stats) 84 | } 85 | dat <- as.matrix(x$fits[, fit_cols]) 86 | miss_val <- is.na(dat) 87 | dat[,3:ncol(dat)] <- sapply(dat[,3:ncol(dat)], formatC, digits = digits, format = "f") 88 | dat[miss_val] <- "" 89 | #rownames(dat) <- "" 90 | prmatrix(dat, rowlab = rep("", nrow(dat)), quote = FALSE, na.print = na.print) 91 | 92 | for(ft in x$statistics){ 93 | #ft <- x$statistics[1] 94 | cat("\nBest model according to", ft, "is Model", dat[, "Model"][x$best[ft]], "with", dat[, "Classes"][x$best[ft]], "classes.") 95 | } 96 | cat("\n\nAn analytic hierarchy process, based on the fit indices AIC, AWE, BIC, CLC, and KIC (Akogul & Erisoglu, 2017), suggests the best solution is Model", dat[, "Model"][x$AHP], "with", dat[, "Classes"][x$AHP], "classes.\n") 97 | } 98 | 99 | -------------------------------------------------------------------------------- /R/data-documentation.R: -------------------------------------------------------------------------------- 1 | # data documentation 2 | 3 | #' student questionnaire data with four variables from the 2015 PISA for students in the United States 4 | #' 5 | #' @source http://www.oecd.org/pisa/data/ 6 | #' @format Data frame with columns 7 | #' #' \describe{ 8 | #' \item{broad_interest}{composite measure of students' self reported broad interest} 9 | #' \item{enjoyment}{composite measure of students' self reported enjoyment} 10 | #' \item{instrumental_mot}{composite measure of students' self reported instrumental motivation} 11 | #' \item{self_efficacy}{composite measure of students' self reported self efficacy} 12 | #' ... 13 | #' } 14 | #' @import tibble 15 | 16 | "pisaUSA15" 17 | -------------------------------------------------------------------------------- /R/data-mac.R: -------------------------------------------------------------------------------- 1 | #' Simulated MAC data 2 | #' 3 | #' This simulated dataset, based on Curry et al., 2019, contains data on moral 4 | #' relevance and judgment across the seven domains of the Morality As 5 | #' Cooperation scale. 6 | #' 7 | #' \tabular{lll}{ 8 | #' \strong{sex} \tab \code{factor} \tab Self-identified sex of participants, Male, Female, or Transgendered.\cr 9 | #' \strong{age_years} \tab \code{numeric} \tab Participants' age in years.\cr 10 | #' \strong{KinshipR} \tab \code{numeric} \tab Mean score of moral relevance, kinship subscale.\cr 11 | #' \strong{MutualismR} \tab \code{numeric} \tab Mean score of moral relevance, mutualism subscale.\cr 12 | #' \strong{ExchangeR} \tab \code{numeric} \tab Mean score of moral relevance, exchange subscale.\cr 13 | #' \strong{HawkR} \tab \code{numeric} \tab Mean score of moral relevance, hawk subscale.\cr 14 | #' \strong{DoveR} \tab \code{numeric} \tab Mean score of moral relevance, dove subscale.\cr 15 | #' \strong{DivisionR} \tab \code{numeric} \tab Mean score of moral relevance, division subscale.\cr 16 | #' \strong{PossessionR} \tab \code{numeric} \tab Mean score of moral relevance, possession subscale.\cr 17 | #' \strong{KinshipJ} \tab \code{numeric} \tab Mean score of moral judgment, kinship subscale.\cr 18 | #' \strong{MutualismJ} \tab \code{numeric} \tab Mean score of moral judgment, mutualism subscale.\cr 19 | #' \strong{ExchangeJ} \tab \code{numeric} \tab Mean score of moral judgment, exchange subscale.\cr 20 | #' \strong{HawkJ} \tab \code{numeric} \tab Mean score of moral judgment, hawk subscale.\cr 21 | #' \strong{DoveJ} \tab \code{numeric} \tab Mean score of moral judgment, dove subscale.\cr 22 | #' \strong{DivisionJ} \tab \code{numeric} \tab Mean score of moral judgment, division subscale.\cr 23 | #' \strong{PossessionJ} \tab \code{numeric} \tab Mean score of moral judgment, possession subscale. 24 | #' } 25 | #' @docType data 26 | #' @keywords datasets 27 | #' @name curry_mac 28 | #' @usage data(curry_mac) 29 | #' @references Curry, O. S., Jones Chesters, M., & Van Lissa, C. J. (2019). Mapping morality with a compass: Testing the theory of ‘morality-as-cooperation’ with a new questionnaire. Journal of Research in Personality, 78, 106–124. 30 | #' \doi{10.1016/j.jrp.2018.10.008} 31 | #' @format A data.frame with 1392 rows and 42 variables. 32 | NULL 33 | -------------------------------------------------------------------------------- /R/empathy.R: -------------------------------------------------------------------------------- 1 | #' Simulated empathy data 2 | #' 3 | #' This simulated dataset, based on Van Lissa et al., 2014, contains six annual 4 | #' assessments of adolescents' mean scores on the empathic concern and 5 | #' perspective taking subscales of the Interpersonal Reactivity Index 6 | #' (Davis, 1983). The first measurement wave occurred when adolescents were, on 7 | #' average, 13 years old, and the last one when they were 18 years old. 8 | #' 9 | #' \tabular{lll}{ 10 | #' \strong{ec1} \tab \code{numeric} \tab Mean score of empathic concern in 11 | #' wave 1\cr 12 | #' \strong{ec2} \tab \code{numeric} \tab Mean score of empathic concern in 13 | #' wave 2\cr 14 | #' \strong{ec3} \tab \code{numeric} \tab Mean score of empathic concern in 15 | #' wave 3\cr 16 | #' \strong{ec4} \tab \code{numeric} \tab Mean score of empathic concern in 17 | #' wave 4\cr 18 | #' \strong{ec5} \tab \code{numeric} \tab Mean score of empathic concern in 19 | #' wave 5\cr 20 | #' \strong{ec6} \tab \code{numeric} \tab Mean score of empathic concern in 21 | #' wave 6\cr 22 | #' \strong{pt1} \tab \code{numeric} \tab Mean score of perspective taking in 23 | #' wave 1\cr 24 | #' \strong{pt2} \tab \code{numeric} \tab Mean score of perspective taking in 25 | #' wave 2\cr 26 | #' \strong{pt3} \tab \code{numeric} \tab Mean score of perspective taking in 27 | #' wave 3\cr 28 | #' \strong{pt4} \tab \code{numeric} \tab Mean score of perspective taking in 29 | #' wave 4\cr 30 | #' \strong{pt5} \tab \code{numeric} \tab Mean score of perspective taking in 31 | #' wave 5\cr 32 | #' \strong{pt6} \tab \code{numeric} \tab Mean score of perspective taking in 33 | #' wave 6\cr 34 | #' \strong{sex} \tab \code{factor} \tab Adolescent sex; M = male, F = female. 35 | #' } 36 | #' @docType data 37 | #' @keywords datasets 38 | #' @name empathy 39 | #' @usage data(empathy) 40 | #' @references Van Lissa, C. J., Hawk, S. T., Branje, S. J., Koot, H. M., 41 | #' Van Lier, P. A., & Meeus, W. H. (2014). Divergence Between Adolescent and 42 | #' Parental Perceptions of Conflict in Relationship to Adolescent Empathy 43 | #' Development. Journal of Youth and Adolescence, (Journal Article), 1–14. 44 | #' \doi{10.1007/s10964-014-0152-5} 45 | #' @format A data frame with 467 rows and 13 variables. 46 | NULL 47 | -------------------------------------------------------------------------------- /R/helpers.R: -------------------------------------------------------------------------------- 1 | #' @importFrom MplusAutomation mplusAvailable 2 | .onAttach <- function(libname, pkgname) { 3 | has_mplus <- mplusAvailable(TRUE) 4 | print_message <- paste0("You can use the function citation('tidyLPA') to create a citation for the use of {tidyLPA}.\n", 5 | ifelse(has_mplus == 0, "Mplus is installed; you can use package = 'MplusAutomation' when calling estimate_profiles().", 6 | "Mplus is not installed. Use only package = 'mclust' when calling estimate_profiles().") 7 | ) 8 | packageStartupMessage(print_message) 9 | } 10 | 11 | #' Pipe 12 | #' 13 | #' tidyLPA suggests using the pipe operator, \code{\%>\%}, from the magrittr 14 | #' package (imported here from the dplyr package). 15 | #' 16 | #' @importFrom dplyr %>% 17 | #' @name %>% 18 | #' @rdname pipe 19 | #' @export 20 | #' @param lhs,rhs An object and a function to apply to it 21 | #' @examples 22 | #' # Instead of 23 | #' subset(iris, select = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")) 24 | #' # you can write 25 | #' iris %>% 26 | #' subset(select = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")) 27 | NULL 28 | 29 | 30 | quiet <- function(x) { 31 | sink(tempfile()) 32 | on.exit(sink()) 33 | invisible(force(x)) 34 | } 35 | -------------------------------------------------------------------------------- /R/id_edu.R: -------------------------------------------------------------------------------- 1 | #' Simulated identity data 2 | #' 3 | #' This simulated dataset, based on Crochetti et al., 2014, contains five annual 4 | #' assessments of adolescents' mean scores on the commitment, exploration (in 5 | #' depth), and reconsideration subscales of the Utrecht-Management of Identity 6 | #' Commitments Scale (Crocetti et al., 2008). The scores reported here reflect 7 | #' the educational identity subscales of this instrument. The first measurement 8 | #' wave occurred when adolescents were, on 9 | #' average, 14 years old, and the last one when they were 18 years old. 10 | #' 11 | #' \tabular{lll}{ 12 | #' \strong{com1} \tab \code{numeric} \tab Mean score 13 | #' of educational commitment in 14 | #' wave 1\cr 15 | #' \strong{exp1} \tab \code{numeric} \tab Mean score 16 | #' of educational exploration in 17 | #' wave 1\cr 18 | #' \strong{rec1} \tab \code{numeric} \tab Mean score 19 | #' of educational reconsideration in 20 | #' wave 1\cr 21 | #' \strong{com2} \tab \code{numeric} \tab Mean score 22 | #' of educational commitment in 23 | #' wave 2\cr 24 | #' \strong{exp2} \tab \code{numeric} \tab Mean score 25 | #' of educational exploration in 26 | #' wave 2\cr 27 | #' \strong{rec2} \tab \code{numeric} \tab Mean score 28 | #' of educational reconsideration in 29 | #' wave 2\cr 30 | #' \strong{com3} \tab \code{numeric} \tab Mean score 31 | #' of educational commitment in 32 | #' wave 3\cr 33 | #' \strong{exp3} \tab \code{numeric} \tab Mean score 34 | #' of educational exploration in 35 | #' wave 3\cr 36 | #' \strong{rec3} \tab \code{numeric} \tab Mean score 37 | #' of educational reconsideration in 38 | #' wave 3\cr 39 | #' \strong{com4} \tab \code{numeric} \tab Mean score 40 | #' of educational commitment in 41 | #' wave 4\cr 42 | #' \strong{exp4} \tab \code{numeric} \tab Mean score 43 | #' of educational exploration in 44 | #' wave 4\cr 45 | #' \strong{rec4} \tab \code{numeric} \tab Mean score 46 | #' of educational reconsideration in 47 | #' wave 4\cr 48 | #' \strong{com5} \tab \code{numeric} \tab Mean score 49 | #' of educational commitment in 50 | #' wave 5\cr 51 | #' \strong{exp5} \tab \code{numeric} \tab Mean score 52 | #' of educational exploration in 53 | #' wave 5\cr 54 | #' \strong{rec5} \tab \code{numeric} \tab Mean score 55 | #' of educational reconsideration in 56 | #' wave 5\cr 57 | #' \strong{sex} \tab \code{factor} \tab Adolescent sex; M = male, F = female. 58 | #' } 59 | #' @docType data 60 | #' @keywords datasets 61 | #' @name id_edu 62 | #' @usage data(id_edu) 63 | #' @references Crocetti, E., Klimstra, T. A., Hale, W. W., Koot, H. M., & 64 | #' Meeus, W. (2013). Impact of early adolescent externalizing problem behaviors 65 | #' on identity development in middle to late adolescence: A prospective 7-year 66 | #' longitudinal study. Journal of Youth and Adolescence, 42(11), 1745-1758. 67 | #' \doi{10.1007/s10964-013-9924-6} 68 | #' @format A data frame with 443 rows and 16 variables. 69 | NULL 70 | -------------------------------------------------------------------------------- /R/missing_data.R: -------------------------------------------------------------------------------- 1 | #' @title Apply single imputation to data 2 | #' @description This function accommodates several methods for single imputation 3 | #' of data. Currently, the following methods are defined: 4 | #' \itemize{ 5 | #' \item{"imputeData"}{Applies the mclust native imputation function 6 | #' \code{\link[mclust]{imputeData}}} 7 | #' \item{"missForest"}{Applies non-parameteric, random-forest based data 8 | #' imputation using \code{\link[missForest]{missForest}}. Radom forests can 9 | #' accommodate any complex interactions and non-linear relations in the data. My 10 | #' simulation studies indicate that this method is preferable to mclust's 11 | #' \code{imputeData} (see examples).} 12 | #' } 13 | #' @param x A data.frame or matrix. 14 | #' @param method Character. Imputation method to apply, Default: 'imputeData' 15 | #' @return A data.frame 16 | #' @author Caspar J. van Lissa 17 | #' @examples 18 | #' \dontrun{ 19 | #' library(ggplot2) 20 | #' library(missForest) 21 | #' library(mclust) 22 | #' 23 | #' dm <- 2 24 | #' k <- 3 25 | #' n <- 100 26 | #' V <- 4 27 | #' 28 | #' # Example of one simulation 29 | #' class <- sample.int(k, n, replace = TRUE) 30 | #' dat <- matrix(rnorm(n*V, mean = (rep(class, each = V)-1)*dm), nrow = n, 31 | #' ncol = V, byrow = TRUE) 32 | #' results <- estimate_profiles(data.frame(dat), 1:5) 33 | #' plot_profiles(results) 34 | #' compare_solutions(results) 35 | #' 36 | #' # Simulation for parametric data (i.e., all assumptions of latent profile 37 | #' # analysis met) 38 | #' simulation <- replicate(100, { 39 | #' class <- sample.int(k, n, replace = TRUE) 40 | #' dat <- matrix(rnorm(n*V, mean = (rep(class, each = V)-1)*dm), nrow = n, 41 | #' ncol = V, byrow = TRUE) 42 | #' 43 | #' d <- prodNA(dat) 44 | #' 45 | #' d_mf <- missForest(d)$ximp 46 | #' m_mf <- Mclust(d_mf, G = 3, "EEI") 47 | #' d_im <- imputeData(d, verbose = FALSE) 48 | #' m_im <- Mclust(d_im, G = 3, "EEI") 49 | #' 50 | #' class_tabl_mf <- sort(prop.table(table(class, m_mf$classification)), 51 | #' decreasing = TRUE)[1:3] 52 | #' class_tabl_im <- sort(prop.table(table(class, m_im$classification)), 53 | #' decreasing = TRUE)[1:3] 54 | #' c(sum(class_tabl_mf), sum(class_tabl_im)) 55 | #' }) 56 | #' # Performance on average 57 | #' rowMeans(simulation) 58 | #' # Performance SD 59 | #' colSD(t(simulation)) 60 | #' # Plot shows slight advantage for missForest 61 | #' plotdat <- data.frame(accuracy = as.vector(simulation), model = 62 | #' rep(c("mf", "im"), n)) 63 | #' ggplot(plotdat, aes(x = accuracy, colour = model))+geom_density() 64 | #' 65 | #' # Simulation for real data (i.e., unknown whether assumptions are met) 66 | #' simulation <- replicate(100, { 67 | #' d <- prodNA(iris[,1:4]) 68 | #' 69 | #' d_mf <- missForest(d)$ximp 70 | #' m_mf <- Mclust(d_mf, G = 3, "EEI") 71 | #' d_im <- imputeData(d, verbose = FALSE) 72 | #' m_im <- Mclust(d_im, G = 3, "EEI") 73 | #' 74 | #' class_tabl_mf <- sort(prop.table(table(iris$Species, 75 | #' m_mf$classification)), decreasing = TRUE)[1:3] 76 | #' class_tabl_im <- sort(prop.table(table(iris$Species, 77 | #' m_im$classification)), decreasing = TRUE)[1:3] 78 | #' c(sum(class_tabl_mf), sum(class_tabl_im)) 79 | #' }) 80 | #' 81 | #' # Performance on average 82 | #' rowMeans(simulation) 83 | #' # Performance SD 84 | #' colSD(t(simulation)) 85 | #' # Plot shows slight advantage for missForest 86 | #' plotdat <- data.frame(accuracy = as.vector(tmp), 87 | #' model = rep(c("mf", "im"), n)) 88 | #' ggplot(plotdat, aes(x = accuracy, colour = model))+geom_density() 89 | #' } 90 | #' @rdname single_imputation 91 | #' @export 92 | single_imputation <- function(x, method = "imputeData"){ 93 | if(all(complete.cases(x))) return(x) 94 | if(FALSE) missForest(x) 95 | imputed <- invisible(switch(method, 96 | "imputeData" = do.call(imputeData, list(data = x, verbose = FALSE)), 97 | "missForest" = do.call(missForest::missForest, list(xmis = as.matrix(x)))$ximp, 98 | NULL)) 99 | if(is.null(imputed)){ 100 | stop("No method is currently defined for single imputation of data using '", method, "'.") 101 | } 102 | data.frame(imputed) 103 | } 104 | -------------------------------------------------------------------------------- /R/openmx.R: -------------------------------------------------------------------------------- 1 | #' @importFrom utils getFromNamespace 2 | vnames <- getFromNamespace("vnames", "lavaan") 3 | 4 | #' @importFrom lavaan lavaanify 5 | #' @importFrom OpenMx mxModel 6 | as_ram <- function(model, 7 | int.ov.free = TRUE, int.lv.free = FALSE, auto.fix.first = FALSE, 8 | auto.fix.single = TRUE, auto.var = TRUE, auto.cov.lv.x = TRUE, 9 | auto.efa = TRUE, auto.th = TRUE, auto.delta = TRUE, auto.cov.y = TRUE, ...){ 10 | defaults <- list(int.ov.free = TRUE, int.lv.free = FALSE, auto.fix.first = FALSE, 11 | auto.fix.single = TRUE, auto.var = TRUE, auto.cov.lv.x = TRUE, 12 | auto.efa = TRUE, auto.th = TRUE, auto.delta = TRUE, auto.cov.y = TRUE) 13 | cl <- match.call() 14 | cl[names(defaults)[!names(defaults) %in% names(cl)]] <- defaults[!names(defaults) %in% names(cl)] 15 | cl[[1L]] <- str2lang("lavaan::lavaanify") 16 | lavtab <- eval.parent(cl) 17 | # Remove defined parameters 18 | lavtab <- lavtab[!(lavtab$group == 0), ] 19 | # Starting values 20 | #lavtab$ustart[lavtab$op == "~1"] <- 0 21 | #lavtab$ustart[lavtab$op == "~~"] <- .5 22 | # Identify observed and latent 23 | vnames <- vnames(partable = lavtab, type = "all") 24 | latent <- unlist(vnames[["lv"]]) 25 | obs <- unlist(vnames[["ov"]]) 26 | # Intercept needs rhs 27 | lavtab$rhs[lavtab$op == "~1"] <- "one" 28 | lavtab$op[lavtab$op == "~1"] <- "~" 29 | # Convert lavtab to paths 30 | path_list <- lapply(1:nrow(lavtab), function(i){ 31 | path <- lavtab[i, ] 32 | Args <- list( 33 | name = "mxPath", 34 | from = switch(path[["op"]], 35 | "=~" = path[["lhs"]], 36 | path[["rhs"]]), 37 | to = switch(path[["op"]], 38 | "=~" = path[["rhs"]], 39 | path[["lhs"]]), 40 | connect = "single", 41 | arrows = switch(path[["op"]], 42 | `~~` = 2, 43 | 1), 44 | free = !(path[["free"]] == 0), 45 | values = path[["ustart"]] 46 | ) 47 | if(!path[["label"]] == "") Args$labels <- path[["label"]] 48 | do.call(call, Args) 49 | }) 50 | do.call(mxModel, c(list(model = "model", 51 | type='RAM', 52 | manifestVars = obs, 53 | latentVars = latent), 54 | path_list)) 55 | } 56 | -------------------------------------------------------------------------------- /R/plot.tidyLPA.R: -------------------------------------------------------------------------------- 1 | #' @method plot tidyLPA 2 | #' @export 3 | plot.tidyLPA <- function(x, 4 | y, 5 | ..., 6 | statistics = NULL) { 7 | if(is.null(statistics)) statistics <- "BIC" 8 | p <- plot_tidyLPA(data.frame(t(sapply(x, `[[`, "fit"))), statistics) 9 | suppressMessages(suppressWarnings(print(p))) 10 | invisible(p) 11 | } 12 | 13 | 14 | #' @method plot bestLPA 15 | #' @export 16 | plot.bestLPA <- function(x, 17 | y, 18 | ...) { 19 | p <- plot_tidyLPA(data.frame(x$fits), x$statistics) 20 | suppressMessages(suppressWarnings(print(p))) 21 | invisible(p) 22 | } 23 | 24 | 25 | 26 | plot_tidyLPA <- function(x, 27 | statistics = NULL) { 28 | plotdat <- x 29 | if(is.null(statistics)) statistics <- "BIC" 30 | lowerbetter <- c( 31 | "LogLik" = " (lower is better)", 32 | "AIC" = " (lower is better)", 33 | "AWE" = " (lower is better)", 34 | "BIC" = " (lower is better)", 35 | "CAIC" = " (lower is better)", 36 | "CLC" = " (lower is better)", 37 | "KIC" = " (lower is better)", 38 | "SABIC" = " (lower is better" 39 | ) 40 | higherbetter <- c("ICL" = " (higher is better)", 41 | "Entropy" = " (higher is better") 42 | neutral <- c("prob_min", "prob_max", "n_min", "n_max") 43 | 44 | if (any(!statistics %in% c(names(lowerbetter), names(higherbetter), names(neutral)))) { 45 | stop("Can not plot the following statistics: ", 46 | paste(statistics, collapse = ", "), 47 | ".") 48 | } 49 | 50 | plotdat$Model <- ordered(paste("Model ", plotdat$Model)) 51 | plotdat$Classes <- ordered(plotdat$Classes, levels = sort(unique(plotdat$Classes))) 52 | 53 | if (length(statistics) > 1) { 54 | plotdat <- 55 | reshape( 56 | plotdat[, c("Model", "Classes", statistics)], 57 | varying = list(Value = statistics), 58 | timevar = "Statistic", 59 | v.names = "Value", 60 | direction = "long" 61 | ) 62 | plotdat$Statistic <- 63 | factor(plotdat$Statistic, labels = paste0(statistics, c(lowerbetter, higherbetter)[match(statistics, names(c(lowerbetter, higherbetter)))])) 64 | p <- ggplot( 65 | plotdat, 66 | aes_string( 67 | x = "Classes", 68 | y = "Value", 69 | color = "Model", 70 | group = "Model" 71 | ) 72 | ) + 73 | geom_line(na.rm = TRUE) + 74 | geom_point(na.rm = TRUE) + 75 | theme_bw() + 76 | scale_color_discrete("")+ 77 | facet_wrap(~ Statistic) 78 | 79 | } else { 80 | p <- ggplot( 81 | plotdat, 82 | aes_string( 83 | x = "Classes", 84 | y = statistics, 85 | color = "`Model`", 86 | group = "`Model`" 87 | ) 88 | ) + 89 | geom_line(na.rm = TRUE) + 90 | geom_point(na.rm = TRUE) + 91 | ylab(paste0(statistics, c(lowerbetter, higherbetter)[match(statistics, names(c(lowerbetter, higherbetter)))])) + 92 | theme_bw() + 93 | scale_color_discrete("") 94 | } 95 | return(p) 96 | } 97 | -------------------------------------------------------------------------------- /R/tidylpa.r: -------------------------------------------------------------------------------- 1 | #' tidyLPA: Functionality to carry out Latent Profile Analysis in R 2 | #' 3 | #' Latent Profile Analysis (LPA) is a statistical modeling approach for 4 | #' estimating distinct profiles, or groups, of variables. In the social 5 | #' sciences and in educational research, these profiles could represent, for 6 | #' example, how different youth experience dimensions of being engaged (i.e., 7 | #' cognitively, behaviorally, and affectively) at the same time. 8 | #' 9 | #' tidyLPA provides the functionality to carry out LPA in R. In particular, 10 | #' tidyLPA provides functionality to specify different models that determine 11 | #' whether and how different parameters (i.e., means, variances, and 12 | #' covariances) are estimated and to specify (and compare solutions for) the 13 | #' number of profiles to estimate. 14 | #' 15 | #' @docType package 16 | #' @name tidyLPA 17 | #' @import ggplot2 18 | #' @import mclust 19 | #' @import tibble 20 | #' @importFrom dplyr "%>%" 21 | #' @importFrom stats complete.cases sd reshape quantile qnorm pnorm 22 | NULL 23 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r, echo = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/README-" 12 | ) 13 | ``` 14 | 15 | [![CRAN status](https://www.r-pkg.org/badges/version/tidyLPA)](https://cran.r-project.org/package=tidyLPA) 16 | [![](https://cranlogs.r-pkg.org/badges/tidyLPA)](https://cran.r-project.org/package=tidyLPA) 17 | [![lifecycle](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html) 18 | [![DOI](http://joss.theoj.org/papers/10.21105/joss.00978/status.svg)](https://doi.org/10.21105/joss.00978) 19 | [![R-CMD-check](https://github.com/data-edu/tidyLPA/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/data-edu/tidyLPA/actions/workflows/R-CMD-check.yaml) 20 | [![test-coverage](https://github.com/data-edu/tidyLPA/actions/workflows/test-coverage.yaml/badge.svg)](https://github.com/data-edu/tidyLPA/actions/workflows/test-coverage.yaml) 21 | 22 | ## Background 23 | 24 | Latent Profile Analysis (LPA) is a statistical modeling approach for estimating distinct profiles, or groups, of variables. In the social sciences and in educational research, these profiles could represent, for example, how different youth experience dimensions of being engaged (i.e., cognitively, behaviorally, and affectively) at the same time. 25 | 26 | tidyLPA provides the functionality to carry out LPA in R. In particular, tidyLPA provides functionality to specify different models that determine whether and how different parameters (i.e., means, variances, and covariances) are estimated and to specify (and compare solutions for) the number of profiles to estimate. The package is designed and documented to be easy to use, especially for beginners to LPA, but with fine-grained options available for estimating models and evaluating specific output as part of more complex analyses. 27 | 28 | ## Installation 29 | 30 | You can install tidyLPA from CRAN with: 31 | 32 | ```{r, eval = F} 33 | install.packages("tidyLPA") 34 | ``` 35 | 36 | You can also install the development version of tidyLPA from GitHub with: 37 | 38 | ```{r gh-installation, eval = FALSE} 39 | install.packages("devtools") 40 | devtools::install_github("data-edu/tidyLPA") 41 | ``` 42 | 43 | ## Examples 44 | 45 | ### Mclust 46 | 47 | Here is a brief example using the built-in `pisaUSA15` data set and variables for broad interest, enjoyment, and self-efficacy. Note that we first type the name of the data frame, followed by the unquoted names of the variables used to create the profiles. We also specify the number of profiles and the model. See `?estimate_profiles` for more details. 48 | 49 | In these examples, we pass the results of one function to the next by *piping* (using the `%>%` operator, loaded from the `dplyr` package). We pass the data to a function that selects relevant variables, and then to `estimate_profiles`: 50 | 51 | ```{r, message = F} 52 | library(tidyLPA) 53 | library(dplyr) 54 | ``` 55 | 56 | ```{r} 57 | pisaUSA15[1:100, ] %>% 58 | select(broad_interest, enjoyment, self_efficacy) %>% 59 | single_imputation() %>% 60 | estimate_profiles(3) 61 | ``` 62 | 63 | A simple summary of the analysis is printed to the console (and its posterior probability). 64 | 65 | The resulting object can be further passed down a pipeline to other functions, such as: 66 | 67 | - `plot_profiles()` 68 | - `compare_solutions()` 69 | - `get_data()` 70 | - `get_fit()` 71 | 72 | This is the "tidy" part, in that the function can be embedded in a tidy analysis pipeline. 73 | 74 | ### Mplus 75 | 76 | We can use MPlus simply by changing the package argument for `estimate_profiles()` to `"MplusAutomation"` (please note that _MPlus must be installed on your computer for this functionality to work_): 77 | 78 | ```{r, eval = FALSE} 79 | pisaUSA15[1:100, ] %>% 80 | select(broad_interest, enjoyment, self_efficacy) %>% 81 | single_imputation() %>% 82 | estimate_profiles(3, package = "MplusAutomation") 83 | ``` 84 | 85 | # Learning More 86 | 87 | To learn more, we highly recommend the following: 88 | 89 | * Browse the tidyLPA [website](https://data-edu.github.io/tidyLPA/) (especially check out the Reference page to see more about other functions) 90 | * *Read the Introduction to tidyLPA* [vignette](https://data-edu.github.io/tidyLPA/articles/Introduction_to_tidyLPA.html), which has much more information on the models that can be specified with tidyLPA and on additional functionality 91 | 92 | ## Citing tidyLPA 93 | 94 | > Rosenberg, J. M., Beymer, P. N., Anderson, D. J., Van Lissa, C. J., & Schmidt, J. A. (2018). tidyLPA: An R Package to Easily Carry Out Latent Profile Analysis (LPA) Using Open-Source or Commercial Software. *Journal of Open Source Software, 3*(30), 978, https://doi.org/10.21105/joss.00978 95 | 96 | ## Contributing and Contact Information 97 | 98 | One of the easiest but also most important ways to contribute is to post a question or to provide feedback. Both positive *and* negative feedback is welcome and helpful. You can get in touch by: 99 | 100 | * Sending a message via [tidylpa@googlegroups.com](mailto:tidylpa@googlegroups.com) or view the [the tidyLPA group page](https://groups.google.com/forum/#!forum/tidylpa) 101 | 102 | * Filing an issue on GitHub [here](https://github.com/data-edu/tidyLPA) 103 | 104 | Contributions are also welcome via by making pull requests (PR), e.g. through [this page on GitHub](https://github.com/data-edu/tidyLPA/pulls). 105 | 106 | It may be easier if you first file an issue outlining what you will do in the PR. You can also reach out via the methods described above. 107 | 108 | ## Contributor Code of Conduct 109 | 110 | Please note that this project is released with a [Contributor Code of Conduct](https://link.springer.com/article/10.1007/s41686-019-00030-5). By participating in this project you agree to abide by its terms. 111 | 112 | ## Acknowledgments 113 | 114 | This material is based upon work supported by the National Science Foundation under *Grant No.: DRL#1661064*. Any opinions, findings, conclusions, or recommendations expressed in this material are those of the authors and do not reflect the views of the National Science Foundation. 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [![CRAN 5 | status](https://www.r-pkg.org/badges/version/tidyLPA)](https://cran.r-project.org/package=tidyLPA) 6 | [![](https://cranlogs.r-pkg.org/badges/tidyLPA)](https://cran.r-project.org/package=tidyLPA) 7 | [![lifecycle](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html) 8 | [![DOI](http://joss.theoj.org/papers/10.21105/joss.00978/status.svg)](https://doi.org/10.21105/joss.00978) 9 | [![R-CMD-check](https://github.com/data-edu/tidyLPA/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/data-edu/tidyLPA/actions/workflows/R-CMD-check.yaml) 10 | [![test-coverage](https://github.com/data-edu/tidyLPA/actions/workflows/test-coverage.yaml/badge.svg)](https://github.com/data-edu/tidyLPA/actions/workflows/test-coverage.yaml) 11 | 12 | ## Background 13 | 14 | Latent Profile Analysis (LPA) is a statistical modeling approach for 15 | estimating distinct profiles, or groups, of variables. In the social 16 | sciences and in educational research, these profiles could represent, 17 | for example, how different youth experience dimensions of being engaged 18 | (i.e., cognitively, behaviorally, and affectively) at the same time. 19 | 20 | tidyLPA provides the functionality to carry out LPA in R. In particular, 21 | tidyLPA provides functionality to specify different models that 22 | determine whether and how different parameters (i.e., means, variances, 23 | and covariances) are estimated and to specify (and compare solutions 24 | for) the number of profiles to estimate. The package is designed and 25 | documented to be easy to use, especially for beginners to LPA, but with 26 | fine-grained options available for estimating models and evaluating 27 | specific output as part of more complex analyses. 28 | 29 | ## Installation 30 | 31 | You can install tidyLPA from CRAN with: 32 | 33 | ``` r 34 | install.packages("tidyLPA") 35 | ``` 36 | 37 | You can also install the development version of tidyLPA from GitHub 38 | with: 39 | 40 | ``` r 41 | install.packages("devtools") 42 | devtools::install_github("data-edu/tidyLPA") 43 | ``` 44 | 45 | ## Examples 46 | 47 | ### Mclust 48 | 49 | Here is a brief example using the built-in `pisaUSA15` data set and 50 | variables for broad interest, enjoyment, and self-efficacy. Note that we 51 | first type the name of the data frame, followed by the unquoted names of 52 | the variables used to create the profiles. We also specify the number of 53 | profiles and the model. See `?estimate_profiles` for more details. 54 | 55 | In these examples, we pass the results of one function to the next by 56 | *piping* (using the `%>%` operator, loaded from the `dplyr` package). We 57 | pass the data to a function that selects relevant variables, and then to 58 | `estimate_profiles`: 59 | 60 | ``` r 61 | library(tidyLPA) 62 | library(dplyr) 63 | ``` 64 | 65 | ``` r 66 | pisaUSA15[1:100, ] %>% 67 | select(broad_interest, enjoyment, self_efficacy) %>% 68 | single_imputation() %>% 69 | estimate_profiles(3) 70 | #> tidyLPA analysis using mclust: 71 | #> 72 | #> Model Classes AIC BIC Entropy prob_min prob_max n_min n_max BLRT_p 73 | #> 1 3 639.76 676.23 0.81 0.85 0.95 0.03 0.65 0.01 74 | ``` 75 | 76 | A simple summary of the analysis is printed to the console (and its 77 | posterior probability). 78 | 79 | The resulting object can be further passed down a pipeline to other 80 | functions, such as: 81 | 82 | - `plot_profiles()` 83 | - `compare_solutions()` 84 | - `get_data()` 85 | - `get_fit()` 86 | 87 | This is the “tidy” part, in that the function can be embedded in a tidy 88 | analysis pipeline. 89 | 90 | ### Mplus 91 | 92 | We can use MPlus simply by changing the package argument for 93 | `estimate_profiles()` to `"MplusAutomation"` (please note that *MPlus 94 | must be installed on your computer for this functionality to work*): 95 | 96 | ``` r 97 | pisaUSA15[1:100, ] %>% 98 | select(broad_interest, enjoyment, self_efficacy) %>% 99 | single_imputation() %>% 100 | estimate_profiles(3, package = "MplusAutomation") 101 | ``` 102 | 103 | # Learning More 104 | 105 | To learn more, we highly recommend the following: 106 | 107 | - Browse the tidyLPA [website](https://data-edu.github.io/tidyLPA/) 108 | (especially check out the Reference page to see more about other 109 | functions) 110 | - *Read the Introduction to tidyLPA* 111 | [vignette](https://data-edu.github.io/tidyLPA/articles/Introduction_to_tidyLPA.html), 112 | which has much more information on the models that can be specified 113 | with tidyLPA and on additional functionality 114 | 115 | ## Citing tidyLPA 116 | 117 | > Rosenberg, J. M., Beymer, P. N., Anderson, D. J., Van Lissa, C. J., & 118 | > Schmidt, J. A. (2018). tidyLPA: An R Package to Easily Carry Out 119 | > Latent Profile Analysis (LPA) Using Open-Source or Commercial 120 | > Software. *Journal of Open Source Software, 3*(30), 978, 121 | > 122 | 123 | ## Contributing and Contact Information 124 | 125 | One of the easiest but also most important ways to contribute is to post 126 | a question or to provide feedback. Both positive *and* negative feedback 127 | is welcome and helpful. You can get in touch by: 128 | 129 | - Sending a message via or view the [the 130 | tidyLPA group page](https://groups.google.com/forum/#!forum/tidylpa) 131 | 132 | - Filing an issue on GitHub [here](https://github.com/data-edu/tidyLPA) 133 | 134 | Contributions are also welcome via by making pull requests (PR), 135 | e.g. through [this page on 136 | GitHub](https://github.com/data-edu/tidyLPA/pulls). 137 | 138 | It may be easier if you first file an issue outlining what you will do 139 | in the PR. You can also reach out via the methods described above. 140 | 141 | ## Contributor Code of Conduct 142 | 143 | Please note that this project is released with a [Contributor Code of 144 | Conduct](https://link.springer.com/article/10.1007/s41686-019-00030-5). 145 | By participating in this project you agree to abide by its terms. 146 | 147 | ## Acknowledgments 148 | 149 | This material is based upon work supported by the National Science 150 | Foundation under *Grant No.: DRL#1661064*. Any opinions, findings, 151 | conclusions, or recommendations expressed in this material are those of 152 | the authors and do not reflect the views of the National Science 153 | Foundation. 154 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Getting help with tidyLPA 2 | 3 | Thanks for using tidyLPA. Before filing an issue, there are a few places to 4 | explore and pieces to put together to make the process as smooth as possible. 5 | 6 | Start by making a minimal **repr**oducible **ex**ample using the [reprex](http://reprex.tidyverse.org/) package. 7 | If you haven't heard of or used reprex 8 | before, you're in for a treat! Seriously, reprex will make all of your R- 9 | question-asking endeavors easier (which is a pretty insane ROI for the five to 10 | ten minutes it'll take you to learn what it's all about). For additional reprex 11 | pointers, check out the [Get help!](https://www.tidyverse.org/help/) section of 12 | the tidyverse site. 13 | 14 | One of the easiest but also most important ways to contribute is to post a 15 | question or to provide feedback. Both positive *and* negative feedback is 16 | welcome and helpful. You can get in touch by . . . 17 | 18 | * Sending a message via [tidylpa@googlegroups.com] 19 | (mailto:tidylpa@googlegroups.com) or view the [the tidyLPA group page](https:// 20 | groups.google.com/forum/#!forum/tidylpa) (*preferred*) 21 | * Filing an issue on GitHub [here](https://github.com/jrosen48/tidyLPA) 22 | 23 | Contributions are also welcome via by making pull requests (PR), e.g. through 24 | [this page on GitHub](https://github.com/jrosen48/tidyLPA/pulls). It may be 25 | easier if you first file an issue outlining what you will do in the PR. You can 26 | also reach out via the methods described above. 27 | 28 | Please note that this project is released with a [Contributor Code of Conduct](CONDUCT.md). 29 | By participating in this project you agree to abide by its terms. 30 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | # CRAN comments 2 | 3 | * Add support for OpenMx 4 | 5 | ## Test environments 6 | * local local Windows 10 install, R 3.6.1 7 | * local OS X install, R 3.5.1 8 | * travis-ci, Ubuntu 16.04.6, R 3.6.1 9 | * rhub check: Windows Server 2008 R2 SP1, R-devel, 32/64 bit 10 | * rhub check: Ubuntu Linux 16.04 LTS, R-release, GCC 11 | * rhub check: Fedora Linux, R-devel, clang, gfortran 12 | * win-builder (devel and release) 13 | 14 | ## R CMD check results 15 | 16 | 0 errors | 0 warnings | 0 notes 17 | -------------------------------------------------------------------------------- /data/pisaUSA15.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/data/pisaUSA15.rda -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Page not found (404) • tidyLPA 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 |
24 |
76 | 77 | 78 | 79 | 80 |
81 |
82 | 85 | 86 | Content not found. Please use links in the navbar. 87 | 88 |
89 | 90 | 94 | 95 |
96 | 97 | 98 | 99 |
103 | 104 |
105 |

106 |

Site built with pkgdown 2.0.7.

107 |
108 | 109 |
110 |
111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /docs/LICENSE-text.html: -------------------------------------------------------------------------------- 1 | 2 | License • tidyLPA 6 | 7 | 8 |
9 |
53 | 54 | 55 | 56 |
57 |
58 | 61 | 62 |
YEAR: 2019
63 | COPYRIGHT HOLDER: Joshua M. Rosenberg, Caspar J. van Lissa, Patrick N. Beymer, Daniel Anderson, Jennifer A. Schmidt, and Matthew J. Schell
64 | 
65 | 66 |
67 | 68 | 71 | 72 |
73 | 74 | 75 | 76 |
79 | 80 |
81 |

Site built with pkgdown 2.0.7.

82 |
83 | 84 |
85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /docs/LICENSE.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | MIT License • tidyLPA 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 45 | 46 | 47 | 48 | 49 | 50 |
51 |
52 | 108 | 109 | 110 |
111 | 112 |
113 |
114 | 117 | 118 |
119 | 120 |

Copyright (c) 2018 Joshua M. Rosenberg, Patrick N. Beymer, Daniel Anderson, and Jennifer A. Schmidt

121 |

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

122 |

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

123 |

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

124 |
125 | 126 |
127 | 128 |
129 | 130 | 131 |
132 | 135 | 136 |
137 |

Site built with pkgdown 1.3.0.

138 |
139 |
140 |
141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /docs/README-unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/README-unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /docs/README-unnamed-chunk-4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/README-unnamed-chunk-4-1.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-10-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-10-1.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-10-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-10-2.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-11-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-11-1.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-11-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-11-2.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-12-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-12-1.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-12-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-12-2.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-2-1.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-4-1.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-5-1.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-6-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-6-1.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-7-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-7-1.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-8-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-8-1.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-8-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-8-2.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-9-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-9-1.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-9-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/Introduction_to_tidyLPA_files/figure-html/unnamed-chunk-9-2.png -------------------------------------------------------------------------------- /docs/articles/Introduction_to_tidyLPA_files/header-attrs-2.6/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/benchmarking-mclust-and-mplus_files/header-attrs-2.6/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/comparing-mclust-and-mplus-output.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Using MPlus via tidyLPA • tidyLPA 9 | 10 | 11 | 12 | 16 | 17 | 18 |
19 |
47 | 48 | 49 | 50 |
51 |
52 | 58 | 59 | 60 | 61 |
62 |

This

63 |
64 |
65 | 66 | 68 | 69 |
70 | 71 | 72 |
75 | 76 |
77 |

Site built with pkgdown.

78 |
79 | 80 |
81 |
82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /docs/articles/index.html: -------------------------------------------------------------------------------- 1 | 2 | Articles • tidyLPA 6 | 7 | 8 |
9 |
53 | 54 | 55 | 56 |
57 |
58 | 61 | 62 |
63 |

All vignettes

64 |

65 | 66 |
Introduction to tidyLPA
67 |
68 |
Benchmarking mclust and MPlus
69 |
70 |
71 |
72 |
73 | 74 | 75 |
78 | 79 |
80 |

Site built with pkgdown 2.0.7.

81 |
82 | 83 |
84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /docs/articles/introduction-to-major-changes_files/figure-html/unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/articles/introduction-to-major-changes_files/figure-html/unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /docs/articles/rsconnect/documents/notes-on-model-selection.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | • tidyLPA 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 |
22 |
72 | 73 | 74 | 75 |
76 |
77 | 85 | 86 | 87 | 88 | 89 |
90 | 91 | 93 | 94 |
95 | 96 | 97 |
100 | 101 |
102 |

Site built with pkgdown.

103 |
104 | 105 |
106 |
107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | 6 | /* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ 7 | 8 | /* All levels of nav */ 9 | nav[data-toggle='toc'] .nav > li > a { 10 | display: block; 11 | padding: 4px 20px; 12 | font-size: 13px; 13 | font-weight: 500; 14 | color: #767676; 15 | } 16 | nav[data-toggle='toc'] .nav > li > a:hover, 17 | nav[data-toggle='toc'] .nav > li > a:focus { 18 | padding-left: 19px; 19 | color: #563d7c; 20 | text-decoration: none; 21 | background-color: transparent; 22 | border-left: 1px solid #563d7c; 23 | } 24 | nav[data-toggle='toc'] .nav > .active > a, 25 | nav[data-toggle='toc'] .nav > .active:hover > a, 26 | nav[data-toggle='toc'] .nav > .active:focus > a { 27 | padding-left: 18px; 28 | font-weight: bold; 29 | color: #563d7c; 30 | background-color: transparent; 31 | border-left: 2px solid #563d7c; 32 | } 33 | 34 | /* Nav: second level (shown on .active) */ 35 | nav[data-toggle='toc'] .nav .nav { 36 | display: none; /* Hide by default, but at >768px, show it */ 37 | padding-bottom: 10px; 38 | } 39 | nav[data-toggle='toc'] .nav .nav > li > a { 40 | padding-top: 1px; 41 | padding-bottom: 1px; 42 | padding-left: 30px; 43 | font-size: 12px; 44 | font-weight: normal; 45 | } 46 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 47 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 48 | padding-left: 29px; 49 | } 50 | nav[data-toggle='toc'] .nav .nav > .active > a, 51 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 52 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 53 | padding-left: 28px; 54 | font-weight: 500; 55 | } 56 | 57 | /* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ 58 | nav[data-toggle='toc'] .nav > .active > ul { 59 | display: block; 60 | } 61 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | (function() { 6 | 'use strict'; 7 | 8 | window.Toc = { 9 | helpers: { 10 | // return all matching elements in the set, or their descendants 11 | findOrFilter: function($el, selector) { 12 | // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ 13 | // http://stackoverflow.com/a/12731439/358804 14 | var $descendants = $el.find(selector); 15 | return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); 16 | }, 17 | 18 | generateUniqueIdBase: function(el) { 19 | var text = $(el).text(); 20 | var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); 21 | return anchor || el.tagName.toLowerCase(); 22 | }, 23 | 24 | generateUniqueId: function(el) { 25 | var anchorBase = this.generateUniqueIdBase(el); 26 | for (var i = 0; ; i++) { 27 | var anchor = anchorBase; 28 | if (i > 0) { 29 | // add suffix 30 | anchor += '-' + i; 31 | } 32 | // check if ID already exists 33 | if (!document.getElementById(anchor)) { 34 | return anchor; 35 | } 36 | } 37 | }, 38 | 39 | generateAnchor: function(el) { 40 | if (el.id) { 41 | return el.id; 42 | } else { 43 | var anchor = this.generateUniqueId(el); 44 | el.id = anchor; 45 | return anchor; 46 | } 47 | }, 48 | 49 | createNavList: function() { 50 | return $(''); 51 | }, 52 | 53 | createChildNavList: function($parent) { 54 | var $childList = this.createNavList(); 55 | $parent.append($childList); 56 | return $childList; 57 | }, 58 | 59 | generateNavEl: function(anchor, text) { 60 | var $a = $(''); 61 | $a.attr('href', '#' + anchor); 62 | $a.text(text); 63 | var $li = $('
  • '); 64 | $li.append($a); 65 | return $li; 66 | }, 67 | 68 | generateNavItem: function(headingEl) { 69 | var anchor = this.generateAnchor(headingEl); 70 | var $heading = $(headingEl); 71 | var text = $heading.data('toc-text') || $heading.text(); 72 | return this.generateNavEl(anchor, text); 73 | }, 74 | 75 | // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). 76 | getTopLevel: function($scope) { 77 | for (var i = 1; i <= 6; i++) { 78 | var $headings = this.findOrFilter($scope, 'h' + i); 79 | if ($headings.length > 1) { 80 | return i; 81 | } 82 | } 83 | 84 | return 1; 85 | }, 86 | 87 | // returns the elements for the top level, and the next below it 88 | getHeadings: function($scope, topLevel) { 89 | var topSelector = 'h' + topLevel; 90 | 91 | var secondaryLevel = topLevel + 1; 92 | var secondarySelector = 'h' + secondaryLevel; 93 | 94 | return this.findOrFilter($scope, topSelector + ',' + secondarySelector); 95 | }, 96 | 97 | getNavLevel: function(el) { 98 | return parseInt(el.tagName.charAt(1), 10); 99 | }, 100 | 101 | populateNav: function($topContext, topLevel, $headings) { 102 | var $context = $topContext; 103 | var $prevNav; 104 | 105 | var helpers = this; 106 | $headings.each(function(i, el) { 107 | var $newNav = helpers.generateNavItem(el); 108 | var navLevel = helpers.getNavLevel(el); 109 | 110 | // determine the proper $context 111 | if (navLevel === topLevel) { 112 | // use top level 113 | $context = $topContext; 114 | } else if ($prevNav && $context === $topContext) { 115 | // create a new level of the tree and switch to it 116 | $context = helpers.createChildNavList($prevNav); 117 | } // else use the current $context 118 | 119 | $context.append($newNav); 120 | 121 | $prevNav = $newNav; 122 | }); 123 | }, 124 | 125 | parseOps: function(arg) { 126 | var opts; 127 | if (arg.jquery) { 128 | opts = { 129 | $nav: arg 130 | }; 131 | } else { 132 | opts = arg; 133 | } 134 | opts.$scope = opts.$scope || $(document.body); 135 | return opts; 136 | } 137 | }, 138 | 139 | // accepts a jQuery object, or an options object 140 | init: function(opts) { 141 | opts = this.helpers.parseOps(opts); 142 | 143 | // ensure that the data attribute is in place for styling 144 | opts.$nav.attr('data-toggle', 'toc'); 145 | 146 | var $topContext = this.helpers.createChildNavList(opts.$nav); 147 | var topLevel = this.helpers.getTopLevel(opts.$scope); 148 | var $headings = this.helpers.getHeadings(opts.$scope, topLevel); 149 | this.helpers.populateNav($topContext, topLevel, $headings); 150 | } 151 | }; 152 | 153 | $(function() { 154 | $('nav[data-toggle="toc"]').each(function(i, el) { 155 | var $nav = $(el); 156 | Toc.init($nav); 157 | }); 158 | }); 159 | })(); 160 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /docs/jquery.sticky-kit.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 3 | */ 4 | (function(){var b,f;b=this.jQuery||window.jQuery;f=b(window);b.fn.stick_in_parent=function(d){var A,w,J,n,B,K,p,q,k,E,t;null==d&&(d={});t=d.sticky_class;B=d.inner_scrolling;E=d.recalc_every;k=d.parent;q=d.offset_top;p=d.spacer;w=d.bottoming;null==q&&(q=0);null==k&&(k=void 0);null==B&&(B=!0);null==t&&(t="is_stuck");A=b(document);null==w&&(w=!0);J=function(a,d,n,C,F,u,r,G){var v,H,m,D,I,c,g,x,y,z,h,l;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);I=A.height();g=a.parent();null!=k&&(g=g.closest(k)); 5 | if(!g.length)throw"failed to find stick parent";v=m=!1;(h=null!=p?p&&a.closest(p):b("
    "))&&h.css("position",a.css("position"));x=function(){var c,f,e;if(!G&&(I=A.height(),c=parseInt(g.css("border-top-width"),10),f=parseInt(g.css("padding-top"),10),d=parseInt(g.css("padding-bottom"),10),n=g.offset().top+c+f,C=g.height(),m&&(v=m=!1,null==p&&(a.insertAfter(h),h.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(t),e=!0),F=a.offset().top-(parseInt(a.css("margin-top"),10)||0)-q, 6 | u=a.outerHeight(!0),r=a.css("float"),h&&h.css({width:a.outerWidth(!0),height:u,display:a.css("display"),"vertical-align":a.css("vertical-align"),"float":r}),e))return l()};x();if(u!==C)return D=void 0,c=q,z=E,l=function(){var b,l,e,k;if(!G&&(e=!1,null!=z&&(--z,0>=z&&(z=E,x(),e=!0)),e||A.height()===I||x(),e=f.scrollTop(),null!=D&&(l=e-D),D=e,m?(w&&(k=e+u+c>C+n,v&&!k&&(v=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom"))),eb&&!v&&(c-=l,c=Math.max(b-u,c),c=Math.min(q,c),m&&a.css({top:c+"px"})))):e>F&&(m=!0,b={position:"fixed",top:c},b.width="border-box"===a.css("box-sizing")?a.outerWidth()+"px":a.width()+"px",a.css(b).addClass(t),null==p&&(a.after(h),"left"!==r&&"right"!==r||h.append(a)),a.trigger("sticky_kit:stick")),m&&w&&(null==k&&(k=e+u+c>C+n),!v&&k)))return v=!0,"static"===g.css("position")&&g.css({position:"relative"}), 8 | a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")},y=function(){x();return l()},H=function(){G=!0;f.off("touchmove",l);f.off("scroll",l);f.off("resize",y);b(document.body).off("sticky_kit:recalc",y);a.off("sticky_kit:detach",H);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});g.position("position","");if(m)return null==p&&("left"!==r&&"right"!==r||a.insertAfter(h),h.remove()),a.removeClass(t)},f.on("touchmove",l),f.on("scroll",l),f.on("resize", 9 | y),b(document.body).on("sticky_kit:recalc",y),a.on("sticky_kit:detach",H),setTimeout(l,0)}};n=0;for(K=this.length;n 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /docs/man/figures/README-unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/man/figures/README-unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /docs/man/figures/README-unnamed-chunk-4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/man/figures/README-unnamed-chunk-4-1.png -------------------------------------------------------------------------------- /docs/man/figures/README-unnamed-chunk-5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/man/figures/README-unnamed-chunk-5-1.png -------------------------------------------------------------------------------- /docs/man/figures/README-unnamed-chunk-6-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/man/figures/README-unnamed-chunk-6-1.png -------------------------------------------------------------------------------- /docs/notes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | NA • tidyLPA 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 51 | 52 | 53 | 54 | 55 | 56 | 57 |
    58 |
    59 | 111 | 112 | 113 | 114 |
    115 | 116 |
    117 |
    118 | 121 | 122 | 123 |
    124 |

    125 | plot_profiles()

    126 | 130 |
    131 |
    132 |

    133 | compare_solutions()

    134 |
      135 |
    • add error checking for wrong spelling of arguments (i.e., for what statistic to plot for compare_solutions())
    • 136 |
    137 |
    138 |
    139 |

    140 | compare_solutions_mplus()

    141 |
      142 |
    • add more info when model cannot be fitted about why
    • 143 |
    144 |
    145 |
    146 |

    147 | estimate_profiles_plus()

    148 |
      149 |
    • make all of the Mplus lines lowercase
    • 150 |
    • add a helper function to create the model syntax for Mplus
    • 151 |
    152 |
    153 | 154 | 155 |
    156 | 157 |
    158 | 159 | 160 | 161 |
    162 | 165 | 166 |
    167 |

    Site built with pkgdown 1.4.1.

    168 |
    169 | 170 |
    171 |
    172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $('.navbar-fixed-top').headroom(); 6 | 7 | $('body').css('padding-top', $('.navbar').height() + 10); 8 | $(window).resize(function(){ 9 | $('body').css('padding-top', $('.navbar').height() + 10); 10 | }); 11 | 12 | $('[data-toggle="tooltip"]').tooltip(); 13 | 14 | var cur_path = paths(location.pathname); 15 | var links = $("#navbar ul li a"); 16 | var max_length = -1; 17 | var pos = -1; 18 | for (var i = 0; i < links.length; i++) { 19 | if (links[i].getAttribute("href") === "#") 20 | continue; 21 | // Ignore external links 22 | if (links[i].host !== location.host) 23 | continue; 24 | 25 | var nav_path = paths(links[i].pathname); 26 | 27 | var length = prefix_length(nav_path, cur_path); 28 | if (length > max_length) { 29 | max_length = length; 30 | pos = i; 31 | } 32 | } 33 | 34 | // Add class to parent
  • , and enclosing
  • if in dropdown 35 | if (pos >= 0) { 36 | var menu_anchor = $(links[pos]); 37 | menu_anchor.parent().addClass("active"); 38 | menu_anchor.closest("li.dropdown").addClass("active"); 39 | } 40 | }); 41 | 42 | function paths(pathname) { 43 | var pieces = pathname.split("/"); 44 | pieces.shift(); // always starts with / 45 | 46 | var end = pieces[pieces.length - 1]; 47 | if (end === "index.html" || end === "") 48 | pieces.pop(); 49 | return(pieces); 50 | } 51 | 52 | // Returns -1 if not found 53 | function prefix_length(needle, haystack) { 54 | if (needle.length > haystack.length) 55 | return(-1); 56 | 57 | // Special case for length-0 haystack, since for loop won't run 58 | if (haystack.length === 0) { 59 | return(needle.length === 0 ? 0 : -1); 60 | } 61 | 62 | for (var i = 0; i < haystack.length; i++) { 63 | if (needle[i] != haystack[i]) 64 | return(i); 65 | } 66 | 67 | return(haystack.length); 68 | } 69 | 70 | /* Clipboard --------------------------*/ 71 | 72 | function changeTooltipMessage(element, msg) { 73 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 74 | element.setAttribute('data-original-title', msg); 75 | $(element).tooltip('show'); 76 | element.setAttribute('data-original-title', tooltipOriginalTitle); 77 | } 78 | 79 | if(ClipboardJS.isSupported()) { 80 | $(document).ready(function() { 81 | var copyButton = ""; 82 | 83 | $("div.sourceCode").addClass("hasCopyButton"); 84 | 85 | // Insert copy buttons: 86 | $(copyButton).prependTo(".hasCopyButton"); 87 | 88 | // Initialize tooltips: 89 | $('.btn-copy-ex').tooltip({container: 'body'}); 90 | 91 | // Initialize clipboard: 92 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { 93 | text: function(trigger) { 94 | return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, ""); 95 | } 96 | }); 97 | 98 | clipboardBtnCopies.on('success', function(e) { 99 | changeTooltipMessage(e.trigger, 'Copied!'); 100 | e.clearSelection(); 101 | }); 102 | 103 | clipboardBtnCopies.on('error', function() { 104 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 105 | }); 106 | }); 107 | } 108 | })(window.jQuery || window.$) 109 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 3.1.1 2 | pkgdown: 2.0.7 3 | pkgdown_sha: ~ 4 | articles: 5 | Introduction_to_tidyLPA: Introduction_to_tidyLPA.html 6 | benchmarking-mclust-and-mplus: benchmarking-mclust-and-mplus.html 7 | last_built: 2024-02-15T01:08Z 8 | 9 | -------------------------------------------------------------------------------- /docs/reference/Rplot001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/Rplot001.png -------------------------------------------------------------------------------- /docs/reference/Rplot002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/Rplot002.png -------------------------------------------------------------------------------- /docs/reference/compare_solutions-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/compare_solutions-1.png -------------------------------------------------------------------------------- /docs/reference/compare_solutions-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/compare_solutions-2.png -------------------------------------------------------------------------------- /docs/reference/compare_solutions_lpa-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/compare_solutions_lpa-2.png -------------------------------------------------------------------------------- /docs/reference/extract_mplus_summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Extract summary statistics from an Mplus model — extract_mplus_summary • tidyLPA 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    Extract summary statistics from an Mplus model

    83 | 84 | 85 |
    extract_mplus_summary(x)
    86 | 87 |

    Arguments

    88 | 89 | 90 | 91 | 92 | 93 | 94 |
    x

    an mplus model

    95 | 96 |

    Value

    97 | 98 |

    a tibble with summary statistics

    99 | 100 |

    Details

    101 | 102 |

    Extract log likelihood, BIC, and entropy statistics from an Mplus model

    103 | 104 | 105 |
    106 | 117 |
    118 | 119 |
    120 | 123 | 124 |
    125 |

    Site built with pkgdown.

    126 |
    127 | 128 |
    129 |
    130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /docs/reference/figures/README-unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/figures/README-unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /docs/reference/figures/README-unnamed-chunk-4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/figures/README-unnamed-chunk-4-1.png -------------------------------------------------------------------------------- /docs/reference/figures/README-unnamed-chunk-5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/figures/README-unnamed-chunk-5-1.png -------------------------------------------------------------------------------- /docs/reference/figures/README-unnamed-chunk-6-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/figures/README-unnamed-chunk-6-1.png -------------------------------------------------------------------------------- /docs/reference/figures/README-unnamed-chunk-7-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/figures/README-unnamed-chunk-7-1.png -------------------------------------------------------------------------------- /docs/reference/plot_profiles-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/plot_profiles-1.png -------------------------------------------------------------------------------- /docs/reference/plot_profiles-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/plot_profiles-11.png -------------------------------------------------------------------------------- /docs/reference/plot_profiles-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/plot_profiles-14.png -------------------------------------------------------------------------------- /docs/reference/plot_profiles-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/plot_profiles-2.png -------------------------------------------------------------------------------- /docs/reference/plot_profiles-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/docs/reference/plot_profiles-7.png -------------------------------------------------------------------------------- /docs/reference/plot_profiles_lpa.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Plot profile centroids — plot_profiles_lpa • tidyLPA 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    Plot profile centroids

    83 | 84 | 85 |
    plot_profiles_lpa(x, to_center = F, to_scale = F, plot_what = "tibble",
     86 |   plot_error_bars = TRUE)
    87 | 88 |

    Arguments

    89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 |
    x

    output from create_profiles_mclust()

    to_center

    whether to center the data before plotting

    to_scale

    whether to scale the data before plotting

    plot_what

    whether to plot tibble or mclust output from estimate_profiles_lpa(); defaults to tibble

    plot_error_bars

    whether to plot error bars (representing the 95 percent confidence interval for the mean of each variable)

    112 | 113 |

    Details

    114 | 115 |

    Plot the centroids for tibble or mclust output from estimate_profiles_lpa()

    116 | 117 | 118 |
    119 | 128 |
    129 | 130 |
    131 | 134 | 135 |
    136 |

    Site built with pkgdown.

    137 |
    138 | 139 |
    140 |
    141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /docs/reference/reexports.html: -------------------------------------------------------------------------------- 1 | 2 | Objects exported from other packages — reexports • tidyLPA 13 | 14 | 15 |
    16 |
    60 | 61 | 62 | 63 |
    64 |
    65 | 70 | 71 |
    72 |

    These objects are imported from other packages. Follow the links 73 | below to see their documentation.

    74 |
    tidySEM
    75 |

    plot_bivariate, plot_density, plot_profiles

    76 | 77 | 78 |
    79 | 80 | 81 | 82 |
    83 | 86 |
    87 | 88 | 89 |
    92 | 93 |
    94 |

    Site built with pkgdown 2.0.7.

    95 |
    96 | 97 |
    98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /404.html 5 | 6 | 7 | /CODE_OF_CONDUCT.html 8 | 9 | 10 | /CONDUCT.html 11 | 12 | 13 | /LICENSE-text.html 14 | 15 | 16 | /LICENSE.html 17 | 18 | 19 | /SUPPORT.html 20 | 21 | 22 | /articles/Introduction_to_tidyLPA.html 23 | 24 | 25 | /articles/benchmarking-mclust-and-mplus.html 26 | 27 | 28 | /articles/brief-overview.html 29 | 30 | 31 | /articles/comparing-mclust-and-mplus-output.html 32 | 33 | 34 | /articles/index.html 35 | 36 | 37 | /articles/introduction-to-major-changes.html 38 | 39 | 40 | /articles/notes-on-model-selection.html 41 | 42 | 43 | /articles/rsconnect/documents/notes-on-model-selection.html 44 | 45 | 46 | /authors.html 47 | 48 | 49 | /index.html 50 | 51 | 52 | /news/index.html 53 | 54 | 55 | /notes.html 56 | 57 | 58 | /paper.html 59 | 60 | 61 | /reference/AHP.html 62 | 63 | 64 | /reference/as.tidyLPA.html 65 | 66 | 67 | /reference/bootstrap_lrt-deprecated.html 68 | 69 | 70 | /reference/bootstrap_lrt.html 71 | 72 | 73 | /reference/calc_lrt.html 74 | 75 | 76 | /reference/compare_solutions.html 77 | 78 | 79 | /reference/compare_solutions_lpa.html 80 | 81 | 82 | /reference/compare_solutions_mplus-deprecated.html 83 | 84 | 85 | /reference/compare_solutions_mplus.html 86 | 87 | 88 | /reference/create_profiles_mplus.html 89 | 90 | 91 | /reference/curry_mac.html 92 | 93 | 94 | /reference/empathy.html 95 | 96 | 97 | /reference/estimate_profiles.html 98 | 99 | 100 | /reference/estimate_profiles_lpa.html 101 | 102 | 103 | /reference/estimate_profiles_mclust.html 104 | 105 | 106 | /reference/estimate_profiles_mplus-deprecated.html 107 | 108 | 109 | /reference/estimate_profiles_mplus.html 110 | 111 | 112 | /reference/estimate_profiles_mplus2.html 113 | 114 | 115 | /reference/estimate_profiles_openmx.html 116 | 117 | 118 | /reference/extract_LL_mplus.html 119 | 120 | 121 | /reference/extract_mplus_summary.html 122 | 123 | 124 | /reference/get_data.html 125 | 126 | 127 | /reference/get_estimates.html 128 | 129 | 130 | /reference/get_fit.html 131 | 132 | 133 | /reference/id_edu.html 134 | 135 | 136 | /reference/index.html 137 | 138 | 139 | /reference/mplusAvailable.html 140 | 141 | 142 | /reference/pipe.html 143 | 144 | 145 | /reference/pisaUSA15.html 146 | 147 | 148 | /reference/plot_bivariate.html 149 | 150 | 151 | /reference/plot_density.html 152 | 153 | 154 | /reference/plot_profiles.html 155 | 156 | 157 | /reference/plot_profiles_lpa.html 158 | 159 | 160 | /reference/plot_profiles_mplus-deprecated.html 161 | 162 | 163 | /reference/plot_profiles_mplus.html 164 | 165 | 166 | /reference/poms.html 167 | 168 | 169 | /reference/print.tidyLPA.html 170 | 171 | 172 | /reference/print.tidyProfile.html 173 | 174 | 175 | /reference/reexports.html 176 | 177 | 178 | /reference/single_imputation.html 179 | 180 | 181 | /reference/tidyLPA-deprecated.html 182 | 183 | 184 | /reference/tidyLPA.html 185 | 186 | 187 | -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | citHeader("To cite tidyLPA in publications use:") 2 | 3 | citEntry(entry = "Article", 4 | title = "tidyLPA: An R Package to Easily Carry Out Latent Profile Analysis (LPA) Using Open-Source or Commercial Software", 5 | author = personList(as.person("Joshua M. Rosenberg"), 6 | as.person("Patrick N. Beymer"), 7 | as.person("Daniel J. Anderson"), 8 | as.person("Caspar J. Van Lissa"), 9 | as.person("Jennifer A. Schmidt")), 10 | journal = "Journal of Open Source Software", 11 | year = "2018", 12 | volume = "3", 13 | number = "30", 14 | pages = "978", 15 | url = "https://joss.theoj.org/papers/10.21105/joss.00978", 16 | doi = "10.21105/joss.00978", 17 | 18 | textVersion = 19 | paste("Rosenberg, J. M., Beymer, P. N., Anderson, D. J., Van Lissa, C. J., & Schmidt, J. A. (2018). tidyLPA: An R Package to Easily Carry Out Latent Profile Analysis (LPA) Using Open-Source or Commercial Software. Journal of Open Source Software, 3(30), 978, https://doi.org/10.21105/joss.00978") 20 | ) 21 | -------------------------------------------------------------------------------- /man-roxygen/template-plot-profiles.R: -------------------------------------------------------------------------------- 1 | #' Create latent profile plots 2 | #' 3 | #' Creates a profile plot according to best practices, focusing on the 4 | #' visualization of classification uncertainty by showing: 5 | #' \enumerate{ 6 | #' \item Bars reflecting a confidence interval for the class centroids 7 | #' \item Boxes reflecting the standard deviations within each class; a box 8 | #' encompasses +/- 64\% of the observations in a normal distribution 9 | #' \item Raw data, whose transparancy is weighted by the posterior class 10 | #' probability, such that each datapoint is most clearly visible for the class 11 | #' it is most likely to be a member of. 12 | #' } 13 | #' @param x An object containing the results of a mixture model analysis. 14 | #' @param variables A character vectors with the names of the variables to be 15 | #' plotted (optional). 16 | #' @param ci Numeric. What confidence interval should the errorbars span? 17 | #' Defaults to a 95\% confidence interval. Set to NULL to remove errorbars. 18 | #' @param sd Logical. Whether to display a box encompassing +/- 1SD Defaults to 19 | #' TRUE. 20 | #' @param add_line Logical. Whether to display a line, connecting cluster centroids 21 | #' belonging to the same latent class. Defaults to TRUE. Note that the additional 22 | #' information conveyed by such a line is limited. 23 | #' @param rawdata Should raw data be plotted in the background? Setting this to 24 | #' TRUE might result in long plotting times. 25 | #' @param bw Logical. Should the plot be black and white (for print), or color? 26 | #' @param alpha_range The minimum and maximum values of alpha (transparancy) for 27 | #' the raw data. Minimum should be 0; lower maximum values of alpha can help 28 | #' reduce overplotting. 29 | #' @param ... Arguments passed to and from other functions. 30 | #' @return An object of class 'ggplot'. 31 | #' @author Caspar J. van Lissa 32 | #' @keywords plot mixture 33 | #' @examples 34 | #' # Example 1 35 | #' iris_sample <- iris[c(1:10, 51:60, 101:110), ] # to make example run more quickly 36 | #' 37 | #' iris_sample %>% 38 | #' subset(select = c("Sepal.Length", "Sepal.Width")) %>% 39 | #' estimate_profiles(n_profiles = 1:2, models = 1:2) %>% 40 | #' plot_profiles() 41 | #' 42 | #' # Example 2 43 | #' 44 | #' \donttest{ 45 | #' mtcars %>% 46 | #' subset(select = c("wt", "qsec", "drat")) %>% 47 | #' poms() %>% 48 | #' estimate_profiles(1:4) %>% 49 | #' plot_profiles(add_line = F) 50 | #'} 51 | 52 | -------------------------------------------------------------------------------- /man/.Rapp.history: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/man/.Rapp.history -------------------------------------------------------------------------------- /man/AHP.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calc_functions.R 3 | \name{AHP} 4 | \alias{AHP} 5 | \title{Select best model using analytic hyrarchy process} 6 | \usage{ 7 | AHP( 8 | fitindices, 9 | relative_importance = c(AIC = 0.2323, AWE = 0.1129, BIC = 0.2525, CLC = 0.0922, KIC = 10 | 0.3101) 11 | ) 12 | } 13 | \arguments{ 14 | \item{fitindices}{A matrix or data.frame of fit indices, with colnames 15 | corresponding to the indices named in \code{relative_importance}.} 16 | 17 | \item{relative_importance}{A named numeric vector. Names should correspond to 18 | columns in \code{fitindices}, and values represent the relative weight 19 | assigned to the corresponding fit index. The default value corresponds to the 20 | fit indices and weights assigned by Akogul and Erisoglu. To assign uniform 21 | weights (i.e., each index is weighted equally), assign an equal value to all.} 22 | } 23 | \value{ 24 | Numeric. 25 | } 26 | \description{ 27 | Integrates information from several fit indices, and selects the best model. 28 | } 29 | \details{ 30 | Many fit indices are available for model selection. Following 31 | the procedure developed by Akogul and Erisoglu (2017), this function 32 | integrates information from several fit indices, and selects the best model, 33 | using Saaty's (1990) Analytic Hierarchy Process (AHP). Conceptually, the 34 | process consists of the following steps: 35 | \enumerate{ 36 | \item For each fit index, calculate the amount of support provided for each 37 | model, relative to the other models. 38 | \item From these comparisons, obtain a "priority vector" of the amount of 39 | support for each model. 40 | \item Compute a weighted average of the priority vectors for all fit indeces, 41 | with weights based on a simulation study examining each fit index' ability to 42 | recover the correct number of clusters (Akogul & Erisoglu, 2016). 43 | \item Select the model with the highest weighted average priority. 44 | } 45 | } 46 | \examples{ 47 | iris[,1:4] \%>\% 48 | estimate_profiles(1:4) \%>\% 49 | get_fit() \%>\% 50 | AHP() 51 | } 52 | \author{ 53 | Caspar J. van Lissa 54 | } 55 | -------------------------------------------------------------------------------- /man/as.tidyLPA.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/as.tidyLPA.r 3 | \name{as.tidyLPA} 4 | \alias{as.tidyLPA} 5 | \title{Convert Mplus output to object of class 'tidyLPA'} 6 | \usage{ 7 | as.tidyLPA(modelList) 8 | } 9 | \arguments{ 10 | \item{modelList}{A list of class \code{modelList}, as generated by 11 | \code{\link[MplusAutomation]{readModels}}.} 12 | } 13 | \value{ 14 | A list of class \code{tidyLPA}. 15 | } 16 | \description{ 17 | Takes a list of Mplus output files of class \code{modelList}, 18 | containing only mixture models with a single categorical latent variable, and 19 | converts it to an object of class \code{tidyLPA}. 20 | } 21 | \examples{ 22 | \dontrun{ 23 | library(MplusAutomation) 24 | createMixtures(classes = 1:4, filename_stem = "cars", 25 | model_overall = "wt ON drat;", 26 | model_class_specific = "wt; qsec;", 27 | rdata = mtcars, 28 | usevariables = c("wt", "qsec", "drat"), 29 | OUTPUT = "standardized") 30 | runModels(replaceOutfile = "modifiedDate") 31 | cars_results <- readModels(filefilter = "cars") 32 | results_tidyLPA <- as.tidyLPA(cars_results) 33 | results_tidyLPA 34 | plot(results_tidyLPA) 35 | plot_profiles(results_tidyLPA) # Throws error; missing column 'Classes' 36 | } 37 | } 38 | \author{ 39 | Caspar J. van Lissa 40 | } 41 | \keyword{internal} 42 | -------------------------------------------------------------------------------- /man/calc_lrt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calc_functions.R 3 | \name{calc_lrt} 4 | \alias{calc_lrt} 5 | \title{Lo-Mendell-Rubin likelihood ratio test} 6 | \usage{ 7 | calc_lrt(n, null_ll, null_param, null_classes, alt_ll, alt_param, alt_classes) 8 | } 9 | \arguments{ 10 | \item{n}{Integer. Sample size} 11 | 12 | \item{null_ll}{Numeric. Log-likelihood of the null model.} 13 | 14 | \item{null_param}{Integer. Number of parameters of the null model.} 15 | 16 | \item{null_classes}{Integer. Number of classes of the null model.} 17 | 18 | \item{alt_ll}{Numeric. Log-likelihood of the alternative model.} 19 | 20 | \item{alt_param}{Integer. Number of parameters of the alternative model.} 21 | 22 | \item{alt_classes}{Integer. Number of classes of the alternative model.} 23 | } 24 | \value{ 25 | A numeric vector containing the likelihood ratio LR, the ad-hoc 26 | corrected LMR, degrees of freedom, and the LMR p-value. 27 | } 28 | \description{ 29 | Implements the ad-hoc adjusted likelihood ratio test (LRT) 30 | described in Formula 15 of Lo, Mendell, & Rubin (2001), or LMR LRT. 31 | } 32 | \examples{ 33 | calc_lrt(150L, -741.02, 8, 1, -488.91, 13, 2) 34 | } 35 | \references{ 36 | Lo Y, Mendell NR, Rubin DB. Testing the number of components in a 37 | normal mixture. Biometrika. 2001;88(3):767–778. doi:10.1093/biomet/88.3.767 38 | } 39 | -------------------------------------------------------------------------------- /man/compare_solutions.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/compare-solutions.R 3 | \name{compare_solutions} 4 | \alias{compare_solutions} 5 | \title{Compare latent profile models} 6 | \usage{ 7 | compare_solutions(x, statistics = "BIC") 8 | } 9 | \arguments{ 10 | \item{x}{An object of class 'tidyLPA'.} 11 | 12 | \item{statistics}{Character vector. Which statistics to examine for 13 | determining the optimal model. Defaults to 'BIC'.} 14 | } 15 | \value{ 16 | An object of class 'bestLPA' and 'list', containing a tibble of fits 17 | 'fits', a named vector 'best', indicating which model fit best according to 18 | each fit index, a numeric vector 'AHP' indicating the best model according to 19 | the \code{\link{AHP}}, an object 'plot' of class 'ggplot', and a numeric 20 | vector 'statistics' corresponding to argument of the same name. 21 | } 22 | \description{ 23 | Takes an object of class 'tidyLPA', containing multiple latent profile models 24 | with different number of classes or model specifications, and helps select 25 | the optimal number of classes and model specification. 26 | } 27 | \examples{ 28 | iris_subset <- sample(nrow(iris), 20) # so examples execute quickly 29 | results <- iris \%>\% 30 | subset(select = c("Sepal.Length", "Sepal.Width", 31 | "Petal.Length", "Petal.Width")) \%>\% 32 | estimate_profiles(1:3) \%>\% 33 | compare_solutions() 34 | } 35 | \author{ 36 | Caspar J. van Lissa 37 | } 38 | -------------------------------------------------------------------------------- /man/curry_mac.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data-mac.R 3 | \docType{data} 4 | \name{curry_mac} 5 | \alias{curry_mac} 6 | \title{Simulated MAC data} 7 | \format{ 8 | A data.frame with 1392 rows and 42 variables. 9 | } 10 | \usage{ 11 | data(curry_mac) 12 | } 13 | \description{ 14 | This simulated dataset, based on Curry et al., 2019, contains data on moral 15 | relevance and judgment across the seven domains of the Morality As 16 | Cooperation scale. 17 | } 18 | \details{ 19 | \tabular{lll}{ 20 | \strong{sex} \tab \code{factor} \tab Self-identified sex of participants, Male, Female, or Transgendered.\cr 21 | \strong{age_years} \tab \code{numeric} \tab Participants' age in years.\cr 22 | \strong{KinshipR} \tab \code{numeric} \tab Mean score of moral relevance, kinship subscale.\cr 23 | \strong{MutualismR} \tab \code{numeric} \tab Mean score of moral relevance, mutualism subscale.\cr 24 | \strong{ExchangeR} \tab \code{numeric} \tab Mean score of moral relevance, exchange subscale.\cr 25 | \strong{HawkR} \tab \code{numeric} \tab Mean score of moral relevance, hawk subscale.\cr 26 | \strong{DoveR} \tab \code{numeric} \tab Mean score of moral relevance, dove subscale.\cr 27 | \strong{DivisionR} \tab \code{numeric} \tab Mean score of moral relevance, division subscale.\cr 28 | \strong{PossessionR} \tab \code{numeric} \tab Mean score of moral relevance, possession subscale.\cr 29 | \strong{KinshipJ} \tab \code{numeric} \tab Mean score of moral judgment, kinship subscale.\cr 30 | \strong{MutualismJ} \tab \code{numeric} \tab Mean score of moral judgment, mutualism subscale.\cr 31 | \strong{ExchangeJ} \tab \code{numeric} \tab Mean score of moral judgment, exchange subscale.\cr 32 | \strong{HawkJ} \tab \code{numeric} \tab Mean score of moral judgment, hawk subscale.\cr 33 | \strong{DoveJ} \tab \code{numeric} \tab Mean score of moral judgment, dove subscale.\cr 34 | \strong{DivisionJ} \tab \code{numeric} \tab Mean score of moral judgment, division subscale.\cr 35 | \strong{PossessionJ} \tab \code{numeric} \tab Mean score of moral judgment, possession subscale. 36 | } 37 | } 38 | \references{ 39 | Curry, O. S., Jones Chesters, M., & Van Lissa, C. J. (2019). Mapping morality with a compass: Testing the theory of ‘morality-as-cooperation’ with a new questionnaire. Journal of Research in Personality, 78, 106–124. 40 | \doi{10.1016/j.jrp.2018.10.008} 41 | } 42 | \keyword{datasets} 43 | -------------------------------------------------------------------------------- /man/empathy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/empathy.R 3 | \docType{data} 4 | \name{empathy} 5 | \alias{empathy} 6 | \title{Simulated empathy data} 7 | \format{ 8 | A data frame with 467 rows and 13 variables. 9 | } 10 | \usage{ 11 | data(empathy) 12 | } 13 | \description{ 14 | This simulated dataset, based on Van Lissa et al., 2014, contains six annual 15 | assessments of adolescents' mean scores on the empathic concern and 16 | perspective taking subscales of the Interpersonal Reactivity Index 17 | (Davis, 1983). The first measurement wave occurred when adolescents were, on 18 | average, 13 years old, and the last one when they were 18 years old. 19 | } 20 | \details{ 21 | \tabular{lll}{ 22 | \strong{ec1} \tab \code{numeric} \tab Mean score of empathic concern in 23 | wave 1\cr 24 | \strong{ec2} \tab \code{numeric} \tab Mean score of empathic concern in 25 | wave 2\cr 26 | \strong{ec3} \tab \code{numeric} \tab Mean score of empathic concern in 27 | wave 3\cr 28 | \strong{ec4} \tab \code{numeric} \tab Mean score of empathic concern in 29 | wave 4\cr 30 | \strong{ec5} \tab \code{numeric} \tab Mean score of empathic concern in 31 | wave 5\cr 32 | \strong{ec6} \tab \code{numeric} \tab Mean score of empathic concern in 33 | wave 6\cr 34 | \strong{pt1} \tab \code{numeric} \tab Mean score of perspective taking in 35 | wave 1\cr 36 | \strong{pt2} \tab \code{numeric} \tab Mean score of perspective taking in 37 | wave 2\cr 38 | \strong{pt3} \tab \code{numeric} \tab Mean score of perspective taking in 39 | wave 3\cr 40 | \strong{pt4} \tab \code{numeric} \tab Mean score of perspective taking in 41 | wave 4\cr 42 | \strong{pt5} \tab \code{numeric} \tab Mean score of perspective taking in 43 | wave 5\cr 44 | \strong{pt6} \tab \code{numeric} \tab Mean score of perspective taking in 45 | wave 6\cr 46 | \strong{sex} \tab \code{factor} \tab Adolescent sex; M = male, F = female. 47 | } 48 | } 49 | \references{ 50 | Van Lissa, C. J., Hawk, S. T., Branje, S. J., Koot, H. M., 51 | Van Lier, P. A., & Meeus, W. H. (2014). Divergence Between Adolescent and 52 | Parental Perceptions of Conflict in Relationship to Adolescent Empathy 53 | Development. Journal of Youth and Adolescence, (Journal Article), 1–14. 54 | \doi{10.1007/s10964-014-0152-5} 55 | } 56 | \keyword{datasets} 57 | -------------------------------------------------------------------------------- /man/estimate_profiles.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-profiles.R 3 | \name{estimate_profiles} 4 | \alias{estimate_profiles} 5 | \title{Estimate latent profiles} 6 | \usage{ 7 | estimate_profiles( 8 | df, 9 | n_profiles, 10 | models = NULL, 11 | variances = "equal", 12 | covariances = "zero", 13 | package = "mclust", 14 | select_vars = NULL, 15 | ... 16 | ) 17 | } 18 | \arguments{ 19 | \item{df}{data.frame of numeric data; continuous indicators are required for 20 | mixture modeling.} 21 | 22 | \item{n_profiles}{Integer vector of the number of profiles (or mixture 23 | components) to be estimated.} 24 | 25 | \item{models}{Integer vector. Set to \code{NULL} by default, and models are 26 | constructed from the \code{variances} and \code{covariances} arguments. See 27 | \code{Details} for the six models available in tidyLPA.} 28 | 29 | \item{variances}{Character vector. Specifies which variance components to 30 | estimate. Defaults to "equal" (constrain variances across profiles); the 31 | other option is "varying" (estimate variances freely across profiles). Each 32 | element of this vector refers to one of the models you wish to run.} 33 | 34 | \item{covariances}{Character vector. Specifies which covariance components to 35 | estimate. Defaults to "zero" (do not estimate covariances; this corresponds 36 | to an assumption of conditional independence of the indicators); other 37 | options are "equal" (estimate covariances between items, constrained across 38 | profiles), and "varying" (free covariances across profiles).} 39 | 40 | \item{package}{Character. Which package to use; 'OpenMx', 'mclust', or 41 | 'MplusAutomation' (requires Mplus to be installed). Default: 'OpenMx'.} 42 | 43 | \item{select_vars}{Character. Optional vector of variable names in \code{df}, 44 | to be used for model estimation. Defaults to \code{NULL}, which means all 45 | variables in \code{df} are used.} 46 | 47 | \item{...}{Additional arguments are passed to the estimating function; i.e., 48 | \code{\link[OpenMx]{mxRun}}, 49 | \code{\link[mclust]{Mclust}}, or \code{\link[MplusAutomation]{mplusModeler}}.} 50 | } 51 | \value{ 52 | A list of class 'tidyLPA'. 53 | } 54 | \description{ 55 | Estimates latent profiles (finite mixture models) using either 56 | the open source package \code{\link[mclust:Mclust]{mclust}} or 57 | \code{[OpenMx:mxModel]{OpenMx}}, or the commercial program Mplus (using the 58 | R-interface of \code{\link[MplusAutomation:mplusModeler]{MplusAutomation}}). 59 | } 60 | \details{ 61 | Six models are currently available in tidyLPA, corresponding to the 62 | most common requirements. All models estimate the observed variable means 63 | for each class. The remaining parameters are: 64 | \enumerate{ 65 | \item Equal variances across classes; no covariances between observed 66 | variables 67 | \item Varying variances across classes; no covariances between observed 68 | variables 69 | \item Equal variances and equal covariances across classes 70 | \item Varying variances and equal covariances (not available for \code{package = 'mclust'}) 71 | \item Equal variances and varying covariances (not available for \code{package = 'mclust'}) 72 | \item Varying variances and varying covariances 73 | } 74 | 75 | Two interfaces are available to estimate these models; specify their numbers 76 | in the \code{models} argument (e.g., \code{models = 1}, or 77 | \code{models = c(1, 2, 3)}), or specify the variances/covariances to be 78 | estimated (e.g.,: \code{variances = c("equal", "varying"), covariances = 79 | c("zero", "equal")}). Note that when \code{package = 'mclust'} is used, 80 | \code{models = c(4, 5)} are not available. Use \code{package = 'OpenMx'} or 81 | \code{package = 'Mplus'} to estimate these models. 82 | } 83 | \examples{ 84 | # to make example run more quickly 85 | iris_sample <- iris[c(1:10, 51:60, 101:114), ] 86 | 87 | # Example 1: 88 | iris_sample \%>\% 89 | subset(select = c("Sepal.Length", "Sepal.Width", 90 | "Petal.Length")) \%>\% 91 | estimate_profiles(3) 92 | 93 | \donttest{ 94 | # Example 2: 95 | iris \%>\% 96 | subset(select = c("Sepal.Length", "Sepal.Width", 97 | "Petal.Length")) \%>\% 98 | estimate_profiles(n_profiles = 1:4, models = 1:3) 99 | 100 | # Example 3: 101 | iris_sample \%>\% 102 | subset(select = c("Sepal.Length", "Sepal.Width", 103 | "Petal.Length")) \%>\% 104 | estimate_profiles(n_profiles = 1:4, variances = c("equal", "varying"), 105 | covariances = c("zero", "zero")) 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /man/estimate_profiles_mclust.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-profiles-mclust.R 3 | \name{estimate_profiles_mclust} 4 | \alias{estimate_profiles_mclust} 5 | \title{Estimate latent profiles using mclust} 6 | \usage{ 7 | estimate_profiles_mclust(df, n_profiles, model_numbers, select_vars, ...) 8 | } 9 | \arguments{ 10 | \item{df}{data.frame with two or more columns with continuous variables} 11 | 12 | \item{n_profiles}{Numeric vector. The number of profiles (or mixture 13 | components) to be estimated. Each number in the vector corresponds to an 14 | analysis with that many mixture components.} 15 | 16 | \item{model_numbers}{Numeric vector. Numbers of the models to be estimated. 17 | See \code{\link{estimate_profiles}} for a description of the models available 18 | in tidyLPA.} 19 | 20 | \item{select_vars}{Character. Optional vector of variable names in \code{df}, 21 | to be used for model estimation. Defaults to \code{NULL}, which means all 22 | variables in \code{df} are used.} 23 | 24 | \item{...}{Parameters passed directly to \code{\link[mclust]{Mclust}}. See 25 | the documentation of \code{\link[mclust]{Mclust}}.} 26 | } 27 | \value{ 28 | An object of class 'tidyLPA' and 'list' 29 | } 30 | \description{ 31 | Estimates latent profiles (finite mixture models) using the open source 32 | package \code{\link[mclust:Mclust]{mclust}}. 33 | } 34 | \author{ 35 | Caspar J. van Lissa 36 | } 37 | -------------------------------------------------------------------------------- /man/estimate_profiles_mplus2.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-profiles-mplus.R 3 | \name{estimate_profiles_mplus2} 4 | \alias{estimate_profiles_mplus2} 5 | \title{Estimate latent profiles using Mplus} 6 | \usage{ 7 | estimate_profiles_mplus2( 8 | df, 9 | n_profiles, 10 | model_numbers, 11 | select_vars, 12 | ..., 13 | keepfiles = FALSE 14 | ) 15 | } 16 | \arguments{ 17 | \item{df}{data.frame with two or more columns with continuous variables} 18 | 19 | \item{n_profiles}{Numeric vector. The number of profiles (or mixture 20 | components) to be estimated. Each number in the vector corresponds to an 21 | analysis with that many mixture components.} 22 | 23 | \item{model_numbers}{Numeric vector. Numbers of the models to be estimated. 24 | See \code{\link{estimate_profiles}} for a description of the models available 25 | in tidyLPA.} 26 | 27 | \item{select_vars}{Character. Optional vector of variable names in \code{df}, 28 | to be used for model estimation. Defaults to \code{NULL}, which means all 29 | variables in \code{df} are used.} 30 | 31 | \item{...}{Parameters passed directly to 32 | \code{\link[MplusAutomation]{mplusModeler}}. See the documentation of 33 | \code{\link[MplusAutomation]{mplusModeler}}.} 34 | 35 | \item{keepfiles}{Logical. Whether to retain the files created by 36 | \code{mplusModeler} (e.g., for future reference, or to manually edit them).} 37 | } 38 | \value{ 39 | An object of class 'tidyLPA' and 'list' 40 | } 41 | \description{ 42 | Estimates latent profiles (finite mixture models) using the commercial 43 | program Mplus, through the R-interface of 44 | \code{\link[MplusAutomation:mplusModeler]{MplusAutomation}}. 45 | } 46 | \author{ 47 | Caspar J. van Lissa 48 | } 49 | -------------------------------------------------------------------------------- /man/estimate_profiles_openmx.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-profiles-openmx.R 3 | \name{estimate_profiles_openmx} 4 | \alias{estimate_profiles_openmx} 5 | \title{Estimate latent profiles using OpenMx} 6 | \usage{ 7 | estimate_profiles_openmx(df, n_profiles, model_numbers, select_vars, ...) 8 | } 9 | \arguments{ 10 | \item{df}{data.frame with two or more columns with continuous variables} 11 | 12 | \item{n_profiles}{Numeric vector. The number of profiles (or mixture 13 | components) to be estimated. Each number in the vector corresponds to an 14 | analysis with that many mixture components.} 15 | 16 | \item{model_numbers}{Numeric vector. Numbers of the models to be estimated. 17 | See \code{\link{estimate_profiles}} for a description of the models available 18 | in tidyLPA.} 19 | 20 | \item{select_vars}{Character. Optional vector of variable names in \code{df}, 21 | to be used for model estimation. Defaults to \code{NULL}, which means all 22 | variables in \code{df} are used.} 23 | 24 | \item{...}{Parameters passed to and from functions.} 25 | } 26 | \value{ 27 | An object of class 'tidyLPA' and 'list' 28 | } 29 | \description{ 30 | Estimates latent profiles (finite mixture models) using the R-package OpenMx. 31 | } 32 | \author{ 33 | Caspar J. van Lissa 34 | } 35 | -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/man/figures/README-unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/man/figures/README-unnamed-chunk-4-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/man/figures/README-unnamed-chunk-5-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-6-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/man/figures/README-unnamed-chunk-6-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-7-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-edu/tidyLPA/b303727f636a193e47d0f8f09ac0ec8c1e493d43/man/figures/README-unnamed-chunk-7-1.png -------------------------------------------------------------------------------- /man/get_data.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-profiles.R 3 | \name{get_data} 4 | \alias{get_data} 5 | \alias{get_data.tidyLPA} 6 | \alias{get_data.tidyProfile} 7 | \title{Get data from objects generated by tidyLPA} 8 | \usage{ 9 | get_data(x, ...) 10 | 11 | \method{get_data}{tidyLPA}(x, ...) 12 | 13 | \method{get_data}{tidyProfile}(x, ...) 14 | } 15 | \arguments{ 16 | \item{x}{An object generated by tidyLPA.} 17 | 18 | \item{...}{further arguments to be passed to or from other methods. They are 19 | ignored in this function.} 20 | } 21 | \value{ 22 | If one model is fit, the data is returned in wide format as a tibble. 23 | If more than one model is fit, the data is returned in long form. See the 24 | examples. 25 | } 26 | \description{ 27 | Get data from objects generated by tidyLPA. 28 | } 29 | \section{Methods (by class)}{ 30 | \itemize{ 31 | \item \code{get_data(tidyLPA)}: Get data for a latent profile analysis with multiple 32 | numbers of classes and models, of class 'tidyLPA'. 33 | 34 | \item \code{get_data(tidyProfile)}: Get data for a single latent profile analysis object, 35 | of class 'tidyProfile'. 36 | 37 | }} 38 | \examples{ 39 | \dontrun{ 40 | if(interactive()){ 41 | library(dplyr) 42 | # the data is returned in wide form 43 | results <- iris \%>\% 44 | select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) \%>\% 45 | estimate_profiles(3) 46 | get_data(results) 47 | 48 | # note that if more than one model is fit, the data is returned in long form 49 | results1 <- iris \%>\% 50 | select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) \%>\% 51 | estimate_profiles(c(3, 4)) 52 | get_data(results1) 53 | } 54 | } 55 | } 56 | \author{ 57 | Caspar J. van Lissa 58 | } 59 | -------------------------------------------------------------------------------- /man/get_estimates.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-profiles.R 3 | \name{get_estimates} 4 | \alias{get_estimates} 5 | \alias{get_estimates.tidyLPA} 6 | \alias{get_estimates.tidyProfile} 7 | \title{Get estimates from objects generated by tidyLPA} 8 | \usage{ 9 | get_estimates(x, ...) 10 | 11 | \method{get_estimates}{tidyLPA}(x, ...) 12 | 13 | \method{get_estimates}{tidyProfile}(x, ...) 14 | } 15 | \arguments{ 16 | \item{x}{An object generated by tidyLPA.} 17 | 18 | \item{...}{further arguments to be passed to or from other methods. They are 19 | ignored in this function.} 20 | } 21 | \value{ 22 | A tibble. 23 | } 24 | \description{ 25 | Get estimates from objects generated by tidyLPA. 26 | } 27 | \section{Methods (by class)}{ 28 | \itemize{ 29 | \item \code{get_estimates(tidyLPA)}: Get estimates for a latent profile analysis with 30 | multiple numbers of classes and models, of class 'tidyLPA'. 31 | 32 | \item \code{get_estimates(tidyProfile)}: Get estimates for a single latent profile analysis 33 | object, of class 'tidyProfile'. 34 | 35 | }} 36 | \examples{ 37 | \dontrun{ 38 | if(interactive()){ 39 | results <- iris \%>\% 40 | select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) \%>\% 41 | estimate_profiles(3) 42 | get_estimates(results) 43 | get_estimates(results[[1]]) 44 | } 45 | } 46 | } 47 | \author{ 48 | Caspar J. van Lissa 49 | } 50 | -------------------------------------------------------------------------------- /man/get_fit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-profiles.R 3 | \name{get_fit} 4 | \alias{get_fit} 5 | \alias{get_fit.tidyLPA} 6 | \alias{get_fit.tidyProfile} 7 | \title{Get fit indices from objects generated by tidyLPA} 8 | \usage{ 9 | get_fit(x, ...) 10 | 11 | \method{get_fit}{tidyLPA}(x, ...) 12 | 13 | \method{get_fit}{tidyProfile}(x, ...) 14 | } 15 | \arguments{ 16 | \item{x}{An object generated by tidyLPA.} 17 | 18 | \item{...}{further arguments to be passed to or from other methods. They are 19 | ignored in this function.} 20 | } 21 | \value{ 22 | A tibble. Learn more at https://data-edu.github.io/tidyLPA/articles/Introduction_to_tidyLPA.html#getting-fit-statistics 23 | } 24 | \description{ 25 | Get fit indices from objects generated by tidyLPA. 26 | } 27 | \section{Methods (by class)}{ 28 | \itemize{ 29 | \item \code{get_fit(tidyLPA)}: Get fit indices for a latent profile analysis with 30 | multiple numbers of classes and models, of class 'tidyLPA'. 31 | 32 | \item \code{get_fit(tidyProfile)}: Get fit indices for a single latent profile analysis 33 | object, of class 'tidyProfile'. 34 | 35 | }} 36 | \examples{ 37 | \dontrun{ 38 | if(interactive()){ 39 | results <- iris \%>\% 40 | select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) \%>\% 41 | estimate_profiles(3) 42 | get_fit(results) 43 | get_fit(results[[1]]) 44 | } 45 | } 46 | } 47 | \author{ 48 | Caspar J. van Lissa 49 | } 50 | -------------------------------------------------------------------------------- /man/id_edu.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/id_edu.R 3 | \docType{data} 4 | \name{id_edu} 5 | \alias{id_edu} 6 | \title{Simulated identity data} 7 | \format{ 8 | A data frame with 443 rows and 16 variables. 9 | } 10 | \usage{ 11 | data(id_edu) 12 | } 13 | \description{ 14 | This simulated dataset, based on Crochetti et al., 2014, contains five annual 15 | assessments of adolescents' mean scores on the commitment, exploration (in 16 | depth), and reconsideration subscales of the Utrecht-Management of Identity 17 | Commitments Scale (Crocetti et al., 2008). The scores reported here reflect 18 | the educational identity subscales of this instrument. The first measurement 19 | wave occurred when adolescents were, on 20 | average, 14 years old, and the last one when they were 18 years old. 21 | } 22 | \details{ 23 | \tabular{lll}{ 24 | \strong{com1} \tab \code{numeric} \tab Mean score 25 | of educational commitment in 26 | wave 1\cr 27 | \strong{exp1} \tab \code{numeric} \tab Mean score 28 | of educational exploration in 29 | wave 1\cr 30 | \strong{rec1} \tab \code{numeric} \tab Mean score 31 | of educational reconsideration in 32 | wave 1\cr 33 | \strong{com2} \tab \code{numeric} \tab Mean score 34 | of educational commitment in 35 | wave 2\cr 36 | \strong{exp2} \tab \code{numeric} \tab Mean score 37 | of educational exploration in 38 | wave 2\cr 39 | \strong{rec2} \tab \code{numeric} \tab Mean score 40 | of educational reconsideration in 41 | wave 2\cr 42 | \strong{com3} \tab \code{numeric} \tab Mean score 43 | of educational commitment in 44 | wave 3\cr 45 | \strong{exp3} \tab \code{numeric} \tab Mean score 46 | of educational exploration in 47 | wave 3\cr 48 | \strong{rec3} \tab \code{numeric} \tab Mean score 49 | of educational reconsideration in 50 | wave 3\cr 51 | \strong{com4} \tab \code{numeric} \tab Mean score 52 | of educational commitment in 53 | wave 4\cr 54 | \strong{exp4} \tab \code{numeric} \tab Mean score 55 | of educational exploration in 56 | wave 4\cr 57 | \strong{rec4} \tab \code{numeric} \tab Mean score 58 | of educational reconsideration in 59 | wave 4\cr 60 | \strong{com5} \tab \code{numeric} \tab Mean score 61 | of educational commitment in 62 | wave 5\cr 63 | \strong{exp5} \tab \code{numeric} \tab Mean score 64 | of educational exploration in 65 | wave 5\cr 66 | \strong{rec5} \tab \code{numeric} \tab Mean score 67 | of educational reconsideration in 68 | wave 5\cr 69 | \strong{sex} \tab \code{factor} \tab Adolescent sex; M = male, F = female. 70 | } 71 | } 72 | \references{ 73 | Crocetti, E., Klimstra, T. A., Hale, W. W., Koot, H. M., & 74 | Meeus, W. (2013). Impact of early adolescent externalizing problem behaviors 75 | on identity development in middle to late adolescence: A prospective 7-year 76 | longitudinal study. Journal of Youth and Adolescence, 42(11), 1745-1758. 77 | \doi{10.1007/s10964-013-9924-6} 78 | } 79 | \keyword{datasets} 80 | -------------------------------------------------------------------------------- /man/pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \title{Pipe} 6 | \arguments{ 7 | \item{lhs, rhs}{An object and a function to apply to it} 8 | } 9 | \description{ 10 | tidyLPA suggests using the pipe operator, \code{\%>\%}, from the magrittr 11 | package (imported here from the dplyr package). 12 | } 13 | \examples{ 14 | # Instead of 15 | subset(iris, select = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")) 16 | # you can write 17 | iris \%>\% 18 | subset(select = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")) 19 | } 20 | -------------------------------------------------------------------------------- /man/pisaUSA15.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data-documentation.R 3 | \docType{data} 4 | \name{pisaUSA15} 5 | \alias{pisaUSA15} 6 | \title{student questionnaire data with four variables from the 2015 PISA for students in the United States} 7 | \format{ 8 | Data frame with columns 9 | #' \describe{ 10 | \item{broad_interest}{composite measure of students' self reported broad interest} 11 | \item{enjoyment}{composite measure of students' self reported enjoyment} 12 | \item{instrumental_mot}{composite measure of students' self reported instrumental motivation} 13 | \item{self_efficacy}{composite measure of students' self reported self efficacy} 14 | ... 15 | } 16 | } 17 | \source{ 18 | http://www.oecd.org/pisa/data/ 19 | } 20 | \usage{ 21 | pisaUSA15 22 | } 23 | \description{ 24 | student questionnaire data with four variables from the 2015 PISA for students in the United States 25 | } 26 | \keyword{datasets} 27 | -------------------------------------------------------------------------------- /man/poms.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calc_functions.R 3 | \name{poms} 4 | \alias{poms} 5 | \title{Apply POMS-coding to data} 6 | \usage{ 7 | poms(data) 8 | } 9 | \arguments{ 10 | \item{data}{A data.frame.} 11 | } 12 | \value{ 13 | A data.frame. 14 | } 15 | \description{ 16 | Takes in a data.frame, and applies POMS (proportion of of maximum)-coding to 17 | the numeric columns. 18 | } 19 | \examples{ 20 | data <- data.frame(a = c(1, 2, 2, 4, 1, 6), 21 | b = c(6, 6, 3, 5, 3, 4), 22 | c = c("a", "b", "b", "t", "f", "g")) 23 | poms(data) 24 | } 25 | \author{ 26 | Caspar J. van Lissa 27 | } 28 | -------------------------------------------------------------------------------- /man/print.tidyLPA.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-profiles.R 3 | \name{print.tidyLPA} 4 | \alias{print.tidyLPA} 5 | \title{Print tidyLPA} 6 | \usage{ 7 | \method{print}{tidyLPA}( 8 | x, 9 | stats = c("AIC", "BIC", "Entropy", "prob_min", "prob_max", "n_min", "n_max", "BLRT_p"), 10 | digits = 2, 11 | na.print = "", 12 | ... 13 | ) 14 | } 15 | \arguments{ 16 | \item{x}{An object of class 'tidyLPA'.} 17 | 18 | \item{stats}{Character vector. Statistics to be printed. Default: 19 | c("AIC", "BIC", "Entropy", "prob_min", "prob_max", "n_min", "n_max", "BLRT_p" 20 | ).} 21 | 22 | \item{digits}{minimal number of significant digits, see 23 | \code{\link[base]{print.default}}.} 24 | 25 | \item{na.print}{a character string which is used to indicate NA values in 26 | printed output, or NULL. See \code{\link[base]{print.default}}.} 27 | 28 | \item{...}{further arguments to be passed to or from other methods. They are 29 | ignored in this function.} 30 | } 31 | \description{ 32 | S3 method 'print' for class 'tidyLPA'. 33 | } 34 | \examples{ 35 | \dontrun{ 36 | if(interactive()){ 37 | iris \%>\% 38 | select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) \%>\% 39 | estimate_profiles(3) 40 | } 41 | } 42 | } 43 | \author{ 44 | Caspar J. van Lissa 45 | } 46 | -------------------------------------------------------------------------------- /man/print.tidyProfile.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate-profiles.R 3 | \name{print.tidyProfile} 4 | \alias{print.tidyProfile} 5 | \title{Print tidyProfile} 6 | \usage{ 7 | \method{print}{tidyProfile}(x, digits = 2, na.print = "", ...) 8 | } 9 | \arguments{ 10 | \item{x}{An object of class 'tidyProfile'.} 11 | 12 | \item{digits}{minimal number of significant digits, see 13 | \code{\link[base]{print.default}}.} 14 | 15 | \item{na.print}{a character string which is used to indicate NA values in 16 | printed output, or NULL. See \code{\link[base]{print.default}}.} 17 | 18 | \item{...}{further arguments to be passed to or from other methods. They are 19 | ignored in this function.} 20 | } 21 | \description{ 22 | S3 method 'print' for class 'tidyProfile'. 23 | } 24 | \examples{ 25 | \dontrun{ 26 | if(interactive()){ 27 | tmp <- iris \%>\% 28 | select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) \%>\% 29 | estimate_profiles(3) 30 | tmp[[2]] 31 | } 32 | } 33 | } 34 | \author{ 35 | Caspar J. van Lissa 36 | } 37 | -------------------------------------------------------------------------------- /man/reexports.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot-bivariate.R, R/plot-mixture_densities.R, 3 | % R/plot-profiles.R 4 | \docType{import} 5 | \name{reexports} 6 | \alias{reexports} 7 | \alias{plot_bivariate} 8 | \alias{plot_density} 9 | \alias{plot_profiles} 10 | \title{Objects exported from other packages} 11 | \keyword{internal} 12 | \description{ 13 | These objects are imported from other packages. Follow the links 14 | below to see their documentation. 15 | 16 | \describe{ 17 | \item{tidySEM}{\code{\link[tidySEM]{plot_bivariate}}, \code{\link[tidySEM]{plot_density}}, \code{\link[tidySEM]{plot_profiles}}} 18 | }} 19 | 20 | -------------------------------------------------------------------------------- /man/single_imputation.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/missing_data.R 3 | \name{single_imputation} 4 | \alias{single_imputation} 5 | \title{Apply single imputation to data} 6 | \usage{ 7 | single_imputation(x, method = "imputeData") 8 | } 9 | \arguments{ 10 | \item{x}{A data.frame or matrix.} 11 | 12 | \item{method}{Character. Imputation method to apply, Default: 'imputeData'} 13 | } 14 | \value{ 15 | A data.frame 16 | } 17 | \description{ 18 | This function accommodates several methods for single imputation 19 | of data. Currently, the following methods are defined: 20 | \itemize{ 21 | \item{"imputeData"}{Applies the mclust native imputation function 22 | \code{\link[mclust]{imputeData}}} 23 | \item{"missForest"}{Applies non-parameteric, random-forest based data 24 | imputation using \code{\link[missForest]{missForest}}. Radom forests can 25 | accommodate any complex interactions and non-linear relations in the data. My 26 | simulation studies indicate that this method is preferable to mclust's 27 | \code{imputeData} (see examples).} 28 | } 29 | } 30 | \examples{ 31 | \dontrun{ 32 | library(ggplot2) 33 | library(missForest) 34 | library(mclust) 35 | 36 | dm <- 2 37 | k <- 3 38 | n <- 100 39 | V <- 4 40 | 41 | # Example of one simulation 42 | class <- sample.int(k, n, replace = TRUE) 43 | dat <- matrix(rnorm(n*V, mean = (rep(class, each = V)-1)*dm), nrow = n, 44 | ncol = V, byrow = TRUE) 45 | results <- estimate_profiles(data.frame(dat), 1:5) 46 | plot_profiles(results) 47 | compare_solutions(results) 48 | 49 | # Simulation for parametric data (i.e., all assumptions of latent profile 50 | # analysis met) 51 | simulation <- replicate(100, { 52 | class <- sample.int(k, n, replace = TRUE) 53 | dat <- matrix(rnorm(n*V, mean = (rep(class, each = V)-1)*dm), nrow = n, 54 | ncol = V, byrow = TRUE) 55 | 56 | d <- prodNA(dat) 57 | 58 | d_mf <- missForest(d)$ximp 59 | m_mf <- Mclust(d_mf, G = 3, "EEI") 60 | d_im <- imputeData(d, verbose = FALSE) 61 | m_im <- Mclust(d_im, G = 3, "EEI") 62 | 63 | class_tabl_mf <- sort(prop.table(table(class, m_mf$classification)), 64 | decreasing = TRUE)[1:3] 65 | class_tabl_im <- sort(prop.table(table(class, m_im$classification)), 66 | decreasing = TRUE)[1:3] 67 | c(sum(class_tabl_mf), sum(class_tabl_im)) 68 | }) 69 | # Performance on average 70 | rowMeans(simulation) 71 | # Performance SD 72 | colSD(t(simulation)) 73 | # Plot shows slight advantage for missForest 74 | plotdat <- data.frame(accuracy = as.vector(simulation), model = 75 | rep(c("mf", "im"), n)) 76 | ggplot(plotdat, aes(x = accuracy, colour = model))+geom_density() 77 | 78 | # Simulation for real data (i.e., unknown whether assumptions are met) 79 | simulation <- replicate(100, { 80 | d <- prodNA(iris[,1:4]) 81 | 82 | d_mf <- missForest(d)$ximp 83 | m_mf <- Mclust(d_mf, G = 3, "EEI") 84 | d_im <- imputeData(d, verbose = FALSE) 85 | m_im <- Mclust(d_im, G = 3, "EEI") 86 | 87 | class_tabl_mf <- sort(prop.table(table(iris$Species, 88 | m_mf$classification)), decreasing = TRUE)[1:3] 89 | class_tabl_im <- sort(prop.table(table(iris$Species, 90 | m_im$classification)), decreasing = TRUE)[1:3] 91 | c(sum(class_tabl_mf), sum(class_tabl_im)) 92 | }) 93 | 94 | # Performance on average 95 | rowMeans(simulation) 96 | # Performance SD 97 | colSD(t(simulation)) 98 | # Plot shows slight advantage for missForest 99 | plotdat <- data.frame(accuracy = as.vector(tmp), 100 | model = rep(c("mf", "im"), n)) 101 | ggplot(plotdat, aes(x = accuracy, colour = model))+geom_density() 102 | } 103 | } 104 | \author{ 105 | Caspar J. van Lissa 106 | } 107 | -------------------------------------------------------------------------------- /man/tidyLPA.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tidylpa.r 3 | \docType{package} 4 | \name{tidyLPA} 5 | \alias{tidyLPA} 6 | \title{tidyLPA: Functionality to carry out Latent Profile Analysis in R} 7 | \description{ 8 | Latent Profile Analysis (LPA) is a statistical modeling approach for 9 | estimating distinct profiles, or groups, of variables. In the social 10 | sciences and in educational research, these profiles could represent, for 11 | example, how different youth experience dimensions of being engaged (i.e., 12 | cognitively, behaviorally, and affectively) at the same time. 13 | } 14 | \details{ 15 | tidyLPA provides the functionality to carry out LPA in R. In particular, 16 | tidyLPA provides functionality to specify different models that determine 17 | whether and how different parameters (i.e., means, variances, and 18 | covariances) are estimated and to specify (and compare solutions for) the 19 | number of profiles to estimate. 20 | } 21 | -------------------------------------------------------------------------------- /r-references.bib: -------------------------------------------------------------------------------- 1 | @Manual{R-base, 2 | title = {R: A Language and Environment for Statistical Computing}, 3 | author = {{R Core Team}}, 4 | organization = {R Foundation for Statistical Computing}, 5 | address = {Vienna, Austria}, 6 | year = {2018}, 7 | url = {https://www.R-project.org/}, 8 | } 9 | @Manual{R-dplyr, 10 | title = {dplyr: A Grammar of Data Manipulation}, 11 | author = {Hadley Wickham and Romain François and Lionel Henry and Kirill Müller}, 12 | year = {2018}, 13 | note = {R package version 0.7.8}, 14 | url = {https://CRAN.R-project.org/package=dplyr}, 15 | } 16 | @Manual{R-forcats, 17 | title = {forcats: Tools for Working with Categorical Variables (Factors)}, 18 | author = {Hadley Wickham}, 19 | year = {2018}, 20 | note = {R package version 0.3.0}, 21 | url = {https://CRAN.R-project.org/package=forcats}, 22 | } 23 | @Book{R-ggplot2, 24 | author = {Hadley Wickham}, 25 | title = {ggplot2: Elegant Graphics for Data Analysis}, 26 | publisher = {Springer-Verlag New York}, 27 | year = {2016}, 28 | isbn = {978-3-319-24277-4}, 29 | url = {http://ggplot2.org}, 30 | } 31 | @Manual{R-papaja, 32 | author = {Frederik Aust and Marius Barth}, 33 | title = {{papaja}: {Create} {APA} manuscripts with {R Markdown}}, 34 | year = {2018}, 35 | note = {R package version 0.1.0.9842}, 36 | url = {https://github.com/crsh/papaja}, 37 | } 38 | @Manual{R-purrr, 39 | title = {purrr: Functional Programming Tools}, 40 | author = {Lionel Henry and Hadley Wickham}, 41 | year = {2019}, 42 | note = {R package version 0.3.0}, 43 | url = {https://CRAN.R-project.org/package=purrr}, 44 | } 45 | @Manual{R-readr, 46 | title = {readr: Read Rectangular Text Data}, 47 | author = {Hadley Wickham and Jim Hester and Romain Francois}, 48 | year = {2018}, 49 | note = {R package version 1.3.1}, 50 | url = {https://CRAN.R-project.org/package=readr}, 51 | } 52 | @Manual{R-stringr, 53 | title = {stringr: Simple, Consistent Wrappers for Common String Operations}, 54 | author = {Hadley Wickham}, 55 | year = {2019}, 56 | note = {R package version 1.4.0}, 57 | url = {https://CRAN.R-project.org/package=stringr}, 58 | } 59 | @Manual{R-tibble, 60 | title = {tibble: Simple Data Frames}, 61 | author = {Kirill Müller and Hadley Wickham}, 62 | year = {2019}, 63 | note = {R package version 2.0.1}, 64 | url = {https://CRAN.R-project.org/package=tibble}, 65 | } 66 | @Article{R-tidyLPA, 67 | title = {tidyLPA: An R Package to Easily Carry Out Latent Profile Analysis (LPA) Using Open-Source or Commercial Software}, 68 | author = {Joshua M. Rosenberg and Patrick N. Beymer and Daniel J. Anderson, C. J. Van Lissa, and Jennifer A. Schmidt}, 69 | journal = {Journal of Open Source Software}, 70 | year = {2018}, 71 | volume = {3}, 72 | number = {30}, 73 | pages = {978}, 74 | url = {http://joss.theoj.org/papers/10.21105/joss.00978}, 75 | doi = {10.21105/joss.00978}, 76 | } 77 | @Manual{R-tidyr, 78 | title = {tidyr: Easily Tidy Data with 'spread()' and 'gather()' Functions}, 79 | author = {Hadley Wickham and Lionel Henry}, 80 | year = {2018}, 81 | note = {R package version 0.8.2}, 82 | url = {https://CRAN.R-project.org/package=tidyr}, 83 | } 84 | @Manual{R-tidyverse, 85 | title = {tidyverse: Easily Install and Load the 'Tidyverse'}, 86 | author = {Hadley Wickham}, 87 | year = {2017}, 88 | note = {R package version 1.2.1}, 89 | url = {https://CRAN.R-project.org/package=tidyverse}, 90 | } 91 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(tidyLPA) 3 | options("test_mplus" = FALSE) 4 | if(file.exists("test_local.R")) source("test_local.R") 5 | # To run all mplus tests, run the code below once to create a file that is not 6 | # tracked by git, which toggles the option to run mplus tests: 7 | # writeLines('options("test_mplus" = TRUE)', con = "tests/test_local.R") 8 | test_check("tidyLPA") 9 | # Clean up after test_mplus 10 | if(getOption("test_mplus")){ 11 | remove_files <- list.files(pattern = "\\.(inp|out|dat|log)$", full.names = TRUE) 12 | if(length(remove_files) > 0){ 13 | invisible(file.remove(remove_files)) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/testthat/test-compare-solutions.R: -------------------------------------------------------------------------------- 1 | context("test-compare_solutions.R") 2 | 3 | x <- estimate_profiles(iris[, 1:4], n_profiles = 2:4) 4 | 5 | test_that("compare_solutions works with iris data when we use compare_solutions() 6 | outside of a pipe", { 7 | expect_s3_class(suppressWarnings(compare_solutions(x)), "bestLPA") 8 | }) 9 | 10 | # pisaUSA_compare <- pisaUSA15[1:100, ] %>% 11 | # single_imputation() %>% 12 | # estimate_profiles(2:3, 13 | # variances = c("equal", "varying"), 14 | # covariances = c("zero", "varying")) %>% 15 | # compare_solutions(statistics = c("AIC", "BIC")) 16 | # 17 | # test_that("compare_solutions works with PISA data when we use compare_solutions 18 | # in a pipe", { 19 | # expect_s3_class(pisaUSA_compare, "bestLPA") 20 | # }) 21 | -------------------------------------------------------------------------------- /tests/testthat/test-estimate-profiles-mclust.R: -------------------------------------------------------------------------------- 1 | context("test-estimate_profiles-mclust.R") 2 | 3 | m_mclust <- estimate_profiles(iris[, 1:4], n_profiles = 3, models = c(1:3,6)) 4 | m_cars_mclust <- estimate_profiles(mtcars[, "mpg"], n_profiles = 2, models = 2) 5 | 6 | test_that("estimate_profiles_mclust handles single-column data", 7 | expect_equal(m_cars_mclust$model_2_class_2$estimates$Estimate, c(18.481, 18.337, 31.759, 2.429), 8 | tolerance = .05)) 9 | 10 | test_that("LogLik values are as expected for model type 1", 11 | expect_equal(m_mclust$model_1_class_3$model$loglik, -361.4295, 12 | tolerance = .001) 13 | ) 14 | 15 | test_that("LogLik values are as expected for model type 2", 16 | expect_equal(m_mclust$model_2_class_3$model$loglik, -307.1808, 17 | tolerance = .001) 18 | ) 19 | 20 | test_that("LogLik values are as expected for model type 3", 21 | expect_equal(m_mclust$model_3_class_3$model$loglik, -256.3547, 22 | tolerance = .001) 23 | ) 24 | 25 | test_that("LogLik values are as expected for model type 6", 26 | expect_equal(m_mclust$model_6_class_3$model$loglik, -180.1858, 27 | tolerance = .001) 28 | ) 29 | 30 | m_pisa_mclust_3_profiles <- estimate_profiles(pisaUSA15[1:100, ], n_profiles = 3) 31 | 32 | test_that("estimate_profiles works with build-in PISA data and mclust", 33 | expect_s3_class(m_pisa_mclust_3_profiles, "tidyLPA") 34 | ) 35 | -------------------------------------------------------------------------------- /tests/testthat/test-local-estimate-profiles-mplus.R: -------------------------------------------------------------------------------- 1 | if(getOption("test_mplus")){ 2 | oldwd <- getwd() 3 | testdir <- file.path(tempdir(), "estimateprofiles") 4 | dir.create(testdir) 5 | setwd(testdir) 6 | on.exit({ 7 | setwd(oldwd) 8 | unlink(testdir, recursive = TRUE) 9 | }) 10 | 11 | tmp <- capture_output({ 12 | m_cars_mplus <- estimate_profiles(mtcars[, "mpg"], 13 | n_profiles = 2, 14 | models = 2, 15 | package = "MplusAutomation") 16 | }) 17 | m_cars_mclust <- estimate_profiles(mtcars[, "mpg"], n_profiles = 2, models = 2) 18 | test_that("estimate_profiles_mplus handles single-column data", { 19 | expect_equivalent(m_cars_mplus$model_2_class_2$estimates$Estimate, c(18.481, 18.337, 31.759, 2.429), tolerance = .001) 20 | }) 21 | 22 | test_that("single column fit indices are the same across mplus and mclust", { 23 | expect_equivalent(m_cars_mclust$model_2_class_2$fit[!names(m_cars_mclust$model_2_class_2$fit) %in% c("BLRT_p")], 24 | m_cars_mplus$model_2_class_2$fit[!names(m_cars_mplus$model_2_class_2$fit) %in% c("BLRT_p")], tolerance = .0001) 25 | }) 26 | iris_df <- iris 27 | names(iris_df) <- gsub("\\.", "_", names(iris_df)) 28 | tmp <- capture_output({ 29 | m_mplus <- suppressWarnings(estimate_profiles(iris_df[, 1:4], n_profiles = 3, models = c(1:3,6), package = "MplusAutomation")) 30 | }) 31 | m_mclust <- estimate_profiles(iris_df[, 1:4], n_profiles = 3, models = c(1:3,6)) 32 | 33 | test_that("estimate_profiles() yields the same estimates for mclust and Mplus", { 34 | expect_equivalent(m_mclust[[1]]$estimates$Estimate, m_mplus[[1]]$estimates$Estimate, tolerance = .001) 35 | }) 36 | 37 | test_that("estimate_profiles() yields the same LogLikelihoods for mclust and Mplus", { 38 | expect_equivalent(sapply(m_mclust, function(x){x$fit["LogLik"]}), 39 | sapply(m_mplus, function(x){x$fit["LogLik"]}), 40 | tolerance = .0001) 41 | }) 42 | 43 | test_that("LogLik values are as expected for mplus", { 44 | LLs <- c( 45 | m_mplus$model_1_class_3$model$summaries$LL, 46 | m_mplus$model_2_class_3$model$summaries$LL, 47 | m_mplus$model_3_class_3$model$summaries$LL, 48 | m_mplus$model_6_class_3$model$summaries$LL 49 | ) 50 | Expected <- c(-361.4295, 51 | -307.1808, 52 | -256.3547, 53 | -180.1858) 54 | expect_equivalent(LLs, Expected, tolerance = .001) 55 | }) 56 | } 57 | -------------------------------------------------------------------------------- /tests/testthat/test-local-estimate_profiles_mplus2-arguments.R: -------------------------------------------------------------------------------- 1 | if(getOption("test_mplus")){ 2 | oldwd <- getwd() 3 | testdir <- file.path(tempdir(), "mplusargs") 4 | dir.create(testdir) 5 | setwd(testdir) 6 | on.exit({ 7 | setwd(oldwd) 8 | unlink(testdir, recursive = TRUE) 9 | }) 10 | 11 | test_that("Mplus can handle ANALYSIS = 'starts = .....;'", { 12 | iris_sample <- iris # to make example run more quickly 13 | names(iris_sample) <- gsub("\\.", "_", names(iris_sample)) 14 | # With an argument passed on to mplusModeler, returns a warning 15 | tmp <- capture_output({ 16 | res <- estimate_profiles(iris_sample[, c("Sepal_Length", "Sepal_Width", 17 | "Petal_Length")], 18 | 3, 19 | package = "mplus", 20 | ANALYSIS = "starts = 15 3;", 21 | keepfiles = TRUE) 22 | }) 23 | file_contents <- readLines("model_1_class_3.inp") 24 | expect_true(any(grepl("starts = 15 3;", file_contents))) 25 | 26 | expect_equal(res$model_1_class_3$model$summaries$BLRT_KM1AnalysisStarts, 15) 27 | expect_equal(res$model_1_class_3$model$summaries$BLRT_KM1AnalysisFinal, 3) 28 | 29 | }) 30 | 31 | test_that("Illegal arguments are blocked in call to estimate_profiles_mplus2()", { 32 | tmp <- capture_output({ 33 | 34 | expect_error(estimate_profiles(irisdf, 35 | 3, 36 | package = "mplus", 37 | ANALYSIS = "starts = 15,3;", 38 | keepfiles = TRUE, 39 | hug = "bla")) 40 | 41 | expect_error(estimate_profiles(irisdf, 42 | 3, 43 | package = "mplus", 44 | ANALYSIS = "starts = 15,3;", 45 | keepfiles = TRUE, 46 | usevariables = "bla")) 47 | }) 48 | }) 49 | 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /tests/testthat/test-local-plot-profiles-mplus.R: -------------------------------------------------------------------------------- 1 | if(getOption("test_mplus")){ 2 | oldwd <- getwd() 3 | testdir <- file.path(tempdir(), "plotmplus") 4 | dir.create(testdir) 5 | setwd(testdir) 6 | on.exit({ 7 | setwd(oldwd) 8 | unlink(testdir, recursive = TRUE) 9 | }) 10 | 11 | iris_df <- iris 12 | names(iris_df) <- gsub("\\.", "_", names(iris_df)) 13 | test_that("plot_profiles", { 14 | tmp <- capture_output({ 15 | out_mplus <- suppressWarnings(estimate_profiles(iris_df[, 1:4], n_profiles = 3, package = "MplusAutomation")) 16 | }) 17 | 18 | expect_s3_class(plot_profiles(out_mplus), "ggplot") 19 | }) 20 | 21 | test_that("matrix data are correctly read", { 22 | df <- as.matrix(iris_df[, 1:4]) 23 | tmp <- capture_output({ 24 | expect_error(estimate_profiles(df, n_profiles = 3, package = "MplusAutomation"), NA) 25 | }) 26 | }) 27 | 28 | test_that("Parsing variable names throws error if variable names are not unique", { 29 | df <- iris_df[, 1:4] 30 | names(df)[1:2] <- c("Sepal.Length1", "Sepal.Length2") 31 | tmp <- capture_output({ 32 | expect_error(estimate_profiles(df, n_profiles = 3, package = "MplusAutomation")) 33 | }) 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /tests/testthat/test-pipe.R: -------------------------------------------------------------------------------- 1 | context("test-pipe.R") 2 | 3 | test_that("pipe is loaded and works", { 4 | expect_equal({ 5 | c(1,2,3,4,5) %>% 6 | mean()}, 3) 7 | }) 8 | -------------------------------------------------------------------------------- /tests/testthat/test-plot-mixtures.R: -------------------------------------------------------------------------------- 1 | results <- estimate_profiles(subset(iris, select = c("Sepal.Length", "Sepal.Width", 2 | "Petal.Length", "Petal.Width")), 1:3) 3 | density_plot <- plot_density(results, variables = "Petal.Length") 4 | 5 | test_that("density plot works", 6 | expect_is(density_plot, "gg") 7 | ) 8 | -------------------------------------------------------------------------------- /tests/testthat/test-plot-profiles.R: -------------------------------------------------------------------------------- 1 | test_that("plot_profiles works", { 2 | x <- estimate_profiles(iris[, 1:4], n_profiles = 3) 3 | expect_s3_class(plot_profiles(x), "ggplot") 4 | }) 5 | 6 | pisa_profiles_plot_mclust <- pisaUSA15[1:100, ] %>% 7 | single_imputation() %>% 8 | scale() %>% 9 | estimate_profiles(3) %>% 10 | plot_profiles() 11 | 12 | test_that("plot profiles works with imputed and scaled data using mclust", { 13 | expect_s3_class(pisa_profiles_plot_mclust, "ggplot") 14 | }) 15 | -------------------------------------------------------------------------------- /tidyLPA.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 4 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace,vignette 22 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /vignettes/benchmarking-mclust-and-mplus.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Benchmarking mclust and MPlus" 3 | author: "Vignette Author" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Benchmarking mclust and MPlus} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ## Purpose 13 | 14 | The purpose of this vignette is to facilitate benchmarking the output from the use of two packages, MPlus (via the MplusAutomation package) and mclust (via the mclust package). As CRAN does not allow for MPlus to be used, this vignette is not rendered, but can be rendered on your own computer as long as you have MPlus (and MplusAutomation) installed. Please note that _MPlus must be installed on your computer for this vignette to run_. 15 | 16 | ```{r setup, include = FALSE} 17 | knitr::opts_chunk$set( 18 | collapse = TRUE, 19 | comment = "#>", 20 | eval = FALSE 21 | ) 22 | ``` 23 | 24 | # Using mclust 25 | 26 | ## Just one fit 27 | 28 | ```{r} 29 | library(tidyLPA) 30 | library(dplyr) 31 | 32 | iris %>% 33 | select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) %>% 34 | estimate_profiles(n_profiles = 2) %>% 35 | get_fit() %>% 36 | as.data.frame() 37 | ``` 38 | 39 | # Using MPlus 40 | 41 | ## Just one fit 42 | 43 | ```{r} 44 | iris %>% 45 | select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) %>% 46 | estimate_profiles(n_profiles = 2, package = "mplus") %>% 47 | get_fit() %>% 48 | as.data.frame() 49 | ``` 50 | 51 | # Using mclust 52 | 53 | ## Many fits 54 | 55 | ```{r} 56 | library(tidyLPA) 57 | library(dplyr) 58 | 59 | iris %>% 60 | select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) %>% 61 | estimate_profiles(n_profiles = 2:4, models = c(1, 2, 3, 6)) %>% 62 | get_fit() %>% 63 | as.data.frame() 64 | ``` 65 | 66 | # Using MPlus 67 | 68 | ## Many fits 69 | 70 | ```{r} 71 | iris %>% 72 | select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) %>% 73 | estimate_profiles(n_profiles = 2:4, models = c(1, 2, 3, 6), 74 | package = "mplus") %>% 75 | get_fit() %>% 76 | as.data.frame() 77 | ``` 78 | --------------------------------------------------------------------------------