如何定制 UpSet 图的数字标签、科学计数法、集合配色和粗体标签?
可以改用 ComplexUpset:通过交集标签参数调整数字显示,用 ggplot2 刻度函数设置科学计数法,通过集合查询设置配色,再单独修改矩阵面板中的集合名称字体。这些绘图组件可以分别配置,适合需要同时调整多个面板的情况。组件配置说明
先把集合列表转换为成员关系表
ComplexUpset 接收数据框:每行表示一个元素,每个集合对应一列,列值表示该元素是否属于该集合。可以继续使用 UpSetR::fromList() 转换现有的 combined,再把成员列转成逻辑值。
先运行问题中的 combined <- list(...),然后执行:
library(ggplot2)
library(ComplexUpset)
membership <- UpSetR::fromList(combined)
membership[] <- lapply(membership, as.logical)
set_order <- rev(c(
"c0_prt", "c0_24h", "c4_12w", "c5_12w", "c7_12w"
))
set_colors <- c(
c0_prt = "#4477AA",
c0_24h = "#EE6677",
c4_12w = "#228833",
c5_12w = "#CCBB44",
c7_12w = "#AA3377"
)
数据格式和集合排序参数可参见 ComplexUpset 数据接口。sort_sets = FALSE 会保留传入的集合顺序;如果显示方向与预期相反,调整 set_order 是否使用 rev() 即可。
定义科学计数法刻度函数
原代码定义了 fancy_scientific(),但没有将它应用到刻度上,所以图形不会因此改变。
下面的函数将有限非零值转换为 plotmath 表达式,让零直接显示为 0:
fancy_scientific <- function(x) {
labels <- vapply(x, function(value) {
if (is.na(value)) return("NA")
if (!is.finite(value) || value == 0) {
return(as.character(value))
}
parts <- strsplit(
sprintf("%.2e", value), "e", fixed = TRUE
)[[1]]
sprintf(
"%s %%*%% 10^{%d}",
parts[1], as.integer(parts[2])
)
}, character(1))
parse(text = labels)
}
%.2e 表示尾数保留两位小数。它只影响刻度文字,不改变计数或柱高,也不会把线性轴改成对数轴。
设置数字标签、集合颜色和粗体名称
下面的示例保留柱顶计数,缩小字号、旋转标签,并在顶部预留空间。每个集合使用一个 upset_query(set = ...),将颜色限制在集合大小柱和交集矩阵两个组件上;矩阵中的有效圆点会按对应集合着色。查询参数说明、矩阵着色实现
set_queries <- lapply(names(set_colors), function(set_name) {
ComplexUpset::upset_query(
set = set_name,
color = unname(set_colors[set_name]),
fill = unname(set_colors[set_name]),
only_components = c(
"overall_sizes", "intersections_matrix"
)
)
})
intersection_panel <- ComplexUpset::intersection_size(
counts = TRUE,
bar_number_threshold = 1,
text = list(
size = 2.6,
angle = 90,
hjust = 0,
vjust = 0.5
)
) +
scale_y_continuous(
labels = fancy_scientific,
expand = expansion(mult = c(0, 0.25))
)
p <- ComplexUpset::upset(
membership,
intersect = set_order,
sort_sets = FALSE,
sort_intersections = "descending",
sort_intersections_by = "cardinality",
mode = "distinct",
name = "Dataset",
width_ratio = 0.22,
base_annotations = list(
"Intersection size" = intersection_panel
),
set_sizes = (
ComplexUpset::upset_set_size() +
scale_y_continuous(labels = fancy_scientific)
),
queries = set_queries,
themes = ComplexUpset::upset_modify_themes(list(
"intersections_matrix" = theme(
axis.text.y = element_text(face = "bold")
)
))
)
print(p)
ggsave(
filename = "upset_custom.png",
plot = p,
width = 12,
height = 6,
units = "in",
dpi = 300
)
intersection_size() 的 text 参数会传给 geom_text();bar_number_threshold = 1 用于让标签保留在柱顶。集合名称位于矩阵的纵轴,因此可以修改 intersections_matrix 的 axis.text.y。交集标签参数、组件主题示例
集合大小面板在内部使用翻转坐标,所以示例对它使用 scale_y_continuous(),显示时对应横向数值轴。该面板可通过 upset_set_size() 单独配置。集合大小面板接口
数字仍然拥挤时如何调整
数字是否重叠取决于交集数量、标签长度和最终绘图宽度。示例中的字号、旋转角度和导出尺寸可以作为调整起点,但不能保证适用于所有数据。
如果希望保留全部数字,可以优先增大导出宽度。标签较短时,也可以把 angle 改成 0,同时调整对齐方式。如果顶部标签被裁切,可继续增加 expand 的上侧留白。
如果允许省略部分标签,可以在 text 列表中加入 check_overlap = TRUE。它会隐藏检测到重叠的标签,不会自动将标签移到其他位置。geom_text 重叠处理说明
代码中的科学计数法作用于轴刻度,柱顶标签仍然保留整数计数。给出的样例数值较小,整数刻度通常更容易阅读;实际计数较大时,再启用科学计数法更合适。
mode = "distinct" 表示按精确成员组合计数。例如,某根柱对应两个集合时,只统计属于这两个集合且不属于其他所选集合的元素,适合区分独有和不同共享组合的需求。示例配色可以替换为需要的颜色;同时加载 UpSetR 和 ComplexUpset 时,保留代码中的命名空间前缀,避免调用到同名的 upset()。
备注:内容仅供参考。
