-
-
Notifications
You must be signed in to change notification settings - Fork 94
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
Support Hjust and Vjust #69
Comments
Could I ask you to please try ggplot_build on a plot that uses If that seems to work, then I'll consider whether this is reasonable to try to integrate into the package. |
Sorry for being dense: I'm looking around the return of |
As I worked through the example below, I started to realize that it might be difficult (or impossible) to take the output from ggplot and hack it into the plot you want. Sorry! Anyway, I think I understand your feature request, but I unfortunately won't be able to work on this any time soon. I'd be happy to review any pull requests that implement this, though. It turns out to be a bit tricky to get the coordinates out of a plot. For future reference, here's a working example: library(ggrepel)
library(gtable)
ggplot(mtcars, aes(x = 0, y = mpg)) +
coord_cartesian(ylim = c(0, 50)) +
geom_point(color = 'red') +
geom_text_repel(
aes(label = rownames(mtcars)),
direction = "y",
nudge_x = -0.1
) grid.force()
pos <- grid.get("textrepelgrob", grep = TRUE, global = TRUE)
# Coordinates on the [0,1] scale (not the original scale of the data).
pos <- data.frame(
x = sapply(pos, "[[", "x"),
y = sapply(pos, "[[", "y"),
x.orig = sapply(pos, "[[", "x.orig"),
y.orig = sapply(pos, "[[", "y.orig")
)
plot(pos$x, pos$y)
points(pos$x.orig, pos$y.orig, pch = 19) |
I've added into my own fork support for hjust and vjust, but don't think it is ready for pull request yet as the resulting plot doesn't look great as the lines end up clashing with the labels: One way to address this issue would be to have the hjust/vjust parameter affect how the lines are drawn -- e.g. if text is left aligned the line tries to hit left side of text. I don't think this is a great option though because you could have all the text left aligned but to the right of the points, making the lines longer than necessary. Another way of making it look better could be to have the lines try to hit the outside of the text using the shortest path (rather than trying to connect to center). Possibly the lines could also be chosen to try to minimize conflict with other labels (might help with issue #34 as well). As this type of change in the line behavior would affect the plots with default ggrepel parameters in addition to cases with hjust and vjust set, figured I should ask whether this kind of change might be acceptable? Or if you might have other ideas for how to make the lines look better with hjust/vjust? |
Alicia, thanks so much for taking the time to do this! Currently, I use the plots in the vignette to test if any changes to the code break anything. If all of the vignettes look ok, then chances are that most plots will work for most people. I'd be very happy to merge a pull request that includes the hjust/vjust feature and a new line connection algorithm. Or you could do two pull requests -- that's also fine by me, because these features seem to go well together. Line segmentsAs you mentioned, the algorithm currently draws the line segment to the center of the label bounding box. It could be modified to choose 1 of 8 points on the label bounding box that is nearest to the data point: Regarding line segment collisions with labels, I like your suggestion to choose 1 of the 8 points that minimizes collisions. Another possible approach is to modify the collision detection loop to trace along the segments and look for collisions with labels, and then apply forces to the labels. I haven't explored this at all. Label orderingThe order of the labels is not the same as the order of the data points. For example, I would expect "Datsun 710" to appear below "Merc 240D". You can tell which labels are not lined up properly because the line segments are intersecting. I might suggest changing the way the layout algorithm is initialized. Currently, it is initialized by adding a tiny amount jitter to each label. Next, the layout is set with repulsion and attraction forces. To better preserve label ordering, the initialization should "zoom in" on the labels, and then run the repulsion and attraction forces. In other words, the x range and y range of the labels should be extended from [0, 1] to [-1, 2]. I haven't explored this at all, but I have an inkling that it might work. I also wonder if it would help to distribute the labels evenly across the range of the data -- or to nudge the labels to be slightly more evenly distributed than the initial positions. After repositioning more evenly, then the repulsion algorithm might produce a more pleasant layout. Here's an example: library(ggrepel)
dat <- mtcars
# Extend the range of the wt variable
wt_range <- diff(range(dat$wt)) * 1.05
dat$wt_extend <- scales::rescale(dat$wt, c(
min(dat$wt) - wt_range / 2,
max(dat$wt) + wt_range / 2
))
# Extend the range of the mpg variable
mpg_range <- diff(range(dat$mpg)) * 1.05
dat$mpg_extend <- scales::rescale(dat$mpg, c(
min(dat$mpg) - mpg_range / 2,
max(dat$mpg) + mpg_range / 2
))
# Basic plot
p1 <- ggplot(dat) +
geom_point(aes(wt, mpg), color = 'red') +
geom_text(aes(wt, mpg, label = rownames(mtcars))) +
theme_classic(base_size = 16)
# Same plot, but text labels are "zoomed in"
p2 <- ggplot(dat) +
geom_point(aes(wt, mpg), color = 'red') +
geom_text(aes(wt_extend, mpg_extend, label = rownames(mtcars))) +
theme_classic(base_size = 16)
gridExtra::grid.arrange(p1, p2, ncol = 2) Left: Labels are positioned directly on top of the data. |
Thanks for the detailed response! Yes the label ordering seems to be non-ideal in the example plot. I have started exploring the "zooming" initialization and/or the more even initial spacing... seems promising for that specific plot but not necessarily generalizable (i.e. if the x values are not all the same but you still only wanted force in y direction only). Decreasing the force also seems to help with this specific plot. Perhaps the line / label collision you mentioned as a possibility could also look for line / line crossings and try to add repulsion to avoid those.... I will explore a little to see if it seems promising! |
@AliciaSchep Hi Alicia, I know you're busy but I just wonder if you have any code that you want to merge into ggrepel. Feel free to send a pull request any time, and thank you for helping out :) I'd be very happy to merge your hjust and vjust features from your fork. |
Hi @slowkow, I've actually recently been revisiting this question -- just put in a pull request! thanks! |
Wow! That looks really good. Thank you so much! I'll take a closer look
soon and merge.
…On Nov 3, 2017 11:23 PM, "Alicia Schep" ***@***.***> wrote:
Hi @slowkow <https://github.com/slowkow>, I've actually recently been
revisiting this question -- just put in a pull request! thanks!
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#69 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAMzMosXYVoxj_EPd-1vyPpoyoAFMCzcks5szALHgaJpZM4MLcbh>
.
|
Looking forward to hjust and vjust improving an already-great function! |
@JoGall @bmschmidt I forgot to announce the new feature here! Woops! Alicia implemented If you'd like to try it out, please install ggrepel from github and leave a comment here to let me know how it goes! devtools::install_github("slowkow/ggrepel") Here's an example that you can copy: https://github.com/slowkow/ggrepel/blob/master/vignettes/ggrepel.md#align-text-labels |
Alicia did a great job with this one. I think the issue is resolved. |
Thanks for a great package! Now that this issue is closed with the capability to repel only along the x or y direction, it might be worth following up on one of the things mentioned in there: (re-)supporting hjust and vjust parameters when movement on that dimension isn't allowed. My particular use case is a slopegraph where I want to have a flush
hjust=0
on the left andhjust=1
on the right side for labels--see example. The current version is OK with a nudge parameter, but it would be better to have all labels flush as in the (overlappy)geom_text
version below with lines emanating out of the left or right of the text, not the bottom/top.Sorry if this is now possible and I'm just not seeing how!
overlappy base ggplot version.
The text was updated successfully, but these errors were encountered: