Create a Connected-Scatterplot with Zoom-In in ggplot2 to Visualize Increase of Phones in 1950s

In this work, we’ll use R ggplot2 to create a connected scatterplot to visualize the increasing popularity of telephones in the world in the 1950s. In particular, we’ll leverage the ggforce package to create a zoom-in view over clustered data regions.


Packages and Data cleanup

library(dplyr)library(tidyr)library(ggplot2)library(ggforce)theme_set(theme_bw())
w <- WorldPhones %>% as_tibble(rownames = "year") %>% pivot_longer( -year, names_to = "region", values_to = "number")w

Output:

# A tibble: 49 × 3
year region number
<chr> <chr> <dbl>
1 1951 N.Amer 45939
2 1951 Europe 21574
3 1951 Asia 2876
4 1951 S.Amer 1815
5 1951 Oceania 1646
# ℹ 44 more rows

Visualization

Create a line plot showing the number of telephones in each continent or geographic region.

p1 <- w %>%   ggplot(aes(x = year, y = number, color = region)) +  geom_line(aes(group = region))p1

Create a scatterplot showing individual data points. The first layer of points (as in p2) creates white opaque points residing on top of the lines. The second (top) layer of points (as in p3) paints semi-transparent colors associated with the lines. This two-layer-point technique draws points without lines passing through them.

p2 <- p1+  geom_point(shape = 21, size = 3, fill = "white") 
p3 <- p2 + geom_point(shape = 21, size = 3, aes(fill = region), alpha = .5)
cowplot::plot_grid(p2, p3, nrow = 1)

Label the continent or geographic regions the data points are associated with.

p4 <- p3 +  geom_text(    data = w %>% filter(year == 1960),    aes(label = region),     # shift the text by different amount for different regions    nudge_y = c(-6000, 5000, 4000, 500, -400, -400, -400),    fontface = "bold", size = 4) p4

Create a separate panel to zoom in over clustered data points at the plot bottom. This can be easily achieved using the facet_zoom() function from the ggforce package.

p5 <- p4 +   facet_zoom(    y = ! region %in% c("N.Amer", "Europe", "Asia"),     zoom.size = 1, # same size as the main plot    ylim = c(0, 4000)) p5

Make some final outlook adjustment.

p6 <- p5 +  scale_y_continuous(    n.breaks = 10,    # the original number in the dataset is given in thousands,     # further divide by 1000 to make unit in millions    labels = function(x){ paste(x/1000) }) +    # adjust axis labels and plot titles  labs(y = "numbers (in millions)",        x = NULL,       title = "Number of telephones in the world") +    # theme  theme(    panel.grid = element_blank(),    legend.position = "none",    panel.background = element_rect(fill = "floralwhite"),    plot.title = element_text(size = 15, hjust = .5, face = "bold")) p6
library(dplyr)library(tidyr)library(ggplot2)library(ggforce)theme_set(theme_bw())
w <- WorldPhones %>% as_tibble(rownames = "year") %>% pivot_longer( -year, names_to = "region", values_to = "number")w
### Visualization
# Create a line plotp1 <- w %>% ggplot(aes(x = year, y = number, color = region)) + geom_line(aes(group = region))p1
# Create a scatterplot showing individual data points.p2 <- p1+ geom_point(shape = 21, size = 3, fill = "white")
p3 <- p2 + geom_point(shape = 21, size = 3, aes(fill = region), alpha = .5)
cowplot::plot_grid(p2, p3, nrow = 1)
# Label the continent or geographic regionsp4 <- p3 + geom_text( data = w %>% filter(year == 1960), aes(label = region), # shift the text by different amount for different regions nudge_y = c(-6000, 5000, 4000, 500, -400, -400, -400), fontface = "bold", size = 4) p4
# Create a separate panel to zoom in over clustered data points. p5 <- p4 + facet_zoom( y = ! region %in% c("N.Amer", "Europe", "Asia"), zoom.size = 1, # same size as the main plot ylim = c(0, 4000)) p5
# Make some final outlook adjustment. p6 <- p5 + scale_y_continuous( n.breaks = 10, # the original number in the dataset is given in thousands, # further divide by 1000 to make unit in millions labels = function(x){ paste(x/1000) }) + # adjust axis labels and plot titles labs(y = "numbers (in millions)", x = NULL, title = "Number of telephones in the world") + # theme theme( panel.grid = element_blank(), legend.position = "none", panel.background = element_rect(fill = "floralwhite"), plot.title = element_text(size = 15, hjust = .5, face = "bold")) p6