我试图用GGPLOT2创建具有对数正态分布y缩放性能图表。 不幸的是,我不能够产生很好的蜱作为基本绘图功能。
这里我举的例子:
library(ggplot2)
library(scales)
# fix RNG
set.seed(seed=1)
# simulate returns
y=rnorm(999,0.02,0.2)
# M$Y are the cummulative returns (like an index)
M=data.frame(X=1:1000,Y=100)
for (i in 2:1000)
M[i,"Y"]=M[i-1,"Y"]*(1+y[i-1])
ggplot(M,aes(x=X,y=Y))+geom_line()+scale_y_continuous(trans=log_trans())
产生难看的蜱:
我也尝试:
ggplot(M,aes(x=X,y=Y)) + geom_line() +
scale_y_continuous(trans=log_trans(), breaks=pretty_breaks())
我怎样才能得到相同的符/蜱作为默认打印功能:
plot(M,type="l",log="y")
结果应该是这样的,但不与硬键入休息而是动态的。 我试着功能,如axisTicks()
但没有成功:
ggplot(M,aes(x=X,y=Y)) + geom_line() +
scale_y_continuous(trans=log_trans(), breaks=c(1,10,100,10000))
谢谢!
编辑:插入的图片
Answer 1:
该基地的图形行为可以使用自定义功能破裂转载:
base_breaks <- function(n = 10){
function(x) {
axisTicks(log10(range(x, na.rm = TRUE)), log = TRUE, n = n)
}
}
将此应用于示例数据给出相同的结果用trans_breaks('log10', function(x) 10^x)
:
ggplot(M, aes(x = X, y = Y)) + geom_line() +
scale_y_continuous(trans = log_trans(), breaks = base_breaks()) +
theme(panel.grid.minor = element_blank())
然而,我们可以使用上的数据的一个子集相同的功能,具有50和600之间的y值:
M2 <- subset(M, Y > 50 & Y < 600)
ggplot(M2, aes(x = X, y = Y)) + geom_line() +
scale_y_continuous(trans = log_trans(), breaks = base_breaks()) +
theme(panel.grid.minor = element_blank())
作为10的幂不再适合这里, base_breaks
产生替代漂亮的突破:
请注意,我已经关闭了次要网格线:在某些情况下,它才有意义有一半在y轴的主要网格线之间的网格线,但并非总是如此。
编辑
假设我们修改m,以便最小值为0.1:
M <- M - min(M) + 0.1
该base_breaks()函数还是蛮选择休息,但标签是在科学记数法,这可能不被视为“漂亮”:
ggplot(M, aes(x = X, y = Y)) + geom_line() +
scale_y_continuous(trans = log_trans(), breaks = base_breaks()) +
theme(panel.grid.minor = element_blank())
我们可以通过传递一个文本格式化函数来控制文本格式化labels
的参数scale_y_continuous
。 在这种情况下prettyNum
从基础包做这项工作很好:
ggplot(M, aes(x = X, y = Y)) + geom_line() +
scale_y_continuous(trans = log_trans(), breaks = base_breaks(),
labels = prettyNum) +
theme(panel.grid.minor = element_blank())
Answer 2:
当我对数刻度图施工,我发现了以下工作得很好:
g = ggplot(M,aes(x=X,y=Y)) + geom_line()
g + scale_y_continuous(trans = 'log10',
breaks = trans_breaks('log10', function(x) 10^x),
labels = trans_format('log10', math_format(10^.x)))
一对夫妇的不同之处:
- 轴标签显示为10的幂 - 我喜欢
- 次要网格线是主要的网格线的中间(比较该地块与Andrie的答案网格线)。
- x轴是更好。 出于某种原因,在Andrie的情节,x轴的范围是不同的。
为了让
Answer 3:
基座图形功能axTicks()
返回当前绘图轴断裂。 所以,你可以用它来恢复中断相同的基础图形。 唯一的缺点是,你必须先绘制图形基地情节。
library(ggplot2)
library(scales)
plot(M, type="l",log="y")
breaks <- axTicks(side=2)
ggplot(M,aes(x=X,y=Y)) + geom_line() +
scale_y_continuous(breaks=breaks) +
coord_trans(y="log")
Answer 4:
该功能可以同时指定主要和次要刻度线的所需数量。 它必须两次这种效果被指定:
#' log scale
#'
#' Creates a function which returns ticks for a given data range. It uses some
#' code from scales::log_breaks, but in contrast to that function it not only
#' the exponentials of the base b, but log minor ticks (f*b^i, where f and i are
#' integers), too.
#'
#' @param n Approximate number of ticks to produce
#' @param base Logarithm base
#'
#' @return
#'
#' A function which expects one parameter:
#'
#' * **x**: (numeric vector) The data for which to create a set of ticks.
#'
#' @export
logTicks <- function(n = 5, base = 10){
# Divisors of the logarithm base. E.g. for base 10: 1, 2, 5, 10.
divisors <- which((base / seq_len(base)) %% 1 == 0)
mkTcks <- function(min, max, base, divisor){
f <- seq(divisor, base, by = divisor)
return(unique(c(base^min, as.vector(outer(f, base^(min:max), `*`)))))
}
function(x) {
rng <- range(x, na.rm = TRUE)
lrng <- log(rng, base = base)
min <- floor(lrng[1])
max <- ceiling(lrng[2])
tck <- function(divisor){
t <- mkTcks(min, max, base, divisor)
t[t >= rng[1] & t <= rng[2]]
}
# For all possible divisors, produce a set of ticks and count how many ticks
# result
tcks <- lapply(divisors, function(d) tck(d))
l <- vapply(tcks, length, numeric(1))
# Take the set of ticks which is nearest to the desired number of ticks
i <- which.min(abs(n - l))
if(l[i] < 2){
# The data range is too small to show more than 1 logarithm tick, fall
# back to linear interpolation
ticks <- pretty(x, n = n, min.n = 2)
}else{
ticks <- tcks[[i]]
}
return(ticks)
}
}
你举的例子:
library(ggplot2)
library(scales)
# fix RNG
set.seed(seed=1)
# simulate returns
y=rnorm(999,0.02,0.2)
# M$Y are the cummulative returns (like an index)
M=data.frame(X=1:1000,Y=100)
for (i in 2:1000)
M[i,"Y"]=M[i-1,"Y"]*(1+y[i-1])
ggplot(M,aes(x=X,y=Y))+geom_line()+
scale_y_log10(breaks = logTicks(n = 4), minor_breaks = logTicks(n = 40))
文章来源: Pretty ticks for log normal scale using ggplot2 (dynamic not manual)