Nemesi
Nemesi

Reputation: 801

Add a bubble chart to a simple plot in R

I am plotting some simple variables in R, something like:

a<- runif(1000, 1, 100)
b<- runif(1000, 30, 200)
c<- runif(1000, 45, 160)
plot(sort(a),sort(b), xlab = "fraction of population a", ylab = "something happening to population a")
points(sort(a), sort(c), col="red")
legend("topleft", legend = c("time 0", "time 1"), pch=1, lwd=2.5,  col = c("black","red"))

this gives the following plot: enter image description here

Now I would like to add an additional information to acknowledge that my population a changed between time 0 and time 1. This would be best added as a little bubble chart in the bottom right corner of the plot. Something like the following graph (but just displaying the pop_a_time_0 and pop_a_time_1):

enter image description here

Would this be possible?

Upvotes: 0

Views: 355

Answers (2)

Rui Barradas
Rui Barradas

Reputation: 76402

With base graphics, there is function draw.circle in package plotrix.
I will first redo the graph in the question.

library(plotrix)

set.seed(1234)    # Make the results reproducible

a <- runif(1000, 1, 100)
b <- runif(1000, 30, 200)
c <- runif(1000, 45, 160)

plot(sort(a),sort(b), xlab = "fraction of population a", ylab = "something happening to population a")
points(sort(a), sort(c), col="red")
legend("topleft", legend = c("time 0", "time 1"), pch=1, lwd=2.5,  col = c("black","red"))

Now the circles.

draw.circle(x = 80, y = 50, radius = 12, border = "black")
draw.circle(x = 80, y = 46, radius = 9, border = "red")

And finally the labels. Since there are numbers, I computed the predicted values of the y axis for x = 100, given a linear model.

fit_1 <- lm(sort(b)~sort(a))
fit_0 <- lm(sort(c)~sort(a))
t1 <- predict(fit_1, newdata = data.frame(a = 100))
t0 <- predict(fit_0, newdata = data.frame(a = 100))
t1 <- round(t1)
t0 <- round(t0)

text(80, 65, labels = t1, pos = 3, cex = 0.65)
text(80, 56, labels = t0, pos = 3, cex = 0.65)
text(80, 75, labels = "Population", pos = 3)    # Plot once
text(80, 75, labels = "Population", pos = 3)    # Overplot to make it darker

enter image description here

Upvotes: 1

the-mad-statter
the-mad-statter

Reputation: 8676

Here is a solution using ggplot instead of base graphics.

I used ggforce::geom_circle() to draw the circles and performed the inset as per here.

library(dplyr)
library(ggforce)
library(ggplot2)

ggplot() + 
  geom_circle(aes(x0 = 0, y0 = 0:2, r = 1:3)) + 
  geom_text(aes(label = c("3", "20", "40m", "Population"), x = 0, y = c(1.5, 3.5, 5.5, 6.5))) + 
  coord_equal() + 
  theme_void() -> inset_plot

tibble(x = rep(sort(runif(1000, 1, 100)), 2), 
       time = rep(c("time 0", "time 1"), each = 1000), 
       y = c(sort(runif(1000, 30, 200)), sort(runif(1000, 45, 160)))) %>% 
  ggplot(aes(x = x, y = y, color = time)) + 
  geom_point() + 
  labs(x = "fraction of popuation a", 
       y = "something happend to popuation a") + 
  theme(legend.position = c(.05, .92)) + 
  annotation_custom(ggplotGrob(inset_plot), xmin = 70, xmax = 120, ymin = 25, ymax = 75)

Upvotes: 1

Related Questions