How to add geom_text or geom_label with a position relative to the size of a geom_point?

Viewed 457

What I am trying to do, is add a label to points made with geom_point that have a variable mapped to the size. The value is also displayed in the label. The text or label should be positioned just under the geom_point, but achieving this with position_nudge does not seem possible.

My code currently looks like this (simplified):

ggplot(data, aes(x = var1, y = var2) +
   geom_point(aes(size = var3)) +
   geom_text(aes(label = var3))

The result is this

2

but I am trying to achieve something like this:

1

Is there any way to achieve this in a simple way?

Thanks.

EDIT: I am trying to have the distance between the border of the geom_point and the border of the labels be a fixed value.

3 Answers

The problem can be solved by scaling size and adding it to the vjust distance to the points.

library(ggplot2)

ggplot(data, aes(x = var1, y = var2)) +
  geom_point(aes(size = var3), show.legend = FALSE) +
  geom_text(aes(label = var3, vjust = 1.5 + 0.1 * var3))

enter image description here

Test data

data <- data.frame(var1 = factor(rep(1:3, 2)),
                   var2 = factor(rep(1:2, each = 3)),
                   var3 = c(3, 10, 2, 1, 1, 10))

Use nudge

Thanks to Rui for the data. +1

library(ggplot2)
data <- data.frame(var1 = factor(rep(1:3, 2)),
                   var2 = factor(rep(1:2, each = 3)),
                   var3 = c(3, 10, 2, 1, 1, 10))

ggplot(data, aes(x = var1, y = var2)) +
  geom_point(aes(size = var3), show.legend = FALSE) +
  geom_text(aes(label = var3), nudge_y = -0.1 )

Created on 2021-01-20 by the reprex package (v0.3.0)

I hope this is sufficiently different to merit another answer. I admit I have overlooked the bit to what exactly you wanted to position the labels. So basically you want it not relative to the point centre, but to the radius.

I felt quite nostalgically reminded of my very own first question in this community, of which I admit I haven't understood its answer for a very long time.

The basic idea is to not use geom_point, but to use ggforce::geom_circle (or: geom_ellipse). You can use the radius which you use for creation for positioning of your labels. It requires a bit of hard coding, but I am sure there would be ways to programmatically define the radius based on your general coordinates.

library(ggplot2)
library(ggforce)

foo <- data.frame(var1 = rep(1:3, 2),  var2 =rep(1:2, each = 3),
                   var3 = c(3, 10, 2, 1, 1, 10))
# Create cuts - you can also assign other values of course. factor of 0.01 was chosen randomly. 
foo$rad <- 0.01 * findInterval(foo$var3, 1:5)

ggplot(foo) +
  geom_circle(aes(x0 = var1, y0 = var2, r = rad),
              fill = "Grey50") +
  geom_text(aes(x = var1, y = var2 - rad - 0.03, label = var3)) +
  coord_equal()

Created on 2021-01-20 by the reprex package (v0.3.0)

Related