Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

trans_format and label_math behaving differently on log10 scale #311

Closed
fontikar opened this issue Jun 15, 2021 · 9 comments
Closed

trans_format and label_math behaving differently on log10 scale #311

fontikar opened this issue Jun 15, 2021 · 9 comments

Comments

@fontikar
Copy link

fontikar commented Jun 15, 2021


author: fontikar
date: 2021-06-15
output: "reprex::reprex_document"
title: drear-kitty_reprex.R

First time issue lodger so forgive me if I am not thorough enough. Feedback welcome!
I've been trying to convert retired scales functions to use the 'new' recommended functions for a particular function in a R package I am developing (https://github.com/traitecoevo/austraits/blob/develop/R/plot_trait_distribution_beeswarm.R).
I noticed label_math() is not behaving the same as trans_format() - code and plots to illustrate below.
Any advice would be greatly appreciated!

library(scales)
library(patchwork)

# Old retired code that needs to be updated following scales recommendations
#"parse_format() and math_format() was retired; please use label_parse() and label_math() instead"
demo_log10(x = c(0.1, 10e07),
           breaks = scales::trans_breaks("log10", function(x) 10^x),
           labels = scales::trans_format("log10", scales::math_format(10^.x)))
#> scale_x_log10(breaks = scales::trans_breaks("log10", function(x) 10^x), 
#>     labels = scales::trans_format("log10", scales::math_format(10^.x)))

#Lets do the breaks first
demo_log10(x = c(0.1, 10e07),
           breaks = trans_breaks("log10", function(x) 10^x)) #Old retired code
#> scale_x_log10(breaks = trans_breaks("log10", function(x) 10^x))

demo_log10(x = c(0.1, 10e07),
           breaks = breaks_log(6)) #YAY easy conversion
#> scale_x_log10(breaks = breaks_log(6))

#Now the labels
demo_log10(x = c(0.1, 10e07),
           breaks = breaks_log(6), 
           labels = trans_format("log10", scales::math_format(10^.x))) #Old retired code
#> scale_x_log10(breaks = breaks_log(6), labels = trans_format("log10", 
#>     scales::math_format(10^.x)))

lab_math <- demo_log10(x = c(0.1, 10e07),
           breaks = breaks_log(6), 
           labels = scales::label_math()) #The superscript is not what is expected
#> scale_x_log10(breaks = breaks_log(6), labels = scales::label_math())

lab_number <- demo_log10(x = c(0.1, 10e07),
                       breaks = breaks_log(6), 
                       labels = scales::label_number()) #Original labels
#> scale_x_log10(breaks = breaks_log(6), labels = scales::label_number())

lab_math/lab_number

Created on 2021-06-15 by the reprex package (v2.0.0)

@davidchall
Copy link
Contributor

label_math() has a default argument of expr = 10^.x, which will substitute "10 superscript .x" for each break value. The break values are in the untransformed scale, so the tick labels show incredibly high values.

You want to apply the log10 transformation before the labeler evaluates the expression. This can be achieved using the format argument (see below).

I do agree this is a confusing pair of default argument values though - I'm not sure if this is the intended behavior? I think it's natural to pair expr = 10^.x with format = log10.

library(scales)

demo_log10(x = c(0.1, 10e07),
           breaks = breaks_log(6), 
           labels = label_math(format = log10))
#> scale_x_log10(breaks = breaks_log(6), labels = label_math(format = log10))

Created on 2021-06-24 by the reprex package (v2.0.0)

@clauswilke
Copy link
Collaborator

@davidchall Thanks for this example! I had never figured out how to use label_math(). I think this should be added to the documentation. Would you mind preparing a PR?

Also, I'd argue that the log10 case is so common that it would make sense to add a special labeler function for it, something like:

label_log10 <- function() label_math(format = log10)

@davidchall
Copy link
Contributor

Yeah, I was totally thinking along the same lines! 😄

@clauswilke
Copy link
Collaborator

(Or maybe call it label_log and make the base configurable with default as 10, just like breaks_log.)

@teunbrand
Copy link
Contributor

Having a dedicated function for label_mat(format = log10) would be very nice! The only edge case I've come across is when the transformation's labeller includes 3s in the breaks, which doesn't make for the prettiest labels:

library(scales)

demo_log10(c(1, 10), labels = math_format(format = log10))
#> scale_x_log10(labels = math_format(format = log10))

It would be great if the number of digits displayed in the superscript could be controlled in the case above. In addition, a gist linked in this issue has a neat solution for this that might deserve some daylight:

source("https://gist.githubusercontent.com/bbolker/5ba6a37d64b06a176e320b2b696b6733/raw/2982cb74d9cb760e6594bed926566c6a3da1b018/scientific_10.R")

demo_log10(c(1, 10), labels = scientific_10)
#> scale_x_log10(labels = scientific_10)

Created on 2021-06-24 by the reprex package (v1.0.0)

@clauswilke
Copy link
Collaborator

@teunbrand Agree with your points. I just wanted to point out that placing the breaks in the mathematically correct location fixes the issue, so maybe break placement for log scales also needs to be revisited.

library(scales)

demo_log10(c(1, 10), breaks = c(1, sqrt(10), 10), labels = math_format(format = log10))
#> scale_x_log10(breaks = c(1, sqrt(10), 10), labels = math_format(format = log10))

demo_log10(c(1, 100), breaks = c(1, sqrt(10), 10, 10*sqrt(10), 100), labels = math_format(format = log10))
#> scale_x_log10(breaks = c(1, sqrt(10), 10, 10 * sqrt(10), 100), 
#>     labels = math_format(format = log10))

Created on 2021-06-24 by the reprex package (v1.0.0)

@fontikar
Copy link
Author

fontikar commented Jun 28, 2021


author: fontikar
date: 2021-06-28
output: "reprex::reprex_document"

Dear all,

Thank you for taking the time to reply with such insightful comments and tips!
I was really excited to get some answers after submitting my first issue using reprex!
Unfortunately, I didn't have any success after implementing the formatting tip from @davidchall using label_math(format = "log10"). I'm still getting scientific notation as superscript which is confusing to read! I've updated R and Rstudio and installed the dev version of scales via github.

R version 4.1.0 (2021-05-18)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Big Sur 11.4)
scales_1.1.1.9000

I am not entirely sure why there are discrepancies among users. I wanted to apply this workflow to this plotting function my collaborator wrote for an R package (https://github.com/traitecoevo/austraits/blob/master/R/plot_trait_distribution_beeswarm.R), I wondered if it was the data input that is throwing problems or interfacing with ggbeeswarm but I suspect not after using some simulated data below...

Any advice would be greatly appreciated!

(x <-c(2:10 %o% 10^(3:7)))
#>  [1] 2e+03 3e+03 4e+03 5e+03 6e+03 7e+03 8e+03 9e+03 1e+04 2e+04 3e+04 4e+04
#> [13] 5e+04 6e+04 7e+04 8e+04 9e+04 1e+05 2e+05 3e+05 4e+05 5e+05 6e+05 7e+05
#> [25] 8e+05 9e+05 1e+06 2e+06 3e+06 4e+06 5e+06 6e+06 7e+06 8e+06 9e+06 1e+07
#> [37] 2e+07 3e+07 4e+07 5e+07 6e+07 7e+07 8e+07 9e+07 1e+08

scales::demo_log10(x = x,
           breaks = scales::breaks_log(),
           labels = scales::label_math(format = "log10"))
#> scale_x_log10(breaks = scales::breaks_log(), labels = scales::label_math(format = "log10"))

Created on 2021-06-28 by the reprex package (v2.0.0)

@clauswilke
Copy link
Collaborator

You need to copy the code exactly as written. You added quotes that don't belong there.

@fontikar
Copy link
Author

Thank you @clauswilke for pointing that out! But like @teunbrand format = log10 is not very pretty for odd number of breaks! The number of breaks is hard for me to determine in a function that takes input of different magnitudes so right now I can't think of a generalisable solution! But I certainly appreciated everyone's help! I'm glad my little problem has sparked this thread and hope to see it evolve into some pretty functions - will stay subscribed!

image

I have implemented bbolker's scientific_10 for now - many thanks @teunbrand for sharing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants