| Type: | Package |
| Title: | Profile Analysis via Multidimensional Scaling |
| Version: | 0.1.0 |
| Date: | 2026-03-22 |
| Description: | Implements Profile Analysis via Multidimensional Scaling (PAMS) for the identification of population-level core response profiles from cross-sectional and longitudinal person-score data. Each person profile is decomposed into a level component (the person mean) and a pattern component (ipsatized subscores). PAMS uses nonmetric multidimensional scaling via the SMACOF algorithm to identify a small number of core profiles that represent the central response patterns in a sample of any size. Bootstrap standard errors and bias-corrected and accelerated (BCa) confidence intervals for individual core profile coordinates are estimated, enabling significance testing of coordinates that is not available in other profile analysis methods such as cluster profile analysis or latent profile analysis. Person-level weights, R-squared values, and correlations with core profiles are also estimated, allowing individual profiles to be interpreted in terms of the core profile structure. PAMS can be applied to both cross-sectional data and longitudinal data, where core trajectory profiles describe how response patterns change over time. Methods are described in Kim and Kim (2024) <doi:10.20982/tqmp.20.3.p230>, de Leeuw and Mair (2009) <doi:10.18637/jss.v031.i03>, and Kruskal (1964) <doi:10.1007/BF02289565>. |
| License: | MIT + file LICENSE |
| URL: | https://github.com/sekangakim/pams |
| BugReports: | https://github.com/sekangakim/pams/issues |
| Depends: | R (≥ 4.0.0) |
| Imports: | smacof (≥ 2.1.0) |
| Suggests: | lmtest (≥ 0.9.40), testthat (≥ 3.0.0) |
| Encoding: | UTF-8 |
| RoxygenNote: | 7.3.3 |
| Config/testthat/edition: | 3 |
| NeedsCompilation: | no |
| Packaged: | 2026-03-27 03:48:18 UTC; sekangkim |
| Author: | Se-Kang Kim |
| Maintainer: | Se-Kang Kim <Se-Kang.Kim@bcm.edu> |
| Repository: | CRAN |
| Date/Publication: | 2026-03-31 15:00:02 UTC |
Profile Analysis via Multidimensional Scaling
Description
Identifies population-level core response profiles from cross-sectional or
longitudinal person-score data using nonmetric multidimensional scaling
(SMACOF algorithm). Each person profile is decomposed into a level
component (person mean) and a pattern component (ipsatized subscores).
BootSmacof fits a nonmetric MDS solution to the J \times J
inter-variable distance matrix, bootstraps the solution to generate
empirical sampling distributions of core profile coordinates, and computes
bias-corrected and accelerated (BCa) confidence intervals for each
coordinate. Person-level weights, R-squared values, and correlations with
core profiles are estimated for all participants, with optional bootstrap
confidence intervals for a selected subset.
Usage
BootSmacof(
testdata,
participant = NULL,
mds = c("smacof", "classical"),
type = c("ratio", "interval", "ordinal", "mspline"),
distance = c("euclid", "sqeuclid"),
scale = FALSE,
nprofile = 3,
direction = rep(1, nprofile),
cl = 0.95,
nBoot = 2000,
testname = NULL,
file = NULL
)
Arguments
testdata |
A data frame or matrix of persons (rows) by subscales (columns). Subscores are assumed to be related and continuous. For longitudinal data, columns should be ordered as all subscales at Time 1 followed by all subscales at Time 2, and so on. |
participant |
An integer vector of row indices identifying persons for
whom individual bootstrap confidence intervals on weights and partial
correlations are computed. If |
mds |
Character string specifying the MDS algorithm. Either
|
type |
Character string specifying the optimal scaling transformation
passed to |
distance |
Character string specifying the distance measure used to
compute the |
scale |
Logical. If |
nprofile |
A positive integer specifying the number of core profiles
(MDS dimensions) to extract. Choose by inspecting stress values across
2-, 3-, and 4-dimensional solutions; Kruskal's (1964) criterion of
stress |
direction |
An integer vector of length |
cl |
Numeric confidence level for BCa intervals. Default is
|
nBoot |
A positive integer specifying the number of bootstrap
samples. A minimum of |
testname |
An optional character vector of length equal to the number
of columns in |
file |
An optional character string giving a file path stem. If
supplied, three CSV files are written: |
Value
A named list with the following components:
MDSThe MDS fit object for the original data. When
mds = "smacof"this is the full object returned bysmacofSym, including$conf(core profile coordinate matrix,J \times K) and$stress. Whenmds = "classical"this is a minimal list with$confonly.MDSsummaryA list of
nprofiledata frames, one per core profile. Each data frame has rows corresponding to subscales and columns:Ori(original coordinate),Mean(bootstrap mean),SE(bootstrap standard error),LowerandUpper(percentile CI bounds),BCaLowerandBCaUpper(BCa CI bounds). Coordinates whose BCa CI does not include zero are statistically significant.MDSprofileA list of
nprofilematrices, each of dimensionnBoot\timesJ, containing the full bootstrap distribution of core profile coordinates.stresssummaryA one-row data frame with bootstrap summary statistics for the smacof stress value:
Ori,Mean,SE,Lower,Upper,BCaLower,BCaUpper.NULLwhenmds = "classical".stressprofileA numeric vector of length
nBootcontaining bootstrap stress values.NULLwhenmds = "classical".MDSR2A numeric vector of length
nprofilecontaining the R-squared values from regressing each core profile dimension on the remaining dimensions. Low values confirm that the core profiles are not collinear.WeightA matrix of dimension
I \times (2K + 2)containing, for every person: raw weights (w1, ...,wK), level estimate, R-squared value, and correlations with each core profile (corDim1, ...,corDimK). Row names are"#1","#2", ...WeightmeanR2The mean R-squared value across all
Ipersons, summarising how well thenprofilecore profiles account for pattern variance in the sample.WeightBA matrix of bootstrap summary statistics (original estimate, mean, SE, lower and upper CI bounds) for the weights of each person in
participant.NULLifparticipantisNULL.PcorrBA matrix of bootstrap summary statistics for the partial correlations of each person in
participant.NULLifparticipantisNULL.nprofileThe number of core profiles extracted.
nBootThe number of bootstrap samples used.
scaleLogical; whether columns were standardised.
testnameCharacter vector of subscale names used.
References
Davison, M. L. (1996). Multidimensional scaling interest and aptitude profiles: Idiographic dimensions, nomothetic factors. Presidential address to Division 5, American Psychological Association, Toronto.
de Leeuw, J., & Mair, P. (2009). Multidimensional scaling using majorization: SMACOF in R. Journal of Statistical Software, 31(3), 1–30. doi:10.18637/jss.v031.i03
Efron, B., & Tibshirani, R. J. (1993). An introduction to the bootstrap. Chapman & Hall.
Kim, S.-K., & Kim, D. (2024). Utility of profile analysis via multidimensional scaling in R for the study of person response profiles in cross-sectional and longitudinal data. The Quantitative Methods for Psychology, 20(3), 230–247. doi:10.20982/tqmp.20.3.p230
Kruskal, J. B. (1964). Multidimensional scaling by optimizing goodness of fit to a nonmetric hypothesis. Psychometrika, 29, 1–27. doi:10.1007/BF02289565
See Also
smacofSym for the underlying MDS
algorithm.
Examples
# Small toy example (runs automatically)
set.seed(42)
toy_data <- as.data.frame(matrix(rnorm(50 * 5, mean = 10, sd = 2),
nrow = 50, ncol = 5))
colnames(toy_data) <- paste0("S", 1:5)
result <- BootSmacof(
testdata = toy_data,
participant = 1:3,
mds = "smacof",
type = "ordinal",
distance = "euclid",
nprofile = 2,
direction = c(1, 1),
cl = 0.95,
nBoot = 20,
testname = colnames(toy_data)
)
result$MDS$stress
round(result$WeightmeanR2, 2)
round(result$MDSsummary[[1]], 3)
# Larger synthetic example demonstrating 3 core profiles (takes > 5 sec).
# In practice, replace syn_data with your own persons x subscales data frame.
set.seed(1)
syn_data <- as.data.frame(matrix(rnorm(200 * 8, mean = 50, sd = 10),
nrow = 200, ncol = 8))
colnames(syn_data) <- paste0("Sub", 1:8)
result3 <- BootSmacof(
testdata = syn_data,
participant = 1:5,
mds = "smacof",
type = "ordinal",
distance = "euclid",
nprofile = 3,
direction = c(1, 1, 1),
cl = 0.95,
nBoot = 200,
testname = colnames(syn_data),
file = file.path(tempdir(), "syn_profile")
)
result3$MDS$stress
round(result3$WeightmeanR2, 2)
round(result3$MDSsummary[[1]], 3)
round(result3$MDSsummary[[2]], 3)
round(result3$MDSsummary[[3]], 3)
round(result3$Weight[1:5, ], 2)