← 返回 Tessera
散点5 张图iris(Tessera Toy,150 行 × 3 个物种)2026-08-11

grouped_scatter

两个连续变量之间是什么关系;有分组时,怎样用形状或颜色把组标出来?

需要的输入
2 个连续变量,同一批观测;可选 1 个分组变量
示例数据
iris(Tessera Toy,150 行 × 3 个物种)
依赖
ggplot2 · ggpubr · biopalette
配色
walter_white2
成图预览另有 4 张在配方里
grouped_scatter

什么时候用它

散点图是两个连续变量最直接的入口:一行数据一个点,横轴一个变量,纵轴另一个变量。先看点云有没有方向、弯曲、分团、离群和重叠,再决定是否需要相关系数或拟合模型。

分组不是散点图的必需部分。没有真实分组就画普通散点;有分组时,再从形状、颜色或两者共同编码中选择一种。

怎么读

  1. 先看整体形状。 点云是上升、下降、弯曲,还是没有明显方向。
  2. 看组内聚集。 同一种颜色是否聚在相近区域,组间是否分开或重叠。
  3. 再看离散程度。 同一组内部的点散得多宽,是否存在次级结构。
  4. 找离群点。 尤其注意远离本组主体、可能改变后续相关或回归结果的观测。

常见陷阱

  • 一上来就画拟合线。 线会先替读者总结点云,弯曲、分团和离群反而容易被略过。普通散点先画干净,需要模型时再去 scatter_fit
  • 同一张图塞太多视觉变量。 颜色和形状分别映射两个不同分组时,读者要同时解两套图例,信息密度很快失控。
  • 形状分组太多。 人能稳定区分的点形有限;超过五六组后,颜色通常更清楚。
  • 点太大或不透明。 重叠观测会被完全遮住。先减小点,再适当降低 alpha;数据很多时考虑 hexbin 或二维密度,而不是无限缩小点。
  • 点太小。 导出后缩进论文双栏或幻灯片,原本勉强可见的小点会直接消失。点大小要按最终版面判断,不按 RStudio 预览窗口判断。
  • 把分类变量当连续变量。 Species 必须是 factor;如果分组在数据里写成 1、2、3,也应先转成 factor,否则会得到连续色条。

配色

三个物种是三个无序类别,使用定性色板 walter_white2 中区分较清楚的青、橄榄和橙三色。这里只有三个真实分组,不为了展示完整五色增加虚假类别。

浅色点在白底上容易消失,所以颜色版统一使用带深色细边的圆点。边线只负责保持轮廓,不编码第二个变量。

配方

方法绘图系统什么时候选它
Ageom_point()ggplot2只看两个连续变量的关系,没有分组要表达
Baes(shape = group)ggplot2黑白输出,或不希望颜色承担信息
Caes(fill = group)ggplot2屏幕和彩色输出;通常是分组散点最清楚的做法
Daes(fill = group, shape = group)ggplot2颜色辨认可能受限,需要用同一个分组变量做冗余编码
Egeom_point(size = ...)ggplot2根据点数、重叠程度和最终画布调整点的视觉重量

数据与公共样式

iris 已收进 Tessera Toy。Petal length 与 Petal width 能让三个物种形成清楚但并非完全无重叠的点群,比 Orange 的重复测量结构更适合演示分组散点。

library(ggplot2)
library(ggpubr)
library(biopalette)

d <- read.csv("content/tessera/data/csv/iris.csv")
d$Species <- factor(
  d$Species,
  levels = c("setosa", "versicolor", "virginica")
)

walter_white2 <- get_palette("walter_white2", type = "qualitative")
species_colors <- setNames(
  walter_white2[c(1, 2, 4)],
  levels(d$Species)
)
species_shapes <- setNames(c(21, 22, 24), levels(d$Species))

scatter_scales <- list(
  scale_x_continuous(
    breaks = 1:7,
    limits = c(0.9, 7.1),
    expand = expansion(mult = c(0, 0))
  ),
  scale_y_continuous(
    breaks = seq(0, 2.5, 0.5),
    limits = c(-0.05, 2.55),
    expand = expansion(mult = c(0, 0))
  )
)

scatter_theme <- theme_pubr(base_size = 13, legend = "right") +
  theme(
    panel.grid.major = element_line(color = "#E5E3DC", linewidth = 0.35),
    panel.grid.minor = element_blank(),
    axis.line = element_line(color = "#333330", linewidth = 0.45),
    axis.ticks = element_line(color = "#333330", linewidth = 0.4),
    plot.title = element_text(face = "bold", size = 15, hjust = 0),
    legend.title = element_text(face = "bold"),
    legend.key.height = grid::unit(5, "mm"),
    strip.background = element_blank(),
    strip.text = element_text(face = "bold"),
    plot.margin = margin(14, 16, 12, 12)
  )

A · 普通散点

没有分组要表达时,只画点。不要为了“丰富”画面主动加入颜色或形状。

#| fig: basic
#| fig-width: 7.4
#| fig-height: 5.1
ggplot(d, aes(Petal.Length, Petal.Width)) +
  geom_point(size = 2.7, alpha = 0.72, color = "#333330") +
  scatter_scales +
  labs(
    title = "Iris petal measurements",
    x = "Petal length (cm)",
    y = "Petal width (cm)"
  ) +
  scatter_theme
grouped_scatter — basic
grouped_scatter-basic

B · 用形状分组

形状适合黑白输出,也适合颜色不能承担信息的场景。三个物种的点云聚集位置不同,因此即使没有颜色也能读出分组结构。

#| fig: shape
#| fig-width: 7.4
#| fig-height: 5.1
ggplot(d, aes(Petal.Length, Petal.Width, shape = Species)) +
  geom_point(size = 3.1, alpha = 0.72, color = "#333330", stroke = 0.7) +
  scale_shape_manual(values = species_shapes) +
  scatter_scales +
  labs(
    title = "Grouped by shape",
    x = "Petal length (cm)",
    y = "Petal width (cm)",
    shape = "Species"
  ) +
  scatter_theme
grouped_scatter — shape
grouped_scatter-shape

C · 用颜色分组

这是彩色输出下最直接的分组方案。所有点保持同一种圆形,读者只需要解一套颜色图例;同色点在空间上形成点群,分组关系会比 Orange 示例清楚得多。

#| fig: color
#| fig-width: 7.4
#| fig-height: 5.1
ggplot(d, aes(Petal.Length, Petal.Width, fill = Species)) +
  geom_point(
    shape = 21,
    size = 3.2,
    alpha = 0.82,
    color = "#333330",
    stroke = 0.55
  ) +
  scale_fill_manual(values = species_colors) +
  scatter_scales +
  labs(
    title = "Grouped by color",
    x = "Petal length (cm)",
    y = "Petal width (cm)",
    fill = "Species"
  ) +
  scatter_theme
grouped_scatter — color
grouped_scatter-color

D · 形状与颜色共同分组

两种通道必须映射同一个变量。这样没有增加新的信息,只是让分组在色觉差异、灰度打印或投影偏色时仍然可辨。普通屏幕展示优先使用 C;确实需要冗余编码时再用这一版。

#| fig: color-shape
#| fig-width: 7.4
#| fig-height: 5.1
ggplot(d, aes(Petal.Length, Petal.Width, fill = Species, shape = Species)) +
  geom_point(
    size = 3.2,
    alpha = 0.82,
    color = "#333330",
    stroke = 0.6
  ) +
  scale_fill_manual(values = species_colors) +
  scale_shape_manual(values = species_shapes) +
  scatter_scales +
  labs(
    title = "Color + shape",
    x = "Petal length (cm)",
    y = "Petal width (cm)",
    fill = "Species",
    shape = "Species"
  ) +
  scatter_theme
grouped_scatter — color-shape
grouped_scatter-color-shape

E · 调整点大小

size 控制的是点的直径感,而不是简单的装饰。点太小,缩放后消失;点太大,组内密集区域会糊在一起。下面复制同一份数据做三个分面,只改变 geom_point() 的大小,颜色、透明度和坐标完全相同。

#| fig: point-size
#| fig-width: 11
#| fig-height: 4.2
size_settings <- data.frame(
  size_label = factor(
    c("size = 1.5", "size = 3", "size = 5"),
    levels = c("size = 1.5", "size = 3", "size = 5")
  ),
  point_size = c(1.5, 3, 5)
)

size_demo <- merge(d, size_settings)

ggplot(
  size_demo,
  aes(Petal.Length, Petal.Width, fill = Species, size = point_size)
) +
  geom_point(shape = 21, alpha = 0.78, color = "#333330", stroke = 0.5) +
  facet_wrap(~size_label, nrow = 1) +
  scale_fill_manual(values = species_colors) +
  scale_size_identity() +
  scatter_scales +
  guides(fill = "none") +
  labs(
    title = "Point size changes overlap and visual weight",
    x = "Petal length (cm)",
    y = "Petal width (cm)"
  ) +
  scatter_theme +
  theme(plot.title = element_text(size = 14))
grouped_scatter — point-size
grouped_scatter-point-size

这里 size = 3 是这份数据和当前画布的平衡点,不是通用默认值。样本量、重叠程度、输出尺寸和导出后的缩放比例变了,都应重新判断。

五种方法怎么选

  1. 没有分组,选 A。
  2. 黑白输出或不能使用颜色,选 B。
  3. 常规彩色图,选 C。
  4. 需要无障碍或灰度兼容,才选 D;不要把颜色和形状分别映射到两个不同变量。
  5. 最后根据点数和最终版面调整 size;不要把预览窗口里的默认值当成成品参数。
运行环境4 个包 · 2026-08-11

R version 4.5.1 (2025-06-13 ucrt) · x86_64-w64-mingw32

  • biopalette 0.1.0
  • ggplot2 4.0.3
  • ggpubr 0.6.2
  • grid 4.5.1