r - 日志转换后如何在 ggplot 的图例中保留 0 值?
问题描述
如果我trans="log"
在scale_fill_viridis
或其他连续刻度中使用,如何在图表图例上添加 NA 或“0”标签
> d1
persona num.de.puntos puntos
1 p1 1 3
2 p1 2 4
3 p1 3 0
4 p1 4 4
5 p1 5 2
6 p2 1 2
7 p2 2 3
8 p2 3 0
9 p2 4 0
10 p2 5 4
11 p3 1 0
12 p3 2 1
13 p3 3 0
14 p3 4 5
15 p3 5 8
p <- ggplot(d1, aes(persona, num.de.puntos, fill = puntos)) +
scale_fill_viridis(trans="log", option ="D", direction=1, na.value = "gray50",
breaks=c(0,1,5,8),
name="Number of people",
guide=guide_legend(label.position = "bottom",
title.position = 'top',
nrow=1,
label.theme = element_text(size = 6,
face = "bold",
color = "black"),
title.theme = element_text(size = 6,
face = "bold",
color = "black"))) +
geom_tile(colour="grey", show.legend = TRUE)
p
我想
解决方案
注意:下面的代码在 R 3.5.1 和 ggplot2 3.1.0 中运行。您可能使用的是旧版本的 ggplot2 包,因为您的代码使用scale_fill_viridis
而不是scale_fill_viridis_c
.
TL;DR 解决方案:
我很确定这不是正统的,但假设你的情节被命名为p
,设置:
p$scales$scales[[1]]$is_discrete <- function() TRUE
将在您的图例中获得 NA 值,而无需更改任何现有的填充美学映射。
示范:
p <- ggplot(d1, aes(persona, num.de.puntos, fill = puntos)) +
scale_fill_viridis_c(trans="log", option ="D", direction=1,
na.value = "gray50", # optional, change NA colour here
breaks = c(0, 1, 5, 8),
labels = c("NA label", "1", "5", "8"), # optional, change NA label here
name="Number of people",
guide=guide_legend(label.position = "bottom",
title.position = 'top',
nrow=1,
label.theme = element_text(size = 6,
face = "bold",
color = "black"),
title.theme = element_text(size = 6,
face = "bold",
color = "black"))) +
geom_tile(colour = "grey", show.legend = TRUE)
p # no NA mapping
p$scales$scales[[1]]$is_discrete <- function() TRUE
p # has NA mapping
说明:
我通过转换p
为 grob 对象(通过ggplotGrob
)深入研究了绘图机制,并debug()
在影响绘图过程中图例生成部分的函数上运行。
通过ggplot2:::ggplot_gtable.ggplot_built
、ggplot2:::build_guides
和调试后ggplot2:::guides_train
,我得到ggplot2:::guide_train.legend
了包中未导出的函数ggplot2
:
> ggplot2:::guide_train.legend
function (guide, scale, aesthetic = NULL)
{
breaks <- scale$get_breaks()
if (length(breaks) == 0 || all(is.na(breaks))) {
return()
}
key <- as.data.frame(setNames(list(scale$map(breaks)), aesthetic %||%
scale$aesthetics[1]), stringsAsFactors = FALSE)
key$.label <- scale$get_labels(breaks)
if (!scale$is_discrete()) {
limits <- scale$get_limits()
noob <- !is.na(breaks) & limits[1] <= breaks & breaks <=
limits[2]
key <- key[noob, , drop = FALSE]
}
if (guide$reverse)
key <- key[nrow(key):1, ]
guide$key <- key
guide$hash <- with(guide, digest::digest(list(title, key$.label,
direction, name)))
guide
}
我一直看到这key$.label <- scale$get_labels(breaks)
一步,key
看起来像这样:
> key
fill .label
1 gray50 NA label
2 #440154 1
3 #72CC59 5
4 #FDE725 8
但是scale$is_discrete()
is FALSE
,所以!scale$is_discrete()
is TRUE
,并且对应于 NA 值的行在key
下一步中被删除,因为在对数转换后填充比例的中断中有一个 NA 值:
> scale$get_breaks()
[1] NA 0.000000 1.609438 2.079442
因此,如果我们可以用scale$is_discrete()
评估来TRUE
代替FALSE
,这一步将被跳过,我们最终得到包括 NA 值的完整图例。
推荐阅读
- r - 不知道为什么 eigen() 给出了一个错误符号的向量,而加载矩阵只是向量
- javascript - 声明时 const 存储在哪里?
- mysql - mysql 5.6 的自定义 json_extract 函数无法按预期工作
- c# - 改变弹丸角度
- html - 未应用角度中 ng5-slider 的样式
- php - 在 php 中每三个结果后显示横幅广告图片
- ag-grid - 如何将值发送到下拉单元格编辑器?
- adobe - 每次对项目进行更改时,是否可以在 After Effects HTML 面板中获取通知/事件?
- java - Primefaces LineChart 未显示正确的日期值(谷歌浏览器)
- android - 导出 .apk 文件时出现问题(无法访问数字证书 - 无法加载证书)