1. 全部群架边框
library(ggplot2)
library(shadowtext)
library(ggrepel)
library(ggunchull)
head(iris)
# 计算每个species的边框
# setup a proper distance to extend (and simplify) the circle (here use 3% of the range of x axis)
delta_r <- 0.03
th_r <- 0.03
delta <- diff(range(iris$Sepal.Length)) * delta_r # 3% of the range of x axis
th <- diff(range(iris$Sepal.Width)) * th_r # 3% of the range of y axis
# 计算每个物种类型的中位数
species_type_med <- iris |>
dplyr::group_by(Species) |>
dplyr::summarise(
length_median = median(Sepal.Length), # x轴中位数
width_median = median(Sepal.Width) # y轴中位数
)
species_type_med
# 为数据添加微小的随机扰动
iris_jittered <- iris
set.seed(123) # 设置随机种子以确保结果可重现
iris_jittered$Sepal.Length <- iris_jittered$Sepal.Length + rnorm(nrow(iris_jittered), 0, 0.001)
iris_jittered$Sepal.Width <- iris_jittered$Sepal.Width + rnorm(nrow(iris_jittered), 0, 0.001)
# 使用添加扰动后的数据绘图
ggplot(iris_jittered, aes(x = Sepal.Length, y = Sepal.Width, fill = Species)) +
geom_point(size = 3, shape = 21, color = "black") +
stat_unchull(
aes(color = Species, fill = Species), # 按Species着色和填充
alpha = 0.3, # 设置透明度为 0.3
delta = delta, # 使用计算的 x 轴扩展距离
th = th, # 使用计算的 y 轴扩展距离
n = 5 # 设置平滑度(控制边界的圆滑程度)
) +
geom_shadowtext(
aes(x = length_median, y = width_median, label = Species),
fontface = "bold",
color = "black",
bg.colour='white',
data = species_type_med,
point.padding = unit(0.5, "lines")
) +
theme_classic() +
theme(
axis.line = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
axis.title = element_blank()
)

image.png
2. 指定群架边框
# 特定群加边框
# 使用添加扰动后的数据绘图
ggplot(iris_jittered, aes(x = Sepal.Length, y = Sepal.Width, fill = Species)) +
geom_point(size = 3, shape = 21, color = "black") +
stat_unchull(data = subset(iris_jittered, Species == "setosa"),
aes(color = Species, fill = Species), # 按Species着色和填充
alpha = 0.3, # 设置透明度为 0.3
delta = delta, # 使用计算的 x 轴扩展距离
th = th, # 使用计算的 y 轴扩展距离
n = 5 # 设置平滑度(控制边界的圆滑程度)
) +
geom_shadowtext(
aes(x = length_median, y = width_median, label = Species),
fontface = "bold",
color = "black",
bg.colour='white',
data = species_type_med,
point.padding = unit(0.5, "lines")
) +
theme_classic() +
theme(
axis.line = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
axis.title = element_blank()
)

image.png