哪些因素会影响 ggplot 图例的排序方式
What factors effect how ggplot legends are ordered
我正在 R 中创建一个散点图,用户可以在其中添加或删除显示固定参考值的水平线。这样做时,我注意到更改参考线的名称会重新排列图例,因此水平线有时会出现在散点图例元素之前,有时会出现在散点图例元素之后。
比较:
到
下面是一个可重现的例子
YEAR = as.integer(rep(2010:2020,5))
SERIES_NAME = rep(LETTERS[1:5], each = 11)
OBS_VALUE = runif(n = 55, min = -5, max = 20)
EA = ifelse(SERIES_NAME=='A', 'Option 1', 'Option 2')
df <- data.frame(YEAR=YEAR,
SERIES_NAME=SERIES_NAME,
OBS_VALUE=OBS_VALUE,
EA=EA)
注释掉两条线中的一条以生成图表,在其中命名图例上的水平线。
aaaaaaa <- "RGCUZYMSFP" # appears above
aaaaaaa <- "IZTCYUXGBO" # appears below
然后生成图表:
df %>%
select(YEAR,SERIES_NAME, OBS_VALUE, EA) %>%
ggplot() +
ggplot2::geom_point(
ggplot2::aes(
x = YEAR,
y = OBS_VALUE,
col = EA),
size = 2) +
ggplot2::guides(
color = ggplot2::guide_legend(nrow = 2,
byrow = TRUE))+
scale_linetype_manual(values = 2) +
scale_x_continuous(breaks = seq(2010,2020,5))+
geom_hline(aes(yintercept = EAMean,
linetype = aaaaaaa),
size = 1, color = "black")
我还注意到更改变量的名称会更改输出。如果我将变量的名称从 aaaaaaaa
(字母 a 的 8 倍)更改为 aaaaaaa
(字母 a 的 7 倍)并相应地更新水平线的代码,图例将重新排序
有什么方法可以让我更一致地控制图例项目的去向?
正如@stefan 正确指出的那样,它取决于 'secret algorithm'。如果未设置 'order',则算法的结果是不可预测的,但我们可以对其进行逆向工程。
在 guide_legend()
方法的 these lines 中,我们看到构建的 'hash' 对于指南的标题、标签、方向和名称是(相对)唯一的。这里的不可预测性在于散列,它可以为相对相似(但不相同)的输入创建广泛不同的散列。
稍后,在 guides_merge()
内部函数中,我们可以看到指南(或指南定义)在其散列上被拆分。由于哈希对相同的输入产生相同的结果,这会指示 ggplot2 这些指南是否 'mergeable' 由于共享标题、标签、方向和名称。
'order' 参数的作用是将 'order' 粘贴在散列前面,因此在字典顺序中 order = 0
的指南位于 [=13= 的指南之前].未设置顺序参数的指南将获得 99
作为顺序。因为拆分 returns 会根据拆分级别产生排序顺序,这有效地首先对输出进行排序,其次是散列。
我正在 R 中创建一个散点图,用户可以在其中添加或删除显示固定参考值的水平线。这样做时,我注意到更改参考线的名称会重新排列图例,因此水平线有时会出现在散点图例元素之前,有时会出现在散点图例元素之后。
比较:
到
下面是一个可重现的例子
YEAR = as.integer(rep(2010:2020,5))
SERIES_NAME = rep(LETTERS[1:5], each = 11)
OBS_VALUE = runif(n = 55, min = -5, max = 20)
EA = ifelse(SERIES_NAME=='A', 'Option 1', 'Option 2')
df <- data.frame(YEAR=YEAR,
SERIES_NAME=SERIES_NAME,
OBS_VALUE=OBS_VALUE,
EA=EA)
注释掉两条线中的一条以生成图表,在其中命名图例上的水平线。
aaaaaaa <- "RGCUZYMSFP" # appears above
aaaaaaa <- "IZTCYUXGBO" # appears below
然后生成图表:
df %>%
select(YEAR,SERIES_NAME, OBS_VALUE, EA) %>%
ggplot() +
ggplot2::geom_point(
ggplot2::aes(
x = YEAR,
y = OBS_VALUE,
col = EA),
size = 2) +
ggplot2::guides(
color = ggplot2::guide_legend(nrow = 2,
byrow = TRUE))+
scale_linetype_manual(values = 2) +
scale_x_continuous(breaks = seq(2010,2020,5))+
geom_hline(aes(yintercept = EAMean,
linetype = aaaaaaa),
size = 1, color = "black")
我还注意到更改变量的名称会更改输出。如果我将变量的名称从 aaaaaaaa
(字母 a 的 8 倍)更改为 aaaaaaa
(字母 a 的 7 倍)并相应地更新水平线的代码,图例将重新排序
有什么方法可以让我更一致地控制图例项目的去向?
正如@stefan 正确指出的那样,它取决于 'secret algorithm'。如果未设置 'order',则算法的结果是不可预测的,但我们可以对其进行逆向工程。
在 guide_legend()
方法的 these lines 中,我们看到构建的 'hash' 对于指南的标题、标签、方向和名称是(相对)唯一的。这里的不可预测性在于散列,它可以为相对相似(但不相同)的输入创建广泛不同的散列。
稍后,在 guides_merge()
内部函数中,我们可以看到指南(或指南定义)在其散列上被拆分。由于哈希对相同的输入产生相同的结果,这会指示 ggplot2 这些指南是否 'mergeable' 由于共享标题、标签、方向和名称。
'order' 参数的作用是将 'order' 粘贴在散列前面,因此在字典顺序中 order = 0
的指南位于 [=13= 的指南之前].未设置顺序参数的指南将获得 99
作为顺序。因为拆分 returns 会根据拆分级别产生排序顺序,这有效地首先对输出进行排序,其次是散列。