This example shows how to use the riemannianStats
package to explore a small student data set and reduce its
dimensionality.
The data set contains the grades of 10 students in 5 subjects: Mathematics, Sciences, Spanish, History, and Physical Education.
The objective of this example is not to classify students or use known groups, but to explore the general structure of the data using Riemannian principal components.
The first column identifies each student, and the remaining columns contain their grades in five subjects.
students <- data.frame(
Student = c(
"Lucia", "Pedro", "Ines", "Luis", "Andres",
"Ana", "Carlos", "Jose", "Sonia", "Maria"
),
Mathematics = c(7, 7.5, 7.6, 5, 6, 7.8, 6.3, 7.9, 6, 6.8),
Sciences = c(6.5, 9.4, 9.2, 6.5, 6, 9.6, 6.4, 9.7, 6, 7.2),
Spanish = c(9.2, 7.3, 8, 6.5, 7.8, 7.7, 8.2, 7.5, 6.5, 8.7),
History = c(8.6, 7, 8, 7, 8.9, 8, 9, 8, 5.5, 9),
PhysicalEducation = c(8, 7, 7.5, 9, 7.3, 6.5, 7.2, 6, 8.7, 7)
)
students
#> Student Mathematics Sciences Spanish History PhysicalEducation
#> 1 Lucia 7.0 6.5 9.2 8.6 8.0
#> 2 Pedro 7.5 9.4 7.3 7.0 7.0
#> 3 Ines 7.6 9.2 8.0 8.0 7.5
#> 4 Luis 5.0 6.5 6.5 7.0 9.0
#> 5 Andres 6.0 6.0 7.8 8.9 7.3
#> 6 Ana 7.8 9.6 7.7 8.0 6.5
#> 7 Carlos 6.3 6.4 8.2 9.0 7.2
#> 8 Jose 7.9 9.7 7.5 8.0 6.0
#> 9 Sonia 6.0 6.0 6.5 5.5 8.7
#> 10 Maria 6.8 7.2 8.7 9.0 7.0The Riemannian analysis is applied only to numeric variables.
Therefore, the Student column is used as the row names,
while only the subject grades are kept for the analysis.
data.analysis <- students[, c(
"Mathematics",
"Sciences",
"Spanish",
"History",
"PhysicalEducation"
)]
student.names <- students$Student
rownames(data.analysis) <- student.names
data.analysis
#> Mathematics Sciences Spanish History PhysicalEducation
#> Lucia 7.0 6.5 9.2 8.6 8.0
#> Pedro 7.5 9.4 7.3 7.0 7.0
#> Ines 7.6 9.2 8.0 8.0 7.5
#> Luis 5.0 6.5 6.5 7.0 9.0
#> Andres 6.0 6.0 7.8 8.9 7.3
#> Ana 7.8 9.6 7.7 8.0 6.5
#> Carlos 6.3 6.4 8.2 9.0 7.2
#> Jose 7.9 9.7 7.5 8.0 6.0
#> Sonia 6.0 6.0 6.5 5.5 8.7
#> Maria 6.8 7.2 8.7 9.0 7.0First, a local similarity matrix between students is computed. This matrix summarizes which students are close to each other according to their grade patterns.
n.neighbors <- 3
umap.similarities <- riem.similarities.umap(
data = data.analysis,
n.neighbors = n.neighbors,
min.dist = 0.1,
metric = "euclidean"
)
round(umap.similarities, 3)
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,] 0.000 0.000 0.000 0.000 0.000 0 0.585 0.000 0.000 1.000
#> [2,] 0.000 0.000 0.828 0.000 0.000 1 0.000 0.585 0.000 0.000
#> [3,] 0.000 0.828 0.000 0.000 0.000 1 0.000 0.000 0.000 0.000
#> [4,] 0.000 0.000 0.000 0.000 0.585 0 0.000 0.000 1.000 0.000
#> [5,] 0.000 0.000 0.000 0.585 0.000 0 1.000 0.000 0.585 0.585
#> [6,] 0.000 1.000 1.000 0.000 0.000 0 0.000 1.000 0.000 0.000
#> [7,] 0.585 0.000 0.000 0.000 1.000 0 0.000 0.000 0.000 1.000
#> [8,] 0.000 0.585 0.000 0.000 0.000 1 0.000 0.000 0.000 0.000
#> [9,] 0.000 0.000 0.000 1.000 0.585 0 0.000 0.000 0.000 0.000
#> [10,] 1.000 0.000 0.000 0.000 0.585 0 1.000 0.000 0.000 0.000The Rho matrix is obtained as 1 - umap.similarities.
This matrix is used to weight the differences between students.
rho <- riem.rho(umap.similarities)
round(rho, 3)
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,] 1.000 1.000 1.000 1.000 1.000 1 0.415 1.000 1.000 0.000
#> [2,] 1.000 1.000 0.172 1.000 1.000 0 1.000 0.415 1.000 1.000
#> [3,] 1.000 0.172 1.000 1.000 1.000 0 1.000 1.000 1.000 1.000
#> [4,] 1.000 1.000 1.000 1.000 0.415 1 1.000 1.000 0.000 1.000
#> [5,] 1.000 1.000 1.000 0.415 1.000 1 0.000 1.000 0.415 0.415
#> [6,] 1.000 0.000 0.000 1.000 1.000 1 1.000 0.000 1.000 1.000
#> [7,] 0.415 1.000 1.000 1.000 0.000 1 1.000 1.000 1.000 0.000
#> [8,] 1.000 0.415 1.000 1.000 1.000 0 1.000 1.000 1.000 1.000
#> [9,] 1.000 1.000 1.000 0.000 0.415 1 1.000 1.000 1.000 1.000
#> [10,] 0.000 1.000 1.000 1.000 0.415 1 0.000 1.000 1.000 1.000Riemannian differences compare each student with the others, weighting those differences by the local structure of the data.
A Riemannian distance matrix is then computed from those differences.
distance.matrix <- riem.dist(riemannian.diff)
round(distance.matrix, 3)
#> Lucia Pedro Ines Luis Andres Ana Carlos Jose Sonia Maria
#> Lucia 0.000 3.979 3.114 3.854 1.947 3.887 0.629 4.278 4.317 0.000
#> Pedro 3.979 0.000 0.230 4.393 4.214 0.000 3.910 0.628 4.426 3.360
#> Ines 3.114 0.230 0.000 4.422 3.700 0.000 3.265 1.685 4.769 2.526
#> Luis 3.854 4.393 4.422 0.000 1.275 5.113 3.439 5.445 0.000 4.071
#> Andres 1.947 4.214 3.700 1.275 0.000 4.202 0.000 4.460 1.619 0.718
#> Ana 3.887 0.000 0.000 5.113 4.202 0.000 3.772 0.000 5.360 3.002
#> Carlos 0.629 3.910 3.265 3.439 0.000 3.772 0.000 4.047 4.200 0.000
#> Jose 4.278 0.628 1.685 5.445 4.460 0.000 4.047 0.000 5.643 3.302
#> Sonia 4.317 4.426 4.769 0.000 1.619 5.360 4.200 5.643 0.000 4.697
#> Maria 0.000 3.360 2.526 4.071 0.718 3.002 0.000 3.302 4.697 0.000The Riemannian covariance matrix summarizes the joint variability of the subjects while considering Riemannian centering.
covariance.matrix <- riem.cov(
data = data.analysis,
rho = rho,
umap.distance.matrix = distance.matrix
)
round(covariance.matrix, 3)
#> Mathematics Sciences Spanish History PhysicalEducation
#> Mathematics 0.733 1.068 0.198 0.211 -0.620
#> Sciences 1.068 2.303 -0.551 -0.568 -0.620
#> Spanish 0.198 -0.551 1.471 1.782 -0.684
#> History 0.211 -0.568 1.782 2.325 -0.896
#> PhysicalEducation -0.620 -0.620 -0.684 -0.896 0.841The Riemannian correlation matrix makes it possible to compare the relationship between subjects on a common scale.
correlation.matrix <- riem.cor(
data = data.analysis,
rho = rho,
umap.distance.matrix = distance.matrix
)
round(correlation.matrix, 3)
#> Mathematics Sciences Spanish History PhysicalEducation
#> Mathematics 1.000 0.822 0.191 0.162 -0.790
#> Sciences 0.822 1.000 -0.300 -0.245 -0.446
#> Spanish 0.191 -0.300 1.000 0.963 -0.615
#> History 0.162 -0.245 0.963 1.000 -0.641
#> PhysicalEducation -0.790 -0.446 -0.615 -0.641 1.000Riemannian principal components make it possible to represent students in a lower-dimensional space.
components <- riem.ind.coord(
data = data.analysis,
correlation.matrix = correlation.matrix,
rho = rho,
umap.distance.matrix = distance.matrix
)
round(components, 3)
#> Component.1 Component.2 Component.3 Component.4 Component.5
#> Lucia 0.000 0.000 0.000 0.000 0.000
#> Pedro -0.494 -2.358 0.022 -0.024 -0.138
#> Ines -0.208 -1.741 -0.423 -0.642 0.082
#> Luis -3.729 0.168 -0.603 0.328 -0.014
#> Andres -0.471 0.260 0.042 0.255 0.126
#> Ana 0.460 -2.246 -0.074 0.098 0.031
#> Carlos 0.000 0.000 0.000 0.000 0.000
#> Jose 0.762 -2.474 0.144 0.488 0.052
#> Sonia -3.554 -0.603 0.670 -0.220 0.028
#> Maria 0.000 0.000 0.000 0.000 0.000Explained inertia indicates the proportion of total variability represented by the selected components.
The correlations between the subjects and the components help interpret which subjects are most associated with each axis of the principal plane.
loadings <- riem.var.coord(
data = data.analysis,
components = components,
rho = rho,
umap.distance.matrix = distance.matrix
)
round(loadings, 3)
#> Component.1 Component.2
#> Mathematics 0.731 -0.647
#> Sciences 0.336 -0.914
#> Spanish 0.771 0.618
#> History 0.784 0.598
#> PhysicalEducation -0.959 0.158The principal plane represents the students using the first two Riemannian components. In this example, no clusters are used because the objective is to explore the structure of the data without predefined groups.
riem.plot(
data = data.analysis,
choix = "ind",
components = components,
explained.inertia = inertia,
title = "Student grades"
)The correlation circle helps interpret how the subjects are related to the first two Riemannian components.
riem.plot(
data = data.analysis,
choix = "var",
correlations = loadings,
explained.inertia = inertia,
title = "Student grades"
)The biplot combines the principal plane of the students with the variable arrows, allowing the structure of the observations and the interpretation of the subjects to be explored in the same figure.
riem.biplot(
data = data.analysis,
components = components,
correlations = loadings,
explained.inertia = inertia,
title = "Student grades"
)This example shows how to apply riemannianStats to a
small and simple data set. The workflow computes Riemannian
similarities, distances, correlations, and principal components in order
to explore the structure of the grades and reduce the dimensionality of
the data.