Jellz
Jellz

Reputation: 455

How to plot the irregular shapes in a PCA plot?

I would like to visualize a fatty acid dataset applying PCA method, how could I draw the irregular shapes, rather than an ellipse area? I try to undersatand the ellipse.type in the PCA code, however, none of them could lead the aimed shapes in the figure.

The figure I would like to draw like: aimed PCA figure 1 aimed PCA figure 2

The example code:

# Load libraries
library(ggplot2)
library(dplyr)

# Assuming pca_data is the output from prcomp with PC1 and PC2 columns and 'group' for categories
# Replace 'your_data' with your actual data frame and 'group' with your actual grouping variable

# Example PCA data
pca_data <- data.frame(PC1 = rnorm(50), PC2 = rnorm(50), group = rep(c("A", "B", "C"), length.out = 50))

# Plot with smoother ellipses
ggplot(pca_data, aes(x = PC1, y = PC2, color = group, fill = group)) +
  geom_point(size = 3) +
  stat_ellipse(aes(group = group), level = 0.99, type = "t", linetype = "solid", alpha = 0.2) +
  labs(x = "PC1", y = "PC2") +
  theme_minimal()

Another example code using factoextra package:

fviz_pca_biplot(pca_data, 
                label="var", 
                labelsize=4,#FA text size
                col.var="black",#FA text color
                arrowsize=0.5,#arrow size
                repel=T,#avoid text overlapping
                pointsize=2.5,
                mean.point=F,
                habillage=Group,
                addEllipses=TRUE,
                #ellipse.type="convex",
                #ellipse.type="norm",
                ellipse.type="t",
                #ellipse.type="confidence",
                ellipse.level=0.75,
                alpha.ind=0.8,
                ellipse.alpha=0.1)

Upvotes: 1

Views: 75

Answers (2)

Stefano Barbi
Stefano Barbi

Reputation: 3184

Here is an approach similar to stefan that relies on the sf library.

library(ggplot2)
library(dplyr)
library(sf)

set.seed(123)

pca_data <- data.frame(PC1 = rnorm(50),
                       PC2 = rnorm(50),
                       group = rep(c("A", "B", "C"), length.out = 50))



pca_sf <- st_as_sf(pca_data, coords = c("PC1", "PC2")) |>
  group_by(group) |>
  summarise() |>
  st_concave_hull(0.01) |>
  st_buffer(dist = 0.2)


ggplot(pca_data) +
    geom_point(size = 3, aes(x = PC1, y = PC2, color = group, fill = group)) +
    labs(x = "PC1", y = "PC2") +
    geom_sf(data = pca_sf, aes(color = group), alpha = 0) +
    theme_minimal() 

res

Upvotes: 2

stefan
stefan

Reputation: 123903

Not exactly what you want, but one option would be to use ggforce::geom_mark_hull to draw a convex hull around the groups of points:

library(ggplot2)
library(ggforce)

set.seed(123)

pca_data <- data.frame(
  PC1 = rnorm(50), PC2 = rnorm(50),
  group = rep(c("A", "B", "C"), length.out = 50)
)

ggplot(pca_data, aes(x = PC1, y = PC2, color = group, fill = group)) +
  geom_point(size = 3) +
  ggforce::geom_mark_hull(aes(group = group),
    concavity = 0,
    radius = unit(5, "mm"),
  ) +
  labs(x = "PC1", y = "PC2") +
  theme_minimal() +
  coord_cartesian(clip = "off")

Upvotes: 5

Related Questions