annotation_logticks()是一个很棒的小函数,它在对数刻度轴as shown here上添加了较小的刻度线。
默认情况下,该函数在绘图面板区域的内部绘制刻度线。例如,如果在y轴上,刻度线会出现在轴线的右侧;如果在x轴上,刻度线出现在轴线上方。
对于大多数绘图情况,我认为此默认设置是不可取的。到目前为止,我还没有找到一种简单的方法来使这些较小的刻度线显示在常规ggplot2刻度线所在的面板区域的外部。因此,例如在y轴上显示在该行的左侧,而不是在右侧。有一个简单的解决方案吗?
对于需要在主要刻度线之间进行插值的绘图情况,将其显示在常规ggplot2标签和刻度线的左侧通常是一个很好的选择。我还没有找到一种解决方案,该解决方案不涉及完全剪切或放弃注解_logticks(),并且仅对刻度线长度使用负值还没有成功。
以下是直接来自ggplot2网站示例的代码:
a <- ggplot(msleep, aes(bodywt, brainwt)) +
geom_point(na.rm = TRUE) +
scale_x_log10(
breaks = scales::trans_breaks("log10", function(x) 10^x),
labels = scales::trans_format("log10", scales::math_format(10^.x))
) +
scale_y_log10(
breaks = scales::trans_breaks("log10", function(x) 10^x),
labels = scales::trans_format("log10", scales::math_format(10^.x))
) +
theme_bw()
a + annotation_logticks()
我正在寻找一个将刻度线翻转到轴线另一侧的结果。
答案 0 :(得分:1)
据我所知,是的,但是有点毛病。 TLDR ::
b <- a +
# reverse ticks
annotation_logticks(short=unit(-0.1, "cm"), mid=unit(-0.2, "cm"), long=unit(-0.3,"cm")) +
# remove clipping
coord_cartesian(clip="off") +
# add space between ticks and labels
theme(axis.text.x=element_text(margin = margin(t = 10)), axis.text.y=element_text(margin = margin(r = 10)))
# get the limits of the panel in data coordinates
bb <- ggplot_build(b)$layout$panel_params[[1]]
# draw a white rectangle to cover up the additional tick marks, gross
# the coordinates are actually in powers of 10 of the data
b +
annotation_custom(
grob=rectGrob(gp=gpar(col=NA)),
# the min values are -100 ie "something very large and negative"
# the max values are the bottom-left corner of the plot plus a tiny
# fudge factor to cover up the stubs of the ticks (gross)
xmin=-100, xmax=min(ab$x.range) + 0.01,
ymax=min(ab$y.range) + 0.01, ymin=-100
)
收益
您必须在annotation_custom
中加上0.01和-100。
如果您在控制台中查看annotation_logticks
,则它具有
layer(data = dumy_data(), # more stuff,
geo = GeomLogticks, # lots more stuff
ggplot2:::GeomLogticks
(它不是导出函数,因此要检查的三元组:::
)显示了一个具有各种功能的对象,它们可以绘制刻度线。反复试验表明,ggplot2:::GeomLogticks$draw_panel
似乎是完成所有工作的函数。看起来,此函数使数据框具有每个刻度(!)的xstart,xend,ystart,¥ d坐标。
例如该功能主体的摘要
if (grepl("l", sides)) {
ticks$y_l <- with(data, segmentsGrob(y0 = unit(yticks$y,
"native"), y1 = unit(yticks$y, "native"), x0 = unit(yticks$start,
"cm"), x1 = unit(yticks$end, "cm"), gp = gpar(col = alpha(colour,
alpha), lty = linetype, lwd = size * .pt)))
}
据此,我们似乎可以为annotation_logticks
提供负长度
a2 <- a + annotation_logticks(short=unit(-0.1, "cm"), mid=unit(-0.2, "cm"), long=unit(-0.3,"cm"))
a2
这实际上并没有用,如果您斜视一下就可以看到所有刻度线的存根。看来勾号已正确绘制,但它们已被面板区域裁剪。 (如果您暂时关闭面板边框a2 + theme(panel.border=element_rect(fill=NA, color=NA))
,则会看到这种情况。)
要关闭剪辑,您可以执行+ coord_cartesian(clip='off')
a3 <- a2 + coord_cartesian(clip='off')
a3
如?coord_cartesian
中针对clip
参数所述,这可能会导致“意外的结果”-刻度线的定义区域大于数据区域(我认为它们的整数幂为10,因此,如果最小的数据点是10的幂的一半,它仍然会一直向下计算到下一个较低的幂),因此应扩展到左下角之外。
解决此问题的一种总体方法是在图形的左下角部分(面板外部/边缘)绘制一个矩形以遮盖刻度线。 annotation_custom
这样做,但是需要数据坐标中的坐标。当使用这样的对数刻度时,坐标的幂为10,例如“ 10 ^ -4”是-4。
因此,要绘制矩形以掩盖多余的标记,我们需要使左下角基本上位于负无穷大处(图形的左下角),并且使右上角具有 minimum (最小)。 em>在X / Y轴上的值。
在annotation_custom
中,我们希望rectGrob
绘制一个矩形。默认情况下,它的背景为白色,但黑色边框则可以使用gpar(col=NA)
禁用。我们将xmin
和ymin
的坐标设置为-100(本质上是非常大且为负的坐标; -Inf
的意思是“最低轴值”)。我们可以将xmax
和ymax
坐标设置为最低轴值,-Inf
将为我们做这件事。
a3 +
annotation_custom(
grob=rectGrob(gp=gpar(col=NA)),
xmin=-100, xmax=-Inf,
ymax=-Inf, ymin=-100
)
对我来说,这并没有掩盖多余的刻度线,只留下令人讨厌的小点。
我真的希望xmax
和ymax
为-Inf + a little bit
,以掩盖整个刻度线。但是要做到这一点,我们不能再使用-Inf
作为“轴下限”的简写,我们必须使用
bb <- ggplot_build(b)$layout$panel_params[[1]]
# bb$x.range, bb$y.range
然后我们修改上面的
a4 <- a3 +
annotation_custom(
grob=rectGrob(gp=gpar(col=NA)),
xmin=-100, xmax=min(ab$x.range) + 0.01,
ymax=min(ab$y.range) + 0.01, ymin=-100
)
a4
(我通过反复试验发现了0.01,那不是很好)。
这很好,只不过X和Y轴标签碰到了刻度线。 要在标签和刻度线之间添加间距,请使用
a5 <- a4 + theme(axis.text.x=element_text(margin = margin(t = 10)),
axis.text.y=element_text(margin = margin(r = 10)))
a5
这些以像素为单位的边距(您可以更改单位,请参见?margin
)
产生您首先看到的图片。 您也许可以使其功能正常化,允许用户修改各种软糖系数(-100,+ 0.01和10像素的边距)。
答案 1 :(得分:0)
我找到了一种整齐的方法来解决此问题,尽管此解决方案的记号长度与annotation_logticks()
相同
logticks <- function(datavar,type) {
minimum <- 1/10^abs(floor(log10(min(datavar, na.rm=TRUE))))
maximum <- 1*10^abs(floor(log10(max(datavar, na.rm=TRUE)))+1)
multiple <- floor(log10(maximum/minimum))
yourtickvector <- c()
if (type=="breaks") {
yourtickvector <- c(minimum)
for (x in seq(0,multiple)) {
andadd <- seq(minimum*10^x,minimum*10^(x+1),minimum*10^x)[-1]
yourtickvector <- c(yourtickvector,andadd)
}
} else if (type=="labels") {
for (x in seq(0,multiple)) {
andadd <- c(minimum*10^x,rep("",8))
yourtickvector <- c(yourtickvector,andadd)
}
yourtickvector <- c(yourtickvector,minimum*10^multiple)
}
return(yourtickvector)
}
# only changed the breaks / label fields below to call the above function
a <- ggplot(msleep, aes(bodywt, brainwt)) +
geom_point(na.rm = TRUE) +
scale_x_log10(
breaks = logticks(msleep$bodywt,"breaks"),
labels = logticks(msleep$bodywt,"labels")
) +
scale_y_log10(
breaks = logticks(msleep$brainwt,"breaks"),
labels = logticks(msleep$brainwt,"labels")
) +
theme_bw()
a
答案 2 :(得分:0)
我意识到,如果您希望coord_cartesian
工作,则需要先在scale命令中设置“中断”,“限制”和“标签”:
scale_y_log10(breaks = c(0.1, 1, 10, 100, 1000, 10000,100000),limits = c(0.1,100000),labels=c(0.1, 1, 10, 100, 1000, 10000, "100000")) +
annotation_logticks(sides = "l", outside = T, short = unit(0.05, "cm"),mid = unit(0.05, "cm"),long = unit(0.2, "cm"))+
coord_cartesian(clip = "off")