wilkelab / ggtext

Improved text rendering support for ggplot2
https://wilkelab.org/ggtext/
GNU General Public License v2.0
651 stars 37 forks source link

Error: Theme element `text` has NULL property without default #37

Closed thomas-neitmann closed 4 years ago

thomas-neitmann commented 4 years ago

I tried setting the text theme element to element_markdown() but this results in an error:

library(ggplot2)
ggplot(mtcars, aes(hp, mpg)) +
  geom_point() +
  theme(text = ggtext::element_markdown())
Error: Theme element `text` has NULL property without default: fill, box.colour, linetype, linewidth, halign, valign, padding, r, align_widths, align_heights and rotate_margins

I thought I could use element_markdown() as a direct replacement for element_text() but apparently that's not the case. Is there any way to render all text as markdown other then setting each individual theme element, e.g. axis.text, plot.title etc.?

Session Info ``` R version 3.6.3 (2020-02-29) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows 10 x64 (build 17763) Matrix products: default locale: [1] LC_COLLATE=German_Germany.1252 LC_CTYPE=German_Germany.1252 [3] LC_MONETARY=German_Germany.1252 LC_NUMERIC=C [5] LC_TIME=German_Germany.1252 attached base packages: [1] stats graphics grDevices utils datasets methods [7] base other attached packages: [1] ggplot2_3.3.0 loaded via a namespace (and not attached): [1] Rcpp_1.0.4.6 rstudioapi_0.11 xml2_1.3.1 [4] magrittr_1.5 tidyselect_1.0.0 ggtext_0.1.0 [7] munsell_0.5.0 gridtext_0.1.1 colorspace_1.4-1 [10] R6_2.4.1 rlang_0.4.5 dplyr_0.8.5 [13] tools_3.6.3 grid_3.6.3 gtable_0.3.0 [16] withr_2.1.2 ellipsis_0.3.0 digest_0.6.25 [19] assertthat_0.2.1 tibble_3.0.1 lifecycle_0.2.0 [22] crayon_1.3.4 farver_2.0.3 purrr_0.3.4 [25] vctrs_0.2.4 glue_1.4.0 labeling_0.3 [28] compiler_3.6.3 pillar_1.4.3 scales_1.1.0 [31] pkgconfig_2.0.3 ```

clauswilke commented 4 years ago

The element type is not inherited, only the element contents. Therefore, you have to set every non-NULL element to element_markdown() explicitly.

You can use theme(text = element_markdown(...)), but the purpose of that is to provide default values for every possible argument to element_markdown(), and that's why you're getting the error. For example, see how theme_gray() is defined in the ggplot2 source: https://github.com/tidyverse/ggplot2/blob/2b03e4723f0b91875667ffb4f952ad6e471ac9f8/R/theme-defaults.r#L114-L130

Now something like the following, but it's really bad practice, and I would discourage theme writers from doing so. You're basically leaving some base settings undefined and hoping ggplot2 will somehow fill them in in a reasonable way:

ggplot(mtcars, aes(disp, mpg)) + geom_point() +
  theme(text = element_text(color = "blue"))
thomas-neitmann commented 4 years ago

Thanks for this explanation! Now I am wondering, though, how does {ggplot2} pick values for the non-defined properties of element_text()?

clauswilke commented 4 years ago

It fishes them out of the default theme set via theme_set(). And if that fails there's even an internal default I think. We're just trying as hard as possible to prevent people from messing up their system, because all hell breaks loose if you're trying to draw text and some fundamental properties are not set.

py9mrg commented 3 years ago

@clauswilke Hello, I was looking to do the same as OP but I think I have misunderstood your answer. If I use theme(text = element_markdown(...)) I get the error Error in mget(args, envir = env) : '...' used in an incorrect context. Is there a simple way to set all text elements to element_markdown(), or shall I just go about it manually?

clauswilke commented 3 years ago

All text elements have to be changed explicitly. However, the OP has in the meantime released a package that does exactly that: https://cran.r-project.org/web/packages/mdthemes/index.html

py9mrg commented 3 years ago

Ooooooh, thanks!

Edit: just as a side note - I was trying to be lazy and make a function that would change all element_text to element_markdown programatically. Something like, find all the sections of the theme of class element_text and then use theme_update to modify them. I got the first part ok but couldn't for the life of me work out how use the theme_update function programmatically. As in, if I have a vector of names like to_update <- c("text", "plot.title", etc) I was hoping to do something like for(i in to_update) theme_update(i = element_markdown()) but it was having none of it. I tried things like {{i}} but couldn't get it to work and I'm way beyond my skillset now. Just wondering if there is an easy way to do it, or whether I have to dive in and learn ggproto etc stuff?