2016-11-14 137 views
2

想要绘制一个叠加柱状图:ggplot的scale_y_log10行为

set.seed(1) 
my.df <- data.frame(param = runif(10000,0,1), 
        x = runif(10000,0.5,1)) 
my.df$param.range <- cut(my.df$param, breaks = 5) 

require(ggplot2) 

不记录y轴:

ggplot(my.df,aes_string(x = "x", fill = "param.range")) + 
    geom_histogram(binwidth = 0.1, pad = TRUE) + 
    scale_fill_grey() 

给出: enter image description here

但我想日志10 + 1转换y轴以使其更易于阅读:

ggplot(my.df, aes_string(x = "x", y = "..count..+1", fill = "param.range")) + 
    geom_histogram(binwidth = 0.1, pad = TRUE) + 
    scale_fill_grey() + 
    scale_y_log10() 

这给:

enter image description here

在y轴上的刻度线没有意义。

我得到同样的行为,如果我日志10变换,而不是日志10 + 1:

ggplot(my.df, aes_string(x = "x", fill = "param.range")) + 
    geom_histogram(binwidth = 0.1, pad = TRUE) + 
    scale_fill_grey() + 
    scale_y_log10() 

任何想法是怎么回事?

+0

1.为什么不刻度线是有意义的吗? 2.在最后一行代码中我看不到任何转换。 –

+0

抱歉,最后一行代码已更正。关于y轴刻度值,我认为它应该显示第一个图中显示的计数的log10,所以它们应该是:2.69,3,3.17,3.30而不是1,000。 10,000,000,100,000,000,000 – dan

+0

y轴仍将以实际计数为单位,而不是这些计数的日志,但是y尺度会进行转换,以便每个因子10的物理距离相同。 – eipi10

回答

2

它看起来像一个叠加柱状图调用scale_y_log10是造成ggplot绘制计数的产品每个x仓内堆栈的各个组件。下面是一个演示。我们创建一个名为product.of.counts的数据框,其中包含每个param.range bin的每个x bin内的产品。我们使用geom_text将这些值添加到图中,并看到它们与每个直方图条堆栈的顶部一致。

起初我以为这是一个bug,但在bit of searching后,我想起了ggplot做日志转换的方式。如链接答案中所述,“scale_y_log10”会计数,将它们转换为日志,然后堆叠这些日志,然后以反日志形式显示比例。但是,堆积日志不是线性转换,因此您询问了什么这样做没有任何意义。“

作为一个更简单的例子,假设一个堆栈条的五个组件中的每一个都有100个计数。然后log10(100)= 2,所有五个日志的总和将是10.然后ggplot将采用anti-记录刻度,即使实际高度为100x5 = 500,标尺的总高度为10^10(即100^5)。这正是你的情节发生的情况。

library(dplyr) 
library(ggplot2) 

# Data 
set.seed(1) 
my.df <- data.frame(param=runif(10000,0,1),x=runif(10000,0.5,1)) 
my.df$param.range <- cut(my.df$param,breaks=5) 

# Calculate product of counts within each x bin 
product.of.counts = my.df %>% 
    group_by(param.range, breaks=cut(x, breaks=seq(-0.05, 1.05, 0.1), labels=seq(0,1,0.1))) %>% 
    tally %>% 
    group_by(breaks) %>% 
    summarise(prod = prod(n), 
      param.range=NA) %>% 
    ungroup %>% 
    mutate(breaks = as.numeric(as.character(breaks))) 

ggplot(my.df, aes(x, fill=param.range)) + 
    geom_histogram(binwidth = 0.1, colour="grey30") + 
    scale_fill_grey() + 
    scale_y_log10(breaks=10^(0:14)) + 
    geom_text(data=product.of.counts, size=3.5, 
      aes(x=breaks, y=prod, label=format(prod, scientific=TRUE, digits=3))) 

enter image description here