漂亮使用GGPLOT2蜱日志正常规模(动态不手动)(Pretty ticks for log nor

2019-07-18 02:10发布

我试图用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)))

一对夫妇的不同之处:

  1. 轴标签显示为10的幂 - 我喜欢
  2. 次要网格线是主要的网格线的中间(比较该地块与Andrie的答案网格线)。
  3. 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)
标签: r plot ggplot2