Help with Animated Bar Plots

I recently came across a very useful tutorial on animated bar plots from datascienceplus: (How to build Animated Bar Plots using R | DataScience+) I began using it for a project of my own connected to my own system of ranking baseball players. I used the code as a template almost exactly, and have been able to create the animated bar graphs, but I'm running into two minor problems on my end:

  1. The bars aren't beginning at the start of the y-axis, they are oddly starting at a mid point between the Name's quantitave variable and 0.

  2. Instead of the quantitative variables being displayed on the right of the bar like in the post, they are being displayed directly to the right of the y-axis in the space that should be occupied by the bars extending to 0.

Here's an image for reference:

. I can only post one image per post, but you can see the difference at the link.

Here's the code for reference, in case I glossed over something. I'm pretty new to R Studio, and was somewhat amazed I was even able to make the animation. I tried messaging the author and didn't get a response. If anyone knew how to fix any of the above problems, I'd appreciate it!

staticplot = ggplot(imssformatted2, aes(rank, group = Name, 
                                        fill = as.factor(Name), color = as.factor(Name))) +
  geom_tile(aes(y = TotalScore,
                height = TotalScore,
                width = 0.9), alpha = 0.8, color = NA) +
  geom_text(aes(y = 0, label = paste(Name, " ")), size = 4, hjust = 1) +
  geom_text(aes(y = value_rel, label = TotalScore, size = 25, hjust = 0)) +
  coord_flip(clip = "off", expand = FALSE) +
  scale_y_continuous(labels = scales::comma) +
  scale_x_reverse() +
  guides(color = FALSE, fill = FALSE) +
  theme(axis.line = element_blank(),
        axis.text.x = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y= element_blank(),
        legend.position = "none",
        panel.background = element_blank(),
        panel.border = element_blank(),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.grid.major.x = element_line( size=.1, color="grey" ),
        plot.title = element_text(size=25, hjust=0.5, face="bold", colour="grey", vjust=-1),
        plot.subtitle = element_text(size=18, hjust=0.5, face="italic", color="grey"),
        plot.caption = element_text(size=12, hjust=0.5, face="italic", color="grey"),
        plot.background = element_blank(),
        plot.margin = margin(2, 2, 2, 4, "cm"))

anim = staticplot + transition_states(iRole, transition_length = 4, state_length = 1) +
  view_follow(fixed_x = TRUE)  +
  labs(title = 'Top 10 Players by Role : {closest_state}',  
       subtitle  =  "by imSS",
       caption  = "First Five Years of imSS Data | 2015-2019")

animate(anim, 200, fps = 0.92,  width = 1200, height = 1000,
        renderer = gifski_renderer("gganim.gif"))

Hi!

To help us help you, could you please prepare a reproducible example (reprex) illustrating your issue? Please have a look at this guide, to see how to create one:

Hi. For some reason, when I was writing the draft, it didn't post the chunk of code I had typed in, or the image I included for reference.

The code you provided without data is not runnable, so it becomes harder to assist you.
i.e. you have the object imssformatted2 but we forum users don't.

Sorry about that. I'm trying to create an example, but I'm pouring through the built-in datasets and am still trying to find one that I can replicate this with. I need a dataset that has two categorical variables that appear in multiple rows, because X amount of time passes between observations, with a changing quantitative variable. If you knew off the top of your head which one might be a good one to use, then I can replicate this, but I'll keep looking.

rather than built-ins, why not a fraction of your actual data, to serve as example ?

How do I get it to you? Include it in the post?

I will copy and paste from the link I sent your earlier


Minimal Dataset (Sample Data)

You need to provide a data frame that is small enough to be (reasonably) pasted on a post, but big enough to reproduce your issue.

Let's say, as an example, that you are working with the iris data frame

head(iris)
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1          5.1         3.5          1.4         0.2  setosa
#> 2          4.9         3.0          1.4         0.2  setosa
#> 3          4.7         3.2          1.3         0.2  setosa
#> 4          4.6         3.1          1.5         0.2  setosa
#> 5          5.0         3.6          1.4         0.2  setosa
#> 6          5.4         3.9          1.7         0.4  setosa

Note: In this example we are using the built-in dataset iris , as a representation of your actual data, you should use your own dataset instead of iris, or if your problem can be reproduced with any dataset, then you could use iris directly (or any other built-in dataset e.g. mtcars , ToothGrowth , PlantGrowth , USArrests , etc.) and skip this step.

And you are having issues while trying to do a scatter plot between Sepal.Length and Sepal.Width , so a good minimal sample data for this case would be just the first 5 rows of those two variables, this doesn't mean that you have to necessarily do the same, use your best judgment to decide the minimal amount of sample data needed to exemplify your specific problem.

head(iris, 5)[, c('Sepal.Length', 'Sepal.Width')]
#>   Sepal.Length Sepal.Width
#> 1          5.1         3.5
#> 2          4.9         3.0
#> 3          4.7         3.2
#> 4          4.6         3.1
#> 5          5.0         3.6

Now you just need to put this into a copy/paste friendly format for been posted in the forum, and you can easily do it with the datapasta package.

# If you don't have done it already, You have to install datapasta first with
# install.packages("datapasta")
datapasta::df_paste(head(iris, 5)[, c('Sepal.Length', 'Sepal.Width')])
# This is the sample data that you have to use in your reprex.
data.frame(
      Sepal.Length = c(5.1, 4.9, 4.7, 4.6, 5),
       Sepal.Width = c(3.5, 3, 3.2, 3.1, 3.6)
   )

A nice guide about datapasta can be found here:

maraaverick.rbind.io – 30 Oct 18

reprex-ing with {datapasta} :spaghetti:

How to use {datapasta} to put data in a reprex.

You can also use dput provided in base , which is as simple as this:

dput(head(iris, 5)[c("Sepal.Length", "Sepal.Width")])
#> structure(list(Sepal.Length = c(5.1, 4.9, 4.7, 4.6, 5), Sepal.Width = c(3.5, 
#> 3, 3.2, 3.1, 3.6)), row.names = c(NA, 5L), class = "data.frame")

This output may seem awkward compared to the output of datapasta , but it's much more general in the sense that it supports many more types of R objects.

OK. Since it would've been too complicated to post my data, I wound up continuing to look for built-ins that I could use. I took the Theoph dataset, and for this example, created a new Categorical variable to rank subjects within. Then ranked subjects within the mean theophylline concentration. I'm running into the same problem, where the bars aren't lining up on the left axis, and the actual categorical variables used for the rankings, are displayed, but lined up on the right end of the bars.


attach(Theoph)
Theoph$DoseRange[Dose > 5.29] <- "High"
Theoph$DoseRange[Dose > 4.39 & Dose < 5.2] <- "Medium"
Theoph$DoseRange[Dose < 4.1] <- "Low"
detach(Theoph)

**
Dose_Groups <- group_by(Theoph, Subject)
AggSubj <- summarise(Dose_Groups, 
                       AvConc = mean(conc),
                       DoseRange = DoseRange,
                       Dose = Dose,
                       n = n())
AggSubj <- arrange(AggSubj)
AggSubj <- unique(AggSubj)

**
Theophformatted <- arrange(AggSubj %>%
       group_by(DoseRange) %>%
       mutate(rank = rank(-AvConc)),
       group_by(Subject) %>% 
       filter(rank <=3) %>%
       ungroup())

**
staticplotT = ggplot(Theophformatted, aes(rank, group = Subject, 
      fill = as.factor(Subject), color = as.factor(Subject))) +
  geom_tile(aes(y = AvConc,
          height = AvConc,
          width = 0.9), alpha = 0.8, color = NA) +
  geom_text(aes(y = 0, label = paste(Subject, " ")), size = 4, hjust = 1) +
  geom_text(aes(y = AvConc, label = AvConc, size = 25, hjust = 0)) +
  coord_flip(clip = "off", expand = FALSE) +
  scale_y_continuous(labels = scales::comma) +
  scale_x_reverse() +
  guides(color = FALSE, fill = FALSE) +
  theme(axis.line = element_blank(),
        axis.text.x = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y= element_blank(),
        legend.position = "none",
        panel.background = element_blank(),
        panel.border = element_blank(),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.grid.major.x = element_line( size=.1, color="grey" ),
        plot.title = element_text(size=25, hjust=0.5, face="bold", colour="grey", vjust=-1),
        plot.subtitle = element_text(size=18, hjust=0.5, face="italic", color="grey"),
        plot.caption = element_text(size=12, hjust=0.5, face="italic", color="grey"),
        plot.background = element_blank(),
        plot.margin = margin(2, 2, 2, 4, "cm"))

animT = staticplotT + transition_states(DoseRange, transition_length = 4, state_length = 1) +
  view_follow(fixed_x = TRUE)  +
  labs(title = 'Top 3 Subjects by Dose Range : {closest_state}',  
       subtitle  =  "by Doseage")

animate(animT, 200, fps = 0.92,  width = 1200, height = 1000,
        renderer = gifski_renderer("gganimT.gif"))

Try it again. When I pasted it, it cut off line 1 with "attach."

Theophformatted <- arrange(AggSubj %>%
       group_by(DoseRange) %>%
       mutate(rank = rank(-AvConc)),
       group_by(Subject) %>% 
       filter(rank <=3) %>%
       ungroup())

the comma after mutate should be another pipe right ?

You're right, sorry. Should be %>%. (didn't know that was called a pipe until just now) thanks.

Hey. Just wondering if you had a chance to check my coding here? I could try again to post my own data, but I'm running into the exact same problem as with the Theoph. Appreciate the help!

I'm sorry, but.. your static plot is incomprehensible. You should have a reasonable plot first before you dream of animating it (in my opinion)

I understand, but I thank you for checking back in here. I lifted it as closely as possible from the example from Datascienceplus that I posted, and obviously I was able to animate it on my end, but the example itself probably has too many lines of code in it.

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.