Created
January 28, 2026 02:26
-
-
Save mingjiphd/b1bdb29e026c726b6a3c496c2525a175 to your computer and use it in GitHub Desktop.
Machine Learning using R How to Implement Multidimentional Scaling
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| This R script is a step by step demonstration showing how to implement MDS (both metric and non-metric MDS) using R. The R functions used are: cmdscale (Base R), mds (smacof) and isoMDS(MASS). | |
| Click here to view a step by step demo: https://youtu.be/SkVAzb1IuOU?si=6tTkUsvgu_5vnO4I |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ############################################################################################# | |
| # Machine Learning using R How to Implement Multidimsional Scaling # | |
| ############################################################################################# | |
| #### Multidimensional Scaling (MDS) | |
| ## visualizes similarities/dissimilarities between objects | |
| ## by placing them in low-dimensional space (usually 2D/3D) | |
| ## where distances reflect original relationships | |
| #### Input: Pairwise dissimilarity matrix (interval, ordinal, or nominal data) | |
| #### Output: Point coordinates + goodness-of-fit measures | |
| #### Two main types | |
| ## Metric MDS (cmdscale, smacof interval) | |
| ## Preserves actual distances; assumes Euclidean structure | |
| ## Non-metric/Ordinal MDS (isoMDS): | |
| ## Preserves rank order only; more flexible for rank/perceptual data | |
| ##### Stress value measures fit quality: <0.05=Excellent, <0.10=Good, <0.20=Fair, >0.20=Poor | |
| #### cmdscale eigenvalues indicate variance explained per dimension (large positive = good fit) | |
| #### Shepard diagram shows monotonic regression (observed vs. fitted distances) for ordinal MDS validation | |
| # Load required libraries | |
| library(stats) # for cmdscale (base R MDS) | |
| library(smacof) # for SMACOF MDS | |
| # Set seed for reproducibility | |
| set.seed(1192026) | |
| ## PART 1: Interval Data for MDS | |
| # Generate synthetic interval dissimilarity data for 10 objects | |
| n <- 10 | |
| diss_matrix <- matrix(runif(n*(n-1)/2, 1, 10), nrow = n, ncol = n) | |
| diss_matrix <- as.dist(diss_matrix) | |
| diag(diss_matrix) <- 0 | |
| # Base R MDS using cmdscale (metric/interval MDS) | |
| mds_base <- cmdscale(diss_matrix, k = 2, eig = TRUE) | |
| # SMACOF interval MDS | |
| mds_smacof <- mds(diss_matrix, ndim = 2, type = "interval") | |
| # Comparison | |
| par(mfrow = c(1, 2)) | |
| plot(mds_base$points, main = "Base R cmdscale (Interval)", | |
| xlab = "Dim 1", ylab = "Dim 2", pch = 16) | |
| plot(mds_smacof$conf, main = "SMACOF (Interval)", | |
| xlab = "Dim 1", ylab = "Dim 2", pch = 16) | |
| # Stress values comparison | |
| cat("Base R eigenvalues:", round(mds_base$eig[1:2], 3), "\n") | |
| cat("SMACOF stress:", round(mds_smacof$stress, 3), "\n") | |
| ## PART 2: Ordinal Data MDS | |
| # Load required library | |
| library(MASS) | |
| # Set seed for reproducibility | |
| set.seed(123) | |
| ## Generate Ordinal Dissimilarity Data for MDS | |
| n_objects <- 12 # Number of objects to compare | |
| max_rank <- 7 # Ordinal scale: 1-7 (like Likert ratings) | |
| # Create symmetric dissimilarity matrix with ordinal ranks (1-7) | |
| # Upper triangle filled with random ordinal values | |
| ordinal_matrix <- matrix(0, n_objects, n_objects) | |
| upper_tri <- upper.tri(ordinal_matrix) | |
| # Fill upper triangle with ordinal ranks (1-7) | |
| ordinal_matrix[upper_tri] <- sample(1:max_rank, sum(upper_tri), replace = TRUE) | |
| ordinal_matrix <- ordinal_matrix + t(ordinal_matrix) # Make symmetric | |
| diag(ordinal_matrix) <- 0 # Zero diagonal | |
| # Convert to dist object | |
| ordinal_diss <- as.dist(ordinal_matrix) | |
| # Display first few dissimilarities | |
| cat("Sample ordinal dissimilarities (ranks 1-7):\n") | |
| print(round(ordinal_diss[1:6], 1)) | |
| ## Perform Ordinal MDS using isoMDS | |
| ordinal_mds <- isoMDS(ordinal_diss, k = 2, maxit = 2000) | |
| ## Results and Visualization | |
| par(mfrow = c(1, 2)) | |
| # Plot MDS configuration | |
| par(mfrow = c(1, 2)) | |
| # 1. MDS Configuration Plot | |
| plot(ordinal_mds$points, | |
| main = "Ordinal MDS Configuration (isoMDS)", | |
| xlab = "Dimension 1", ylab = "Dimension 2", | |
| pch = 16, col = "darkred", cex = 1.3) | |
| # 2. Shepard Diagram (CORRECTED) | |
| shepard_plot <- Shepard(ordinal_diss, ordinal_mds$points) | |
| plot(shepard_plot, pch = 16, col = "blue", | |
| main = "Shepard Diagram", | |
| xlab = "Original Ordinal Distances", | |
| ylab = "Fitted Distances") | |
| abline(0, 1, col = "red", lwd = 2) | |
| lines(shepard_plot$x, shepard_plot$yf, col = "darkgreen", lwd = 2) | |
| # Stress results | |
| cat("\n=== ORDINAL MDS RESULTS ===\n") | |
| cat("Stress (ordinal):", round(ordinal_mds$stress, 4), "\n") | |
| cat("Stress %:", round(ordinal_mds$stress * 100, 2), "%\n") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Click here to view a step by step demo: https://youtu.be/SkVAzb1IuOU?si=6tTkUsvgu_5vnO4I |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment