Issue with shadow_mark() in gganimate - r

I've created a gif using gganimate that shows NBA players regular season points per game and compares it to their points per game in the playoffs. I have everything working except i have a graphical issue with shadow_mark(). The gif starts at the playoffs, transitions to the regular season mark, and then transitions back to playoffs mark.
I want shadow_mark() to keep the playoffs mark on the graph at all times with 50% opacity like i have it right now. I don't want the regular season mark to stay on the graph, but I don't know how to get rid of it. I've tried various combinations of past = TRUE and future = FALSE etc in shadow_mark() but it doesn't seem to have solved it. I've also tried exclude_layer = 1 but then that deletes both of the shadows instead of just the 1.
Here is my gif as of right now. Below is the code used to create it.
j <- ggplot(nba2, aes(x = PPG, y = Player)) +
geom_point(shape = 21, stroke = 1, aes(fill = Tm, size = 2)) +
theme(legend.title = element_blank(), legend.position = 'none') +
xlab("Points Per Game") +
labs(caption = 'Data via basketball-reference.com')
plot(j)
anim <- j +
transition_states(Playoff_or_reg,
transition_length = 2,
state_length = 2,
wrap = TRUE) +
shadow_mark(past = TRUE, future = FALSE, alpha = 0.5) +
ggtitle("{closest_state}")
anim
Any help on how to fix this issue would be appreciated!

What you wanna do is create a new variable that equals each player's PPG in the regular season. That variable is going to be your static, transparent point. The original variable is the one that is going to transition.
Here's what the code for that viz might look like:
df %>%
ggplot(aes(x = Player, y = PPG, color = Tm, fill = Tm)) +
geom_point(size = 4.5, shape = 21, alpha = 1, stroke = 1) +
geom_point(size = 4.5, shape = 21, alpha = .2, stroke = 1, aes(fill = Tm, color = Tm, x = Player, y = newPPG)) +
coord_flip() +
theme(legend.position = 'none') +
transition_states(
Playoff_or_reg,
transition_length = 1,
state_length = 2)
Hope that helps

Related

Why are colours appearing in the labels of my gganimate sketch?

I have a gganimate sketch in R and I would like to have the percentages of my bar chart appear as labels.
But for some bizarre reason, I am getting seemingly random colours in place of the labels that I'm requesting.
If I run the ggplot part without animating then it's a mess (as it should be), but it's obvious that the percentages are appearing correctly.
Any ideas? The colour codes don't correspond to the colours of the bars which I have chosen separately. The codes displayed also cycle through about half a dozen different codes, at a rate different to the frame rate that I selected. And while the bars are the same height (they grow until they reach the chosen height displayed in the animation) then they display the same code until they stop and it gets frozen.
Code snippet:
df_new <- data.frame(index, rate, year, colour)
df_new$rate_label <- ifelse(round(df_new$rate, 1) %% 1 == 0,
paste0(round(df_new$rate, 1), ".0%"), paste0(round(df_new$rate, 1), "%"))
p <- ggplot(df_new, aes(x = year, y = rate, fill = year)) +
geom_bar(stat = "identity", position = "dodge") +
scale_fill_manual(values = colour) +
#geom_text(aes(y = rate, label = paste0(rate, "%")), vjust = -0.7) +
geom_shadowtext(aes(y = rate, label = rate_label),
bg.colour='white',
colour = 'black',
size = 9,
fontface = "bold",
vjust = -0.7,
alpha = 1
) +
coord_cartesian(clip = 'off') +
ggtitle("% population belonging to 'No religion', England and Wales census") +
theme_minimal() +
xlab("") + ylab("") +
theme(legend.position = "none") +
theme(plot.title = element_text(size = 18, face = "bold")) +
theme(axis.text = element_text(size = 14)) +
scale_y_continuous(limits = c(0, 45), breaks = 10*(0:4))
p
p <- p + transition_reveal(index) + view_follow(fixed_y = T)
animate(p, renderer = gifski_renderer(), nframes = 300, fps = frame_rate, height = 500, width = 800,
end_pause = 0)
anim_save("atheism.gif")
I think you have missed some delicate points about ggplot2. I will try my best to describe them to you. First of all, you need to enter the discrete values as factor or integer. So you can use as.factor() before plotting or just factor() in the aesthetic. Also, you should consider rounding the percentages as you wish. Here is an example:
set.seed(2023)
df_new <- data.frame(index=1:10, rate=runif(10), year=2001:2010, colour=1:10)
df_new$rate_label <- ifelse(round(df_new$rate, 1) %% 1 == 0,
paste0(round(df_new$rate, 1), ".0%"),
paste0(round(df_new$rate, 1), "%"))
The ggplot for this data is:
library(ggplot2)
p <- ggplot(df_new, aes(x = factor(year), y = rate, fill = factor(colour))) +
geom_bar(stat = "identity", position = "dodge") +
geom_text(aes(y = rate, label = paste0(round(rate,2), "%")), vjust = -0.7) +
coord_cartesian(clip = 'off') +
ggtitle("% population belonging to 'No religion', England and Wales census") +
theme_minimal() +
xlab("") + ylab("") +
theme(legend.position = "none",
plot.title = element_text(size = 18, face = "bold"),
axis.text = element_text(size = 14))
p
And you can combine all theme element in one theme() function (as did I). The output is:
And you can easily animate the plot using the following code:
library(gganimate)
p + transition_reveal(index)
And the output is as below:
Hope it helps.
So it was answered here although I don't know why the fix works.
For some reason, labels need to go into gganimate as factors
as.factor()
I just had to add the line:
df_new$rate_label <- as.factor(df_new$rate_label)
and it works fine.

Issue with colour fill with gganimate and geom_sf

I'm having a problem with gganimate where it does not fill the geom_sf points I am using all of the time. A static version of the plot I'm using works fine:
precincts$margingroup <- cut(precincts$margin,
breaks = breaks, labels = c(1:37))
pointfig <- ggmap(myMap) +
geom_sf(data=centroids, aes(fill=precincts$margin,group=precincts$margingroup), size=precincts$dotsize, pch=21, alpha=1, inherit.aes = FALSE) +
scale_fill_gradient2(midpoint = 0, low='darkmagenta',
min = 'white',
high='orange',
limits = c(-50,50),
oob = scales::squish) +
geom_shadowtext(mapping = aes(x = longitude, y = latitude, label = name, vjust=vjust),
data = places, size = 5, fontface = "bold") +
labs(fill='Fidesz Margin, %',caption = "Data from valasztas.hu") +
ggtitle("Borsod-Abaúj-Zemplén 6th District By-Election by Precinct") +
theme_void() +
theme(legend.box.just = "center") +
theme(plot.title = element_text(size = 12, face = "bold", vjust=4)) +
theme(plot.margin = unit(c(1,1,1,1), "cm")) +
coord_sf()
But when I try to animate it I get an issue with fill. I want the points to appear in order of margin (but I had to group them so that there were fewer than 50 states).
anim <- pointfig + transition_states(precincts$margingroup,
transition_length = 1,
state_length = 0.45, wrap = FALSE) +
shadow_wake(wake_length = 0.1, alpha = TRUE)
This results in (small version for SO but you get the idea!):
The colours which appear towards the end are whole the whole thing should look. Any help would be hugely appreciated, thanks!

How to correct the position of labels on piechart in ggplot. Also tell me how produce 3D piechart

One of the value in my dataset is zero, I think because of that I am not able to adjust labels correctly in my pie chart.
#Providing you all a sample dataset
Averages <- data.frame(Parameters = c("Cars","Motorbike","Bicycle","Airplane","Ships"), Values = c(15.00,2.81,50.84,51.86,0.00))
mycols <- c("#0073C2FF", "#EFC000FF", "#868686FF", "#CD534CFF","#FF9999")
duty_cycle_pie <- Averages %>% ggplot(aes(x = "", y = Values, fill = Parameters)) +
geom_bar(width = 1, stat = "identity", color = "white") +
coord_polar("y", start = 0)+
geom_text(aes(y = cumsum(Values) - 0.7*Values,label = round(Values*100/sum(Values),2)), color = "white")+
scale_fill_manual(values = mycols)
Labels are not placed in the correct way. Please tell me how can get 3D piechart.
Welcome to stackoverflow. I am happy to help, however, I must note that piecharts are highly debatable and 3D piecharts are considered bad practice.
https://www.darkhorseanalytics.com/blog/salvaging-the-pie
https://en.wikipedia.org/wiki/Misleading_graph#3D_Pie_chart_slice_perspective
Additionally, if the names of your variables reflect your actual dataset (Averages), a piechart would not be appropriate as the pieces do not seem to be describing parts of a whole. Ex: avg value of Bicycle is 50.84 and avg value of Airplane is 51.86. Having these result in 43% and 42% is confusing; a barchart would be easier to follow.
Nonetheless, the answer to your question about placement can be solved with position_stack().
library(tidyverse)
Averages <-
data.frame(
Parameters = c("Cars","Motorbike","Bicycle","Airplane","Ships"),
Values = c(15.00,2.81,50.84,51.86,0.00)
) %>%
mutate(
# this will ensure the slices go biggest to smallest (a best practice)
Parameters = fct_reorder(Parameters, Values),
label = round(Values/sum(Values) * 100, 2)
)
mycols <- c("#0073C2FF", "#EFC000FF", "#868686FF", "#CD534CFF","#FF9999")
Averages %>%
ggplot(aes(x = "", y = Values, fill = Parameters)) +
geom_bar(width = 1, stat = "identity", color = "white") +
coord_polar("y", start = 0) +
geom_text(
aes(y = Values, label = label),
color = "black",
position = position_stack(vjust = 0.5)
) +
scale_fill_manual(values = mycols)
To move the pieces towards the outside of the pie, you can look into ggrepel
https://stackoverflow.com/a/44438500/4650934
For my earlier point, I might try something like this instead of a piechart:
ggplot(Averages, aes(Parameters, Values)) +
geom_col(aes(y = 100), fill = "grey70") +
geom_col(fill = "navyblue") +
coord_flip()

How to have x-axis span move with gganimate animation?

Using R, I am trying to make a line graph which is revealed left to right based on x-axis using gganimate. I have managed to do this but what I also wanted to do was make it so that the scale_x_continuous(limits = c(i-5,i+5)), i.e. there is a window around the point that is being revealed and the window will move along while the next point is being revealed.
I have tried many ways to get this including implementing some sort of loop in scale_x_continuous with and without aes(). Nothing seems to work. I am quite new with ggplot2 and especially with gganimate but I couldn't find any help online. I have a feeling the answer is probably quite simple and I just missed it.
Sort of like this but with gganimate:
The following is some reproducible code to show you roughly what I've done so far.
library(ggplot2)
library(gganimate)
library(gifski)
library(png)
Step <- c(1:50,1:50)
Name <- c(rep("A",50), rep("B",50))
Value <- c(runif(50,0,10), runif(50,10,20))
Final <- data.frame(Step, Name, Value)
a <- ggplot(Final, aes(x = Step, y = Value, group = Name, color = factor(Name))) +
geom_line(size=1) +
geom_point(size = 2) +
transition_reveal(Step) +
coord_cartesian(clip = 'off') +
theme_minimal() +
theme(plot.margin = margin(5.5, 40, 5.5, 5.5)) +
theme(legend.position = "none")
options(gganimate.dev_args = list(width = 7, height = 6, units = 'in', res=100))
animate(a, nframes = 100)
Don't use a transition, use a view. E.g.:
ggplot(Final, aes(x = Step, y = Value, color = factor(Name))) +
geom_line(size = 1) +
geom_point() +
view_zoom_manual(
0, 1, pause_first = FALSE, ease = 'linear', wrap = FALSE,
xmin = 1:40, xmax = 11:50, ymin = min(Final$Value), ymax = max(Final$Value)
) +
scale_x_continuous(breaks = seq(0, 50, 2))

How to insert several images into a bar graph using ggtextures and ggplot?

This post is an extension from this one
I want to know if I can use the ggtextures and ggplot packages to have two images side by side on a bar graph.
I've used ggtextures to have one image per bar, and it looks like this so far:
What I'm trying to do now is to add the NBA team logo next to the rookie pictures.
The code for the graph below is something like this:
a5 %>%
ggplot(aes(x = reorder(Player,
PER),
y = PER,
fill = Player,
image = c(image))) +
geom_bar(stat = "identity") +
geom_isotype_col(
img_height = grid::unit(1, "null"), img_width = NULL,
ncol = 1, nrow = 1, hjust = 1, vjust = 0.5
) +
coord_flip() +
theme_minimal() +
xlab("Player") +
ylab(PER) +
theme(legend.position = "none")
I have an image column in my data to correspond to the rookie picture, and I also have another column to correspond to the team the rookie plays in. Is there any way I can change
image = c(image)))
to something like c(image, NBAteams), and get it to work with the line,
geom_isotype_col(
img_height = grid::unit(1, "null"), img_width = NULL,
ncol = 1, nrow = 1, hjust = 1, vjust = 0.5
)
?

Resources