Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why is it so slow to add a geom_text to ggplot2?

I have found a problem when plotting hex graphs using ggplot2. When I use geom_text to add text to the graph, it takes a very long time!

I made a minimal, self-contained, reproducible example and you can easily find this problem.

library(ggplot2)
d1 <- ggplot(diamonds, aes(carat, price)) + 
  geom_hex()
d2 <- d1+ 
  geom_text(x=3,y=5000,
            label="y = 0.0243x + 0.298\nR^2 = 0.648, p < 2.2e-16")

system.time({
  print(d1)
})
#   user  system elapsed 
#   0.11    0.01    0.13

system.time({
  print(d2)
})
#   user  system elapsed 
#   0.75    2.84    3.61 

For a very small amount of data, geom_text makes the runtime more than 27 times longer. For my real code, it increases the runtime from 3.65s to 162.30s (more than 44 times, and note that this is only when the run is complete, it takes more time to show up in the pane).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I’m not exactly sure what’s causing this, but I feel like adding text to a graphic should be one of the more basic graphic settings, so I’m sincerely hoping this can be fixed.In addition, because of this super long running time, it often causes R to crash when I want to stop running (this makes me very frustrated). I am also curious if there is a more appropriate way to end the running process and keep the R program running normally.

>Solution :

In this case, geom_text() maps your string to every row of data. One way to see this is to reproduce both plots as svg strings. You will see the d2 string contains the following repeated for nrow(diamonds) * 2 lines (i.e. 107,880 lines):

<text x='404.35' y='510.41' text-anchor='middle' style='font-size: 11.04px; font-family: "Arimo";' textLength='144.40px' lengthAdjust='spacingAndGlyphs'>R^2 = 0.648, p &lt; 2.2e-16</text>
<text x='404.35' y='494.51' text-anchor='middle' style='font-size: 11.04px; font-family: "Arimo";' textLength='115.77px' lengthAdjust='spacingAndGlyphs'>y = 0.0243x + 0.298</text>
<text x='404.35' y='510.41' text-anchor='middle' style='font-size: 11.04px; font-family: "Arimo";' textLength='144.40px' lengthAdjust='spacingAndGlyphs'>R^2 = 0.648, p &lt; 2.2e-16</text>
<text x='404.35' y='494.51' text-anchor='middle' style='font-size: 11.04px; font-family: "Arimo";' textLength='115.77px' lengthAdjust='spacingAndGlyphs'>y = 0.0243x + 0.298</text>

You do not want to map the text to your data, so for this kind of thing you should instead use ggplot2::annotate(). As the docs state,

The properties of the geoms are not mapped from variables of a data frame, but are instead passed in as vectors. This is useful for adding small annotations (such as text labels)

d3 <- d1 + annotate(
    "text", 
    x = 3, 
    y = 5000, 
    label = "y = 0.0243x + 0.298\nR^2 = 0.648, p < 2.2e-16"
)

This only generates the text once so should not cause this issue:

system.time({
    print(d1)
})
#   user  system elapsed
#   0.11    0.01    0.13

system.time({
    print(d3)
})
#    user  system elapsed 
#   0.141   0.000   0.141 
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading