R label with commas but no decimals - r

My goal is to produce labels with commas, but no decimals. Let's say I have a ggplot with the following section:
geom_text(aes(y = var,
label = scales::comma(round(var))), hjust = 0, nudge_y = 300 )
This is almost what I need. It gives me the commas, but has a decimal. I have seen here (axis labels with comma but no decimals ggplot) that comma_format() could be good, but I think the label in my case needs a data argument, which comma_format() does not take. What can I do?
Update:
As an example of when this problem occurs, see the following, which uses gganimate and has a lot more going on. Code derived from Jon Spring's answer at Animated sorted bar chart with bars overtaking each other
library(gapminder)
library(gganimate)
library(tidyverse)
gap_smoother <- gapminder %>%
filter(continent == "Asia") %>%
group_by(country) %>%
complete(year = full_seq(year, 1)) %>%
mutate(gdpPercap = spline(x = year, y = gdpPercap, xout = year)$y) %>%
group_by(year) %>%
mutate(rank = min_rank(-gdpPercap) * 1) %>%
ungroup() %>%
group_by(country) %>%
complete(year = full_seq(year, .5)) %>%
mutate(gdpPercap = spline(x = year, y = gdpPercap, xout = year)$y) %>%
mutate(rank = approx(x = year, y = rank, xout = year)$y) %>%
ungroup() %>%
arrange(country,year)
gap_smoother2 <- gap_smoother %>% filter(year<=2007 & year>=1999)
gap_smoother3 <- gap_smoother2 %<>% filter(rank<=8)
p <- ggplot(gap_smoother3, aes(rank, group = country,
fill = as.factor(country), color = as.factor(country))) +
geom_tile(aes(y = gdpPercap/2,
height = gdpPercap,
width = 0.9), alpha = 0.8, color = NA) +
geom_text(aes(y = 0, label = paste(country, " ")), vjust = 0.2, hjust = 1) +
geom_text(aes(y = gdpPercap,
label = scales::comma(round(gdpPercap))), hjust = 0, nudge_y = 300 ) +
coord_flip(clip = "off", expand = FALSE) +
scale_x_reverse() +
guides(color = FALSE, fill = FALSE) +
labs(title='{closest_state %>% as.numeric %>% floor}',
x = "", y = "GFP per capita") +
theme(plot.title = element_text(hjust = 0, size = 22),
axis.ticks.y = element_blank(), # These relate to the axes post-flip
axis.text.y = element_blank(), # These relate to the axes post-flip
plot.margin = margin(1,1,1,4, "cm")) +
transition_states(year, transition_length = 1, state_length = 0) +
enter_grow() +
exit_shrink() +
ease_aes('linear')
animate(p, fps = 2, duration = 5, width = 600, height = 500)

In addition to the solution provided by #drf, you need to add scale_y_continuous(scales::comma) to your ggplot commands. But put it before the coord_flip function.
p <- ggplot(gap_smoother3, aes(rank, group = country,
fill = as.factor(country), color = as.factor(country))) +
geom_tile(aes(y = gdpPercap/2,
height = gdpPercap,
width = 0.9), alpha = 0.8, color = NA) +
geom_text(aes(y = gdpPercap,
label = scales::comma(round(gdpPercap), accuracy=1)),
hjust = 0, nudge_y = 300 ) +
scale_y_continuous(labels = scales::comma) +
... etc.

Related

How to adjust ggrepel label on pie chart?

I am trying to create a pie chart to visualize percent abundance of 9 genera. However, the labels are all clumping together. How do I remedy this? Code included below:
generaabundance2020 <- c(883, 464, 1948, 1177, 2607, 962, 2073, 620, 2670)
genera2020 <- c("Andrena", "Ceratina", "Halictus",
"Hesperapis", "Lasioglossum", "Melissodes",
"Osmia", "Panurginus", "Other")
generabreakdown2020 <- data.frame(group = genera2020, value = generaabundance2020)
gb2020label <- generabreakdown2020 %>%
group_by(value) %>% # Variable to be transformed
count() %>%
ungroup() %>%
mutate(perc = `value` / sum(`value`)) %>%
arrange(perc) %>%
mutate(labels = scales::percent(perc))
generabreakdown2020 %>%
ggplot(aes(x = "", y = value, fill = group)) +
geom_col() +
coord_polar("y", start = 0) +
theme_void() +
geom_label_repel(aes(label = gb2020label$labels), position = position_fill(vjust = 0.5),
size = 5, show.legend = F, max.overlaps = 50) +
guides(fill = guide_legend(title = "Genera")) +
scale_fill_manual(values = c("brown1", "chocolate1",
"darkgoldenrod1", "darkgreen",
"deepskyblue", "darkslateblue",
"darkorchid4", "hotpink1",
"lightpink"))
Which produces the following:
Thanks for adding your data.
There are a few errors in your code. The main one is that you didn't precalculate where to place the labels (done here in the text_y variable). That variable needs to be passed as the y aesthetic for geom_label_repel.
The second is that you no longer need
group_by(value) %>% count() %>% ungroup() because the data you provided is already aggregated.
library(tidyverse)
library(ggrepel)
generaabundance2020 <- c(883, 464, 1948, 1177, 2607, 962, 2073, 620, 2670)
genera2020 <- c("Andrena", "Ceratina", "Halictus", "Hesperapis", "Lasioglossum", "Melissodes", "Osmia", "Panurginus", "Other")
generabreakdown2020 <- data.frame(group = genera2020, value = generaabundance2020)
gb2020label <-
generabreakdown2020 %>%
mutate(perc = value/ sum(value)) %>%
mutate(labels = scales::percent(perc)) %>%
arrange(desc(group)) %>% ## arrange in the order of the legend
mutate(text_y = cumsum(value) - value/2) ### calculate where to place the text labels
gb2020label %>%
ggplot(aes(x = "", y = value, fill = group)) +
geom_col() +
coord_polar(theta = "y") +
geom_label_repel(aes(label = labels, y = text_y),
nudge_x = 0.6, nudge_y = 0.6,
size = 5, show.legend = F) +
guides(fill = guide_legend(title = "Genera")) +
scale_fill_manual(values = c("brown1", "chocolate1",
"darkgoldenrod1", "darkgreen",
"deepskyblue", "darkslateblue",
"darkorchid4", "hotpink1",
"lightpink"))
If you want to arrange in descending order of frequency, you should remember to also set the factor levels of the group variable to the same order.
gb2020label <-
generabreakdown2020 %>%
mutate(perc = value/ sum(value)) %>%
mutate(labels = scales::percent(perc)) %>%
arrange(desc(perc)) %>% ## arrange in descending order of frequency
mutate(group = fct_rev(fct_inorder(group))) %>% ## also arrange the groups in descending order of freq
mutate(text_y = cumsum(value) - value/2) ### calculate where to place the text labels
gb2020label %>%
ggplot(aes(x = "", y = value, fill = group)) +
geom_col() +
coord_polar(theta = "y") +
geom_label_repel(aes(label = labels, y = text_y),
nudge_x = 0.6, nudge_y = 0.6,
size = 5, show.legend = F) +
guides(fill = guide_legend(title = "Genera")) +
scale_fill_manual(values = c("brown1", "chocolate1",
"darkgoldenrod1", "darkgreen",
"deepskyblue", "darkslateblue",
"darkorchid4", "hotpink1",
"lightpink"))
Created on 2021-10-27 by the reprex package (v2.0.1)
You didn't provide us with your data to work with so I'm using ggplot2::mpg here.
library(tidyverse)
library(ggrepel)
mpg_2 <-
mpg %>%
slice_sample(n = 20) %>%
count(manufacturer) %>%
mutate(perc = n / sum(n)) %>%
mutate(labels = scales::percent(perc)) %>%
arrange(desc(manufacturer)) %>%
mutate(text_y = cumsum(n) - n/2)
Chart without polar coordinates
mpg_2 %>%
ggplot(aes(x = "", y = n, fill = manufacturer)) +
geom_col() +
geom_label(aes(label = labels, y = text_y))
Chart with polar coordinates and geom_label_repel
mpg_2 %>%
ggplot(aes(x = "", y = n, fill = manufacturer)) +
geom_col() +
geom_label_repel(aes(label = labels, y = text_y),
force = 0.5,nudge_x = 0.6, nudge_y = 0.6) +
coord_polar(theta = "y")
But maybe your data isn’t dense enough to need repelling?
mpg_2 %>%
ggplot(aes(x = "", y = n, fill = manufacturer)) +
geom_col() +
geom_label(aes(label = labels, y = text_y), nudge_x = 0.6) +
coord_polar(theta = "y")
Created on 2021-10-26 by the reprex package (v2.0.1)

How to make A racing Bar Chart in R

I have a dataset that has a column of years from 1965 to 2020 and Teams that have won the championship in the respective years.
I am trying to create a racing bar chart and so far I have been struggling to create the required dataset to create the animated GIF
df1 <- df %>%
group_by(Team) %>%
mutate(cups = 1:n()) %>%
ungroup() %>%
group_by(Year) %>% spread(Year, cups) %>%
replace(is.na(.),0)
which brings a result of the following format.
Kindly assist in how I should go about completing this racing bar chart as I have browsed through several resources but I still cant seem to crack it..
Check if this work, as Jon mentioned you need to pivot your data using pinot_longer
df1 <- pivot_longer(df, -1, names_to = 'Year') %>%
rename(Team= ï..Team) %>%
mutate(Year = as.numeric(substr(Year, 2, 5)))
Then this should create the racing barchart"
df1 <- df1 %>%
group_by(Year) %>%
# The * 1 makes it possible to have non-integer ranks while sliding
mutate(rank = min_rank(-value) * 1,
Value_rel = value/value[rank==1],
Value_lbl = paste0(" ",value)) %>%
filter(rank <=10) %>% # This would show the top 10 teams
ungroup()
p <- ggplot(df1, aes(rank, group = Team,
fill = as.factor(Team), color = as.factor(Team))) +
geom_tile(aes(y = value/2,
height = value,
width = 0.9), alpha = 0.8, color = NA) +
geom_text(aes(y = 0, label = paste(Team, " ")), vjust = 0.2, hjust = 2) +
geom_text(aes(y=value,label = Value_lbl, hjust=0)) +
coord_flip(clip = "off", expand = FALSE) +
scale_y_continuous(labels = scales::comma) +
scale_x_reverse() +
guides(color = FALSE, fill = FALSE) +
labs(title='{closest_state}', x = "", y = "Your Title",
caption = "Your Caption") +
theme(plot.title = element_text(hjust = 0, size = 22),
axis.ticks.y = element_blank(), # These relate to the axes post-flip
axis.text.y = element_blank(), # These relate to the axes post-flip
plot.margin = margin(1,1,1,4, "cm")) +
transition_states(Year, transition_length = 4, state_length = 1) +
ease_aes('cubic-in-out')
animate(p, 200, fps = 10, duration = 40, width = 800, height = 600, renderer = gifski_renderer("gganim.gif"))
anim_save("YourPath//Name.gif")

gganimate horizontal column chart won't transition bars smoothly

I am creating a bar chart race animation using geom_colh from the ggstance package. Right now, the animation is very choppy and doesn't appear to be one continuous animation, instead just one image after another. Below is what the current animation looks like:
Instead, I want the bars to "glide" from one position to another when they pass each other. Below is the reprex of the code I currently have:
library(tidyverse)
library(dplyr)
library(ggplot2)
library(gganimate)
library(ggstance)
library(zoo)
library(gifski)
library(shadowtext)
stats <- read_csv(url("https://raw.githubusercontent.com/samhoppen/Fantasy-Evaluator/main/Data/Animation%20Test%20Data.csv")) %>%
mutate(unique_id = paste0(player_name, recent_team))
all_weeks <- read_csv(url("https://raw.githubusercontent.com/samhoppen/Fantasy-Evaluator/main/Data/Animation%20Weeks%20Data.csv"))
NFL_pri <- stats$team_color
names(NFL_pri) <- stats$unique_id
NFL_sec <- stats$team_color2
names(NFL_sec) <- stats$unique_id
rb_ani <- ggplot(data = stats, aes(group = player_name)) +
geom_colh(aes(x = tot_fpts, y = rank, color = unique_id, fill = unique_id), position = 'identity',
size = 2, width = 0.8) +
scale_x_continuous(expand = expansion(mult = c(0, 0.05))) +
scale_y_reverse(expand = expansion(mult = c(0.01, 0.01)))+
geom_shadowtext(aes(x = name_loc, y = rank, label = player_name, color = unique_id),
bg.color = 'white', size = 5.5, na.rm = T, bg.r = 0.075, show.legend = FALSE) +
scale_color_manual(values = NFL_sec)+
scale_fill_manual(values = NFL_pri)+
labs(title = "Highest-scoring Fantasy Running Backs of the Past Decade",
subtitle = paste0("{all_weeks$week_name[as.numeric(previous_state)]}"),
caption = "Figure: #SamHoppen | Data: #nflfastR",
y = "",
x = "Total Fantasy Points")+
theme(legend.position = "none",
plot.title = element_text(size = 24, face = "bold", margin = margin(0,0,10,0)),
plot.subtitle = element_text(size = 12, margin = margin(0,0,10,0)),
plot.caption = element_text(size = 12)) +
transition_states(states = week_order, transition_length = 2, state_length = 1, wrap = F) +
view_follow(fixed_y = TRUE) +
enter_fly(y_loc = -21) +
exit_fly(y_loc = -21) +
ease_aes('linear')
anim <- animate(rb_ani, nframes = 100, fps = 5,renderer = gifski_renderer(), height = 900, width = 1600)
I've tried changing the transition length/state length, removing the theme items, removing the colors, removing the stat = 'identity' argument, changing the group variable, and the number of frames/fps. I'm at a loss of what to try next. Any suggestions would be great!
Part of the challenge here is very choppy rankings week to week. To make the animation smooth, you'll need to either make the animation pretty long, or select a subset of weeks to calculate rankings on. Here I've limited to just week 30-39, and added more frames.
I also did some more data cleaning to give all the players a rank in each week even if they aren't included in stats that week.
animate(
stats %>%
# Some week_name missing from stats, will use week_order to get from all_weeks
select(-week_name) %>%
left_join(all_weeks %>% select(week_order, week_name), by = "week_order") %>%
# add every week for each player, and fill in any missing tot_fpts or team_colors
select(week_order, week_name, player_name, tot_fpts,
unique_id, team_color, team_color2) %>%
complete(week_order, player_name) %>%
fill(tot_fpts, .direction = "down") %>%
fill(unique_id, team_color, team_color2, .direction = "downup") %>%
# only keep players who had >0 max_tot_fpts and weeks 30-39
group_by(player_name) %>%
mutate(max_tot_fpts = max(tot_fpts)) %>%
filter(max_tot_fpts > 0, week_order >= 30, week_order < 40) %>%
# smooth out tot_fpts
mutate(tot_fpts_smooth = spline(x = week_order, y = tot_fpts, xout = week_order)$y) %>%
# Calc rank for every week, only keep top 20
group_by(week_order) %>%
arrange(-tot_fpts_smooth, player_name) %>%
mutate(rank = row_number()) %>%
ungroup() %>%
filter(rank <= 20) %>%
ggplot(aes(group = player_name, y = rank)) +
geom_tile(aes(x = tot_fpts/2, height = 0.9, width = tot_fpts,
color = unique_id, fill = unique_id)) +
geom_shadowtext(aes(x = tot_fpts, y = rank, label = player_name, color = unique_id),
bg.color = 'white', size = 3.5, na.rm = T, bg.r = 0.075,
show.legend = FALSE, hjust = 1.1) +
# geom_text(aes(x = tot_fpts, label = paste(player_name, " ")), vjust = 0.2, hjust = 1) +
scale_y_reverse(breaks = 1:20, minor_breaks = NULL) +
scale_color_manual(values = NFL_sec)+
scale_fill_manual(values = NFL_pri)+
labs(title = "Highest-scoring Fantasy Running Backs of the Past Decade",
subtitle = paste0("{all_weeks$week_name[as.numeric(previous_state)]}"),
caption = "Figure: #SamHoppen | Data: #nflfastR",
y = "",
x = "Total Fantasy Points")+
theme_minimal() +
theme(legend.position = "none",
plot.title = element_text(size = 14, face = "bold", margin = margin(0,0,10,0)),
plot.subtitle = element_text(size = 12, margin = margin(0,0,10,0)),
plot.caption = element_text(size = 12)) +
transition_states(week_order, state_length = 0) +
view_follow(fixed_y = TRUE) +
enter_fly(y_loc = -21) +
exit_fly(y_loc = -21) +
ease_aes('linear'),
fps = 20, duration = 4, width = 400, height = 300)

Text color with geom_label_repel

Not specific to any particular piece of code, is there a relatively straightforward way to change the color of the text in a geom_label_repel box?
Specifically, I have code that produces the below chart
The percentage in the label box is the percent change in 7-day moving average for the most recent week over the week prior. I'd simply like to color the text red when the value is positive and green when it is negative.
The dataframe for this chart can be copied from here.
The plot code is
#endpoint layer
BaseEndpoints <- smDailyBaseData %>% filter(Base %in% AFMCbases) %>%
group_by(Base) %>%
filter(DaysSince == max(DaysSince)) %>%
select(Base, abbv, DaysSince, newRate,label) %>%
ungroup()
ZoomEndpoints <- BaseEndpoints %>% filter(Base != 'Edwards') %>%
mutate(zoom = TRUE)
CAEndPoint <- BaseEndpoints %>% filter(Base == 'Edwards') %>%
mutate(zoom = FALSE)
ZoomEndpoints <- rbind(ZoomEndpoints, CAEndPoint)
BasePlot <- smDailyBaseData %>% filter(Base %in% AFMCbases) %>%
ggplot(mapping = aes(x = as.numeric(DaysSince), y = newRate)) +
geom_line(aes(color=abbv),show.legend = FALSE) +
scale_color_ucscgb() +
geom_point(data = BaseEndpoints,size = 1.5,shape = 21,
aes(color = abbv,fill = abbv), show.legend = FALSE) +
geom_label_repel(data=ZoomEndpoints, aes(label=label), show.legend = FALSE,
vjust = 0, xlim=c(105,200), size=3, direction='y') +
labs(x = "Days Since First Confirmed Case",
y = "% Local Population Infected Daily") +
theme(plot.title = element_text(size = rel(1), face = "bold"),
plot.subtitle = element_text(size = rel(0.7)),
plot.caption = element_text(size = rel(1))) +
facet_zoom(xlim = c(50,120), ylim=c(0,0.011),zoom.data=zoom)
print(BasePlot)
Yes, it's as simple as this:
library(ggplot2)
df <- data.frame(x = c(-1, -1, 1, 1), y = c(-1, 1, 1, -1), value = c(-2, -1, 1, 2))
ggplot(df, aes(x, y)) +
geom_point(size = 3) +
ggrepel::geom_label_repel(aes(label = value, colour = factor(sign(value)))) +
lims(x = c(-100, 100), y = c(-100, 100)) +
scale_colour_manual(values = c("red", "forestgreen"))
EDIT
Now we have a more concrete example, I can see the problem more clearly. There are workarounds such as using ggnewscale or a hand-crafted solution such as Ian Campbell's thorough example. Personally, I would just note that you haven't used the fill scale yet, and this looks pretty good to my eye:
Here's a bit of a hacky solution since you can't have two scale_color_*'s at the same time:
The approach centers on manually assigning the color outside of aes in the geom_label_repel call. Adding one to the grepl result that searches for the minus sign in the label allows you to subset the two colors. You need two colors for each label, I assume for the box and for the text, so I used rep.
smDailyBaseData %>%
ggplot(mapping = aes(x = as.numeric(DaysSince), y = newRate)) +
geom_line(aes(color=abbv),show.legend = FALSE) +
scale_color_ucscgb() +
geom_point(data = BaseEndpoints,size = 1.5,shape = 21,
aes(color = abbv,fill = abbv), show.legend = FALSE) +
geom_label_repel(data=ZoomEndpoints, aes(label=label),
color = rep(c("green","red")[1+grepl("\\-\\d",as.factor(ZoomEndpoints$label))],times = 2),
show.legend = FALSE, vjust = 0, xlim=c(105,200),
size=3, direction='y') +
labs(x = "Days Since First Confirmed Case",
y = "% Local Population Infected Daily") +
theme(plot.title = element_text(size = rel(1), face = "bold"),
plot.subtitle = element_text(size = rel(0.7)),
plot.caption = element_text(size = rel(1))) +
facet_zoom(xlim = c(50,120), ylim=c(0,0.011),zoom.data=zoom)
Data Setup
#source("https://pastebin.com/raw/Vn2abQ4a")
BaseEndpoints <- smDailyBaseData %>%
group_by(Base) %>%
dplyr::filter(DaysSince == max(DaysSince)) %>%
dplyr::select(Base, abbv, DaysSince, newRate,label) %>%
ungroup()
ZoomEndpoints <- BaseEndpoints %>% filter(Base != 'Edwards') %>%
mutate(zoom = TRUE)
CAEndPoint <- BaseEndpoints %>% filter(Base == 'Edwards') %>%
mutate(zoom = FALSE)
ZoomEndpoints <- rbind(ZoomEndpoints, CAEndPoint)

Including images on axis label in an animated ggplot2

I created an animated bar plot displaying goals scored by players (fictional).
Please see the reproduced data for the example:
df <- data.frame(Player = rep(c("Aguero", "Salah", "Aubameyang", "Kane"), 6),
Team = rep(c("ManCity", "Liverpool", "Arsenal", "Tottenham"), 6),
Gameday = c(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6),
Goals = c(0,1,2,0,1,1,3,1,2,1,3,2,2,2,4,3,3,2,4,5,5,3,5,6),
stringsAsFactors = F)
Following animated bar plot are created by the code below.
# loading required
library(tidyverse)
library(gganimate)
library(png)
Edited:
I would like to include following icons for each player:
icon1.png <- image_read('https://raw.githubusercontent.com/sialbi/examples/master/player1.png')
icon2.png <- image_read('https://raw.githubusercontent.com/sialbi/examples/master/player2.png')
icon3.png <- image_read('https://raw.githubusercontent.com/sialbi/examples/master/player3.png')
icon4.png <- image_read('https://raw.githubusercontent.com/sialbi/examples/master/player4.png')
gap <- df %>%
group_by(Gameday) %>%
mutate(rank = min_rank(-Goals) * 1,
Value_rel = Goals/Goals[rank==1],
Value_lbl = paste0(" ", Goals)) %>%
filter(rank <=10) %>%
ungroup()
gap %>%
group_by(Player) %>%
arrange(Gameday) %>%
mutate(prev.rank = lag(rank)) %>%
ungroup() %>%
group_by(Gameday) %>%
arrange(rank, prev.rank) %>%
mutate(x = seq(1, n())) %>%
ungroup() %>%
ggplot(aes(x = x, y = Goals, fill = Player, color = Player)) +
geom_col() +
geom_text(aes(y = 0, label = Player), size = 5, color="black", hjust = -0.05) +
geom_text(aes(label = Value_lbl), hjust = 0) +
coord_flip(clip = "off", expand = FALSE) +
scale_y_continuous(labels = scales::comma) +
scale_x_reverse() +
guides(color = FALSE, fill = FALSE) +
labs(title = "Gameday: {closest_state}", x="", y = "Goals scored") +
theme(plot.title = element_text(hjust = 0, size = 26),
axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
plot.margin = margin(1,1,1,4, "cm")) +
transition_states(Gameday, transition_length = 4, state_length = 1) +
ease_aes('cubic-in-out')
Problem
To complete the animation I would like to include a picture of each player on the y axis. Below I edited the animation to display the desired result (the circles were chosen to avoid violating any copyrights).
The images (circles) should also move up and down as the bars.
Is there are way to include images on the y-axis?
Edited Code
After the presented suggestions I was able to fix the problems. The code below is working accordingly.
library(imager)
library(ggimage)
library(magick)
library(tidyverse)
library(gganimate)
library(png)
library(gapminder)
#read data
df <- data.frame(Player = rep(c("Aguero", "Salah", "Aubameyang", "Kane"), 6),
Team = rep(c("ManCity", "Liverpool", "Arsenal", "Tottenham"), 6),
Gameday = c(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6),
Goals = c(0,1,2,0,1,1,3,1,2,1,3,2,2,2,4,3,3,2,4,5,5,3,5,6),
stringsAsFactors = F)
# import images
df2 <- data.frame(Player = c("Aguero", "Salah", "Aubameyang", "Kane"),
Image = sample(c("https://raw.githubusercontent.com/sialbi/examples/master/player1.png",
"https://raw.githubusercontent.com/sialbi/examples/master/player2.png",
"https://raw.githubusercontent.com/sialbi/examples/master/player3.png",
"https://raw.githubusercontent.com/sialbi/examples/master/player4.png")),
stringsAsFactors = F)
gap <- df %>%
group_by(Gameday) %>%
mutate(rank = min_rank(-Goals) * 1,
Value_rel = Goals/Goals[rank==1],
Value_lbl = paste0(" ", Goals)) %>%
filter(rank <=10) %>%
ungroup()
p = gap %>%
left_join(df2, by = "Player") %>% # add image file location to the dataframe being
group_by(Player) %>%
arrange(Gameday) %>%
mutate(prev.rank = lag(rank)) %>%
ungroup() %>%
group_by(Gameday) %>%
arrange(rank, prev.rank) %>%
mutate(x = seq(1, n())) %>%
ungroup()
ggplot(p, aes(x = x, y = Goals, fill = Player, color = Player)) +
geom_col() +
geom_text(aes(y = 0, label = Player), size = 5, color="black", hjust = -0.05) +
geom_text(aes(label = Value_lbl), hjust = 0) +
# where the error occurs
geom_image(aes(x = x, Image = Image), y = 0,
size = 0.25, hjust = 1,
inherit.aes = FALSE) +
coord_flip(clip = "off", expand = FALSE) +
scale_y_continuous(labels = scales::comma) +
scale_x_reverse() +
guides(color = FALSE, fill = FALSE) +
labs(title = "Gameday: {closest_state}", x = "", y = "Goals scored") +
theme_classic() +
theme(plot.title = element_text(hjust = 0, size = 26),
axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
plot.margin = margin(1, 1, 1, 4, "cm")) +
transition_states(Gameday, transition_length = 4, state_length = 1) +
ease_aes('cubic-in-out')
You can try the following:
Step 0. Create png images for use, because I don't want to worry about copyright violations either.
emoji.list <- c("grinning", "smile", "heart_eyes", "smirk")
for(i in seq_along(emoji.list)) {
ggsave(paste0("icon", i, ".png"),
ggplot() +
emojifont::geom_emoji(alias = emoji.list[i], size = 10, vjust = 0.5) +
theme_void(),
width = 0.4, height = 0.4, units = "in")
}
rm(emoji.list, i)
Step 1. Create a data frame mapping each player to the location of his image file.
df2 <- data.frame(Player = c("Aguero", "Salah", "Aubameyang", "Kane"),
Image = c("icon1.png", "icon2.png", "icon3.png", "icon4.png"),
stringsAsFactors = F)
Step 2. Add image to plot in a new geom_image layer, & animate everything as before.
library(ggimage)
gap %>%
left_join(df2, by = "Player") %>% # add image file location to the dataframe being
# passed to ggplot()
group_by(Player) %>%
arrange(Gameday) %>%
mutate(prev.rank = lag(rank)) %>%
ungroup() %>%
group_by(Gameday) %>%
arrange(rank, prev.rank) %>%
mutate(x = seq(1, n())) %>%
ungroup() %>%
ggplot(aes(x = x, y = Goals, fill = Player, color = Player)) +
geom_col() +
geom_text(aes(y = 0, label = Player), size = 5, color="black", hjust = -0.05) +
geom_text(aes(label = Value_lbl), hjust = 0) +
geom_image(aes(x = x, image = Image), y = 0, # add geom_image layer
size = 0.25, hjust = 1,
inherit.aes = FALSE) +
coord_flip(clip = "off", expand = FALSE) +
scale_y_continuous(labels = scales::comma) +
scale_x_reverse() +
guides(color = FALSE, fill = FALSE) +
labs(title = "Gameday: {closest_state}", x = "", y = "Goals scored") +
theme_classic() +
theme(plot.title = element_text(hjust = 0, size = 26),
axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
plot.margin = margin(1, 1, 1, 4, "cm")) +
transition_states(Gameday, transition_length = 4, state_length = 1) +
ease_aes('cubic-in-out')

Resources