使用 ggplot 在对数刻度上绘制小中断
Plotting minor breaks on a log scale with ggplot
为了 ggplot
在对数刻度上正确绘制小断点,我必须这样做:
faceplant1 <- function(x) {
return (c(x[1]*10^.25, x[2]/10^.25))
}
faceplant2 <- function(x) {
return (rep(seq(1,9),5)*rep(10^seq(-6,-2), each=9))
}
ggplot(mydata, aes(x=myseries)) +
geom_density() +
scale_x_log10(limits=c(1e-6, 1e-1),
breaks=10^seq(-6,-1),
minor_breaks=trans_breaks(faceplant1, faceplant2, n=45))
有没有更简单的方法来实现这个?
最终结果应如下所示:
这是我对这个问题的解决方案:
library(ggplot2)
log10_minor_break = function (...){
function(x) {
minx = floor(min(log10(x), na.rm=T))-1;
maxx = ceiling(max(log10(x), na.rm=T))+1;
n_major = maxx-minx+1;
major_breaks = seq(minx, maxx, by=1)
minor_breaks =
rep(log10(seq(1, 9, by=1)), times = n_major)+
rep(major_breaks, each = 9)
return(10^(minor_breaks))
}
}
mydata = data.frame(myseries = 10^(rnorm(1e4, mean=0, sd=0.5)))
myplot =
ggplot(mydata, aes(x=myseries))+
geom_density()+
scale_x_log10(minor_breaks=log10_minor_break())+
theme(panel.grid.major.x = element_line(size=1.0),
panel.grid.minor.x = element_line(size=2))
myplot
它与您已经完成的非常相似,但普遍适用。
还有一个小改进:在您的示例中,它会扩展 1e-6 以下和 1e-1 以上的小中断。
我从查看函数 trans_break
开始,并将其简化为最基本的元素。
annotation_logticks() 函数也值得考虑:
myplot+annotation_logticks(side="b")
多年后:我已将@gvrocha 的回答改编为(甚至更)通用。
log_breaks = function(maj, radix=10) {
function(x) {
minx = floor(min(logb(x,radix), na.rm=T)) - 1
maxx = ceiling(max(logb(x,radix), na.rm=T)) + 1
n_major = maxx - minx + 1
major_breaks = seq(minx, maxx, by=1)
if (maj) {
breaks = major_breaks
} else {
steps = logb(1:(radix-1),radix)
breaks = rep(steps, times=n_major) +
rep(major_breaks, each=radix-1)
}
radix^breaks
}
}
scale_x_log_eng = function(..., radix=10) {
scale_x_continuous(...,
trans=log_trans(radix),
breaks=log_breaks(TRUE, radix),
minor_breaks=log_breaks(FALSE, radix))
}
scale_y_log_eng = function(..., radix=10) {
scale_y_continuous(...,
trans=log_trans(radix),
breaks=log_breaks(TRUE, radix),
minor_breaks=log_breaks(FALSE, radix))
}
那么用法更优雅:
ggplot(...) +
geom_line() +
scale_x_log_eng() +
scale_y_log_eng()
我想说最简单的解决方案是使用 annotation_logticks() 并将短、中和长参数排列到 mimic 网格线,然后删除网格线并使用适当的比例来绘制数据。例如,
annotation_logticks(short = unit(1, "npc"), mid = unit(1, "npc"), long = unit(1,"npc"), ...) +
theme(panel.grid = element_blank()) +
scale_x_log10(breaks = 10^(seq(-6,-1,1)), limits = c(10^-6, 0.1),...)
为了 ggplot
在对数刻度上正确绘制小断点,我必须这样做:
faceplant1 <- function(x) {
return (c(x[1]*10^.25, x[2]/10^.25))
}
faceplant2 <- function(x) {
return (rep(seq(1,9),5)*rep(10^seq(-6,-2), each=9))
}
ggplot(mydata, aes(x=myseries)) +
geom_density() +
scale_x_log10(limits=c(1e-6, 1e-1),
breaks=10^seq(-6,-1),
minor_breaks=trans_breaks(faceplant1, faceplant2, n=45))
有没有更简单的方法来实现这个?
最终结果应如下所示:
这是我对这个问题的解决方案:
library(ggplot2)
log10_minor_break = function (...){
function(x) {
minx = floor(min(log10(x), na.rm=T))-1;
maxx = ceiling(max(log10(x), na.rm=T))+1;
n_major = maxx-minx+1;
major_breaks = seq(minx, maxx, by=1)
minor_breaks =
rep(log10(seq(1, 9, by=1)), times = n_major)+
rep(major_breaks, each = 9)
return(10^(minor_breaks))
}
}
mydata = data.frame(myseries = 10^(rnorm(1e4, mean=0, sd=0.5)))
myplot =
ggplot(mydata, aes(x=myseries))+
geom_density()+
scale_x_log10(minor_breaks=log10_minor_break())+
theme(panel.grid.major.x = element_line(size=1.0),
panel.grid.minor.x = element_line(size=2))
myplot
它与您已经完成的非常相似,但普遍适用。 还有一个小改进:在您的示例中,它会扩展 1e-6 以下和 1e-1 以上的小中断。
我从查看函数 trans_break
开始,并将其简化为最基本的元素。
annotation_logticks() 函数也值得考虑:
myplot+annotation_logticks(side="b")
多年后:我已将@gvrocha 的回答改编为(甚至更)通用。
log_breaks = function(maj, radix=10) {
function(x) {
minx = floor(min(logb(x,radix), na.rm=T)) - 1
maxx = ceiling(max(logb(x,radix), na.rm=T)) + 1
n_major = maxx - minx + 1
major_breaks = seq(minx, maxx, by=1)
if (maj) {
breaks = major_breaks
} else {
steps = logb(1:(radix-1),radix)
breaks = rep(steps, times=n_major) +
rep(major_breaks, each=radix-1)
}
radix^breaks
}
}
scale_x_log_eng = function(..., radix=10) {
scale_x_continuous(...,
trans=log_trans(radix),
breaks=log_breaks(TRUE, radix),
minor_breaks=log_breaks(FALSE, radix))
}
scale_y_log_eng = function(..., radix=10) {
scale_y_continuous(...,
trans=log_trans(radix),
breaks=log_breaks(TRUE, radix),
minor_breaks=log_breaks(FALSE, radix))
}
那么用法更优雅:
ggplot(...) +
geom_line() +
scale_x_log_eng() +
scale_y_log_eng()
我想说最简单的解决方案是使用 annotation_logticks() 并将短、中和长参数排列到 mimic 网格线,然后删除网格线并使用适当的比例来绘制数据。例如,
annotation_logticks(short = unit(1, "npc"), mid = unit(1, "npc"), long = unit(1,"npc"), ...) +
theme(panel.grid = element_blank()) +
scale_x_log10(breaks = 10^(seq(-6,-1,1)), limits = c(10^-6, 0.1),...)