PAYATHON 2026

UpSetR 如何按集合总频数调整行顺序,让 Fentanyl 位于顶部?

数据小陈

可以。对于这组数据,删除 intersections,再用 sets 和 keep.order = TRUE 指定行顺序即可。集合名称需要按图中从下到上的顺序传入。Lorazepam 与 PropofolTCI 的总频数相同,还需明确指定两者的先后位置。

为什么原来的排序没有生效?

在所核对的 UpSetR 源码中,只要提供了 intersections,函数就会通过下面的表达式取得集合名称:

Set_names <- unique(unlist(intersections))

这个分支不会采用传入的 sets。此时,keep.order = TRUE 保留的是集合名称在 intersections 中首次出现的顺序,所以反复调整 sets_ordered 不会改变行顺序。参见 UpSetR 的 upset() 源码。

矩阵中的第一个集合对应底部位置。因此,要让总频数最大的集合显示在顶部,应按总频数升序传入集合名称。参见 UpSetR 矩阵坐标的实现。

修改示例

原问题的 intersections 已列出示例数据中全部 20 个实际出现的组合,可以让 UpSetR 直接从数据计算交集,并用 nintersects = NA 显示全部交集。

在原问题的 input 定义之后运行:

library(UpSetR)

df <- fromExpression(input)

# df 仅包含集合的 0/1 指示列,列和就是各集合总频数
set_sizes <- colSums(df)

# 按总频数从小到大排列,对应图中从下到上的顺序
# 频数相同时,将 Lorazepam 放在前面,确保它位于底部
sets_bottom_to_top <- names(set_sizes)[
  order(set_sizes, names(set_sizes) != "Lorazepam")
]

upset_plot <- upset(
  df,
  sets = sets_bottom_to_top,
  keep.order = TRUE,
  nintersects = NA,
  order.by = c("freq", "degree"),
  decreasing = c(TRUE, FALSE),
  mb.ratio = c(0.6, 0.4),
  text.scale = c(1.2, 1.1, 1, 1, 1.1, 1),
  point.size = 3,
  line.size = 1,
  mainbar.y.label = "Number receiving drug (n)",
  sets.x.label = "Total number given drug (n)"
)

upset_plot

不要再对 sets_bottom_to_top 使用 rev(),否则频数较大的集合会被放到底部。

根据输入数据求和,各集合总频数为:

集合总频数
Fentanyl172
Propofol146
Ketamine53
Midazolam51
Alfentanil5
RemifentanilTCI2
PropofolTCI1
Lorazepam1

上述排序在图中从上到下与表中顺序一致。最后两个集合的频数并列,代码中的第二排序条件会把 Lorazepam 固定在底部。

原有的交集排序和着色怎么处理?

order.by 和 decreasing 控制交集列排序,sets 和 keep.order 控制集合行排序。示例继续使用原调用默认的交集排序规则;频数和交集集合数都相同时,列之间的先后顺序并未显式指定。

可以将原有的 queries = list(...) 加回绘图调用,以保留交集着色。需要先定义原代码引用的 col_single、col_two、col_three 和 col_four,这些颜色变量未包含在输入材料中。

如果实际数据还包含其他组合,而你只想显示 intersections 中指定的部分组合,删除该参数会扩大显示范围。上述简化方案适用于本题列出全部实际交集的情况;如果仍需保留交集筛选,应结合安装版本的实现处理,不能假定同时设置 sets 就能覆盖该分支的集合顺序。

备注:内容仅供参考。