Ari B. Friedman
Ari B. Friedman

Reputation: 72739

Dynamic position for ggplot2 objects (especially geom_text)?

When using ArcGIS to make maps, the software by default pushes point and polygon labels around automatically to avoid overlap using a proprietary algorithm. They refer to this as dynamic labeling. ggplot2 has position_jitter which is excellent for points (since dynamic labeling might create systematic bias), but less good for labels using geom_text.

Here's an example of some problems with jitter that a dynamic labeling algorithm might solve:

library(ggplot2)
ggplot( mtcars,aes( x=wt, y=mpg, label=rownames(mtcars) ) ) +
  geom_point() +
  geom_text( position=position_jitter(h=1,w=1) )

jittered labels with problems noted

Does such a dynamic labeling feature exist already in ggplot2?

If not, what algorithms exist for doing so and is it possible to implement a position_dynamic in R?

Upvotes: 18

Views: 12285

Answers (4)

Sukhi
Sukhi

Reputation: 846

Check out the new package ggrepel. ggrepel provides geoms for ggplot2 to repel overlapping text labels. It works both for geom_text and geom_label.

enter image description here

Figure is taken from this blog post.

Upvotes: 12

gregk
gregk

Reputation: 91

I ran into a similar problem with several of the plots I have been working with and wrote a basic package that uses force field simulation to adjust object location. While much improvement is possible, including integration with ggplot, etc. it seems to get the task accomplished. The following illustrates the functionality:

install.packages("FField", type = "source")
install.packages("ggplot2")
install.packages("gridExtra")
library(FField)
FFieldPtRepDemo()

Upvotes: 9

Andrie
Andrie

Reputation: 179458

AFAIK, the best that exists is directlabels, available from R-forge and CRAN and with a comprehensive examples page.

This seems a good starting point, but in my opinion has the following negative aspects:

  • Unlike the ggplot philosophy of separating data and presentation, directlabels returns a ggplot object rather than a geom
  • it only works on the group aesthetic, not individual points

I have glanced at the source code some time ago and I think it should be reasonably easy to adapt the code to address both points I mention.

There is an example of how to use this with ggplot in this question on SO

Upvotes: 8

Gavin Simpson
Gavin Simpson

Reputation: 174843

This isn't anything that can be used directly in ggplot2, but the ordipointlabel() function in package vegan tries to do something similar. It displays data as points and tries to label each point with the appropriate label, using an optimisation algorithm to position the labels next to their point but without overlapping other labels and points.

?ordipointlabel mentions that it is based on pointlabel() in the maptools package, which could be another place to look for inspiration.

Upvotes: 7

Related Questions