I have created a circular (polar) barplot with facets and would like to place headshots of two baseball players in the center of each plot. I have tried several methods including annotation_custom (only works with cartesian plots, not coord_polar) and a similar, questionable solution found here: Trying to add an image to a polar plot gives "Error: annotation_custom only works with Cartesian coordinates".
Would be grateful for any and all help. The headshot links for the two players are included in the org
column of the my_data_long
data frame. Also attaching a screenshot of the existing plot (sans headshots, of course) below for context.
my_data_long <- structure(data.frame(player = c("Jackson Holliday", "Jackson Holliday",
"Jackson Holliday", "Jackson Holliday", "Jackson Holliday", "Jackson Holliday",
"Jackson Holliday", "James Wood", "James Wood", "James Wood",
"James Wood", "James Wood", "James Wood", "James Wood", "Jackson Holliday",
"Jackson Holliday", "Jackson Holliday", "Jackson Holliday", "Jackson Holliday",
"Jackson Holliday", "Jackson Holliday", "James Wood", "James Wood",
"James Wood", "James Wood", "James Wood", "James Wood", "James Wood"
), names = c("hit", "raw_power", "game_power", "spd", "fld",
"bat_ctrl", "pitch_sel", "hit", "raw_power", "game_power", "spd",
"fld", "bat_ctrl", "pitch_sel", "hit", "raw_power", "game_power",
"spd", "fld", "bat_ctrl", "pitch_sel", "hit", "raw_power", "game_power",
"spd", "fld", "bat_ctrl", "pitch_sel"), variable = structure(c(1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), levels = c("current",
"future"), class = "factor"), value = c(45, 50, 25, 50, 40, 60,
60, 30, 70, 55, 60, 45, 40, 50, 60, 60, 60, 50, 50, 60, 60, 35,
80, 80, 50, 50, 40, 50), org = c("https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/702616/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/702616/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/702616/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/702616/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/702616/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/702616/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/702616/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/695578/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/695578/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/695578/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/695578/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/695578/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/695578/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/695578/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/702616/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/702616/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/702616/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/702616/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/702616/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/702616/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/702616/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/695578/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/695578/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/695578/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/695578/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/695578/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/695578/headshot/milb/current",
"https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/695578/headshot/milb/current")))
library(tidyverse)
ggplot(data=my_data_long, aes(x=names, y=value, fill=variable, color=variable, alpha=variable))+
geom_hline(
aes(yintercept = y),
data.frame(y = c(4:8) * 10),
color = "lightgrey"
) +
geom_bar(stat="identity", position ="identity") +
scale_colour_manual(values=c("lightblue4", "red")) +
scale_fill_manual(values=c("lightblue", "pink")) +
scale_alpha_manual(values=c(.8, .3)) +
scale_y_continuous(limits = c(-40,82),
expand = c(0,0),
breaks = c(40,50,60,70,80)) +
theme_bw() +
facet_wrap(~player) +
coord_polar() +
annotate(
x = 4,
y = 40,
label = "40",
geom = "text",
color = "gray12",
family = "Trebuchet MS"
) +
annotate(
x = 4,
y = 60,
label = "60",
geom = "text",
color = "gray12",
family = "Trebuchet MS"
) +
annotate(
x = 4,
y = 80,
label = "80",
geom = "text",
color = "gray12",
family = "Trebuchet MS"
) +
labs(title = "Top MLB Prospect Tools",
subtitle = "Using 20-80 Scouting Scale",
caption = "Data: FanGraphs") +
# Customize general theme
theme(
# Set default color and font family for the text
text = element_text(color = "gray12", family = "Trebuchet MS"),
# Customize the text in the title, subtitle, and caption
plot.title = element_text(face = "bold", hjust = 0.0, size = 20),
plot.subtitle = element_text(hjust = 0.0, size = 14),
plot.caption = element_text(size = 12),
axis.title = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.text.x = element_text(size = 10),
strip.text = element_text(size = 16),
legend.title = element_blank(),
# Make the background white and remove extra grid lines
panel.background = element_rect(fill = "white", color = "white"),
panel.grid = element_blank(),
panel.grid.major.x = element_blank()
)
One option would be to use ggimage
library(tidyverse)
library(ggimage)
images <- my_data_long |>
distinct(player, org)
ggplot(data = my_data_long, aes(
x = names, y = value, fill = variable,
color = variable, alpha = variable
)) +
geom_hline(
aes(yintercept = y),
data.frame(y = c(4:8) * 10),
color = "lightgrey"
) +
geom_bar(stat = "identity", position = "identity") +
geom_image(
data = images, aes(image = org), x = 4, y = -40, size = .1,
inherit.aes = FALSE
) +
scale_colour_manual(values = c("lightblue4", "red")) +
scale_fill_manual(values = c("lightblue", "pink")) +
scale_alpha_manual(values = c(.8, .3)) +
scale_y_continuous(
limits = c(-40, 82),
expand = c(0, 0),
breaks = c(40, 50, 60, 70, 80)
) +
theme_bw() +
facet_wrap(~player) +
coord_polar() +
geom_text(
data = data.frame(x = 4, y = c(40, 60, 80)),
aes(x = x, y = y, label = y),
color = "gray12",
family = "Trebuchet MS",
inherit.aes = FALSE
) +
labs(
title = "Top MLB Prospect Tools",
subtitle = "Using 20-80 Scouting Scale",
caption = "Data: FanGraphs"
) +
# Customize general theme
theme(
# Set default color and font family for the text
text = element_text(color = "gray12", family = "Trebuchet MS"),
# Customize the text in the title, subtitle, and caption
plot.title = element_text(face = "bold", hjust = 0.0, size = 20),
plot.subtitle = element_text(hjust = 0.0, size = 14),
plot.caption = element_text(size = 12),
axis.title = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.text.x = element_text(size = 10),
strip.text = element_text(size = 16),
legend.title = element_blank(),
# Make the background white and remove extra grid lines
panel.background = element_rect(fill = "white", color = "white"),
panel.grid = element_blank(),
panel.grid.major.x = element_blank()
)
UPDATE Perhaps an even prettier approach would be to additionally use the cropcircles
package:
library(cropcircles)
images <- my_data_long |>
distinct(player, org) |>
mutate(
img_circle = circle_crop(org, border_size = 12, border_colour = "black")
)
... +
geom_image(
data = images, aes(image = img_circle), x = 4, y = -40, size = .2,
inherit.aes = FALSE
) +
...