Skip to content

Could position nudging be done in an easy proportional way relative to scale as a whole (e.g. using I function)? #6466

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

Closed
davidhodge931 opened this issue May 20, 2025 · 6 comments

Comments

@davidhodge931
Copy link

It'd be nice to be able to nudge in a proportional way easily. At present, you can calculate your nudge manually in absolute units, but it'd nice if there was a more simple straightforward way.

The I function allows relative positioning when annotating. So was wondering if it'd be possible to support this with nudging? This is adding nudge_x =I(0.05) or position_nudge(x = I(0.05)) to do this, rather than having to manually calculate.

Sorry for all the issues!

library(tidyverse)
library(tidyplots)

#currrently do this 
spendings |> 
  group_by(category) |> 
  summarise(across(amount, sum)) |> 
  ggplot(aes(x = amount, y = category, label = amount)) +
  geom_col() +
  geom_text(nudge_x = 1200 * 0.05) #guessing 1200 is the size of the x scale

  
# # would like to do this
# spendings |> 
#   group_by(category) |> 
#   summarise(across(amount, sum)) |> 
#   ggplot(aes(x = amount, y = category, label = amount)) +
#   geom_col() +
#   geom_text(nudge_x = I(0.05)) 

Created on 2025-05-21 with reprex v2.1.1

@smouksassi
Copy link

you can nudge by a fixed amount or proportional to your x value
( you can also do stuff using npc units in ggpp geom_text_npc
what exactly you need to do with your example ?

library(tidyverse)
library(tidyplots)
library(patchwork)
#currrently do this 
a<- spendings |> 
  group_by(category) |> 
  summarise(across(amount, sum)) |> 
  ggplot(aes(x = amount, y = category, label = amount)) +
  geom_col() +
  geom_text(aes(x=amount*1.2)) +
  labs(subtitle = "nudge 20%")
b<- spendings |> 
  group_by(category) |> 
  summarise(across(amount, sum)) |> 
  ggplot(aes(x = amount, y = category, label = amount)) +
  geom_col() +
  geom_text(aes(x=amount+50)) +
  labs(subtitle = "nudge +50 x units")

a | b

Created on 2025-05-20 with reprex v2.1.1

@davidhodge931
Copy link
Author

Interesting, thanks @smouksassi I want to be able to easily make the nudging the same for each value, and proportional to the whole of a scale. So multiplying by the aesthetic doesn't work, as large values then get larger nudging. Adding works but it's not proportional without doing some calcs

@teunbrand
Copy link
Collaborator

In the development version, since nudge_x has become a 'proper' aesthetic, you can do this: geom_text(aes(nudge_x = after_stat(max(abs(x)) * 0.05))).

@davidhodge931
Copy link
Author

davidhodge931 commented May 20, 2025

That looks pretty cool @teunbrand

However, it would still make the nudge proportional to the max value, rather than proportional to the entire scale size - which is what I want because I often change the limits, expand etc. This code nudges relative to the max value, as I understand it.

I'd say the use of after_stat is still pretty challenging for non-advanced ggplot2 users too.

Is the I solution possible? This would align nicely with how this works in annotating

Image https://www.tidyverse.org/blog/2024/02/ggplot2-3-5-0/#ignoring-scales

@davidhodge931 davidhodge931 changed the title Could position nudging be done in an easy proportional way (e.g. using I function)? Could position nudging be done in an easy proportional way relative to scale as a whole (e.g. using I function)? May 20, 2025
@davidhodge931
Copy link
Author

Ideally, I want to be able to add a line of code like this, which would add some space equivalent to that proportion of the scale as a whole...

geom_text(aes(x = xvar + I(0.02)), hjust = 0)

Not sure if it'd be possible..

library(tidyverse)
library(tidyplots)

# can do this based on the max value for where scale min is 0
spendings |>
  group_by(category) |> 
  summarise(across(amount, sum)) |> 
  ggplot(aes(x = amount, y = category, label = amount)) +
  geom_col() +
  geom_text(aes(x = amount + max(amount) * 0.01), hjust = 0) +
  scale_x_continuous(expand = expansion(c(0, 0.1)))

# #prefer to do this based on the scale size, which would work for any limits/expand combo consistently
# spendings |>
#   group_by(category) |> 
#   summarise(across(amount, sum)) |> 
#   ggplot(aes(x = amount, y = category, label = amount)) +
#   geom_col() +
#   geom_text(aes(x = amount + I(0.02)), hjust = 0) +
#   scale_x_continuous(expand = expansion(c(0, 0.1)))

Created on 2025-05-22 with reprex v2.1.1

@teunbrand
Copy link
Collaborator

That sounds like you want the same as #5609, in which case, I'll mark this as a duplicate to prune discussion here so it may grow there.

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

3 participants