Is there a built-in way to do a logarithmic color

2020-01-29 04:44发布

问题:

Here's an example of a binned density plot:

require(ggplot2)
n <- 1e5
df <- data.frame(x = rexp(n), y = rexp(n))
p <- ggplot(df, aes(x = x, y = y)) + stat_binhex()
print(p)

It would be nice to adjust the color scale so that the breaks are log-spaced, but a try

my_breaks <- round_any(exp(seq(log(10), log(5000), length = 5)), 10)
p + scale_fill_hue(breaks = as.factor(my_breaks), labels = as.character(my_breaks))

Results in an Error: Continuous variable () supplied to discrete scale_hue. It seems breaks is expecting a factor (maybe?) and designed with categorical variables in mind?

There's a not built-in work-around I'll post as an answer, but I think I might just be lost in my use of scale_fill_hue, and I'd like to know if there's anything obvious I'm missing.

回答1:

Yes! There is a trans argument to scale_fill_gradient, which I had missed before. With that we can get a solution with appropriate legend and color scale, and nice concise syntax. Using p from the question and my_breaks = c(2, 10, 50, 250, 1250, 6000):

p + scale_fill_gradient(name = "count", trans = "log",
                        breaks = my_breaks, labels = my_breaks)

My other answer is best used for more complicated functions of the data. Hadley's comment encouraged me to find this answer in the examples at the bottom of ?scale_gradient.



回答2:

Another way, using a custom function in stat_summary_hex:

ggplot(cbind(df, z = 1), aes(x = x, y = y, z = z)) + 
  stat_summary_hex(function(z){log(sum(z))})

This is now part of ggplot, but was originally inspired by the wonderful code by by @kohske in this answer, which provided a custom stat_aggrhex. In versions of ggplot > 2.0, use the above code (or the other answer)

ggplot(cbind(df, z = 1), aes(x = x, y = y, z = z)) +
    stat_aggrhex(fun = function(z) log(sum(z))) +
    labs(fill = "Log counts")

To generate this plot.



标签: r ggplot2