简体   繁体   中英

R animation ggplot using 'for loop' and listing

What I am trying to do is to make an animation ggplot having labels changing by the column names. So, my data is

EXTRACTION<-
structure(list(TICKERS = c("SPY", "IVV", "VTI"), X2020.11.02 = c(0, 
0, 0), X2020.11.04 = c(-0.0110832443075151, -0.0258415332395525, 
-0.028852983646287), X2020.11.08 = c(-0.00678564274087334, -0.028592196288115, 
-0.0287979806647458), X2020.11.11...5 = c(0.00362433932387574, 
-0.0183931126967061, -0.0159248566046306), X2020.11.11...6 = c(0.0475566216272374, 
-0.0043522045803146, -0.00278232172594206), X2020.11.17 = c(0.0210585321899657, 
-0.0175562162191414, -0.00540261044582935), X2020.11.19 = c(0.0574666424876265, 
0.00762503019098637, 0.0215144350034273), X2020.11.24 = c(0.0327027084626714, 
-0.00126684622955087, 0.00988617332076935), X2020.11.29 = c(0.0346871743474724, 
-0.00331008153617796, 0.0140402133559614), X2020.12.07 = c(0.0264324000235459, 
-0.00860290128787633, 0.00821403534252774), X2020.12.08...12 = c(0.0285459458362687, 
-0.00675657470727886, 0.00932080453971507)), row.names = c("SPY", 
"IVV", "VTI"), class = "data.frame")

This looks a bit messy so I will show how my data frame pretty much looks like

TICKERS X2020.11.02 X2020.11.03 X2020.11.04
SPY     SPY  -0.4461672   1.0571358  -0.3913777
IVV     IVV  -0.2668565   0.7148972  -0.2661292
VTI     VTI   2.0241657  -0.6570240  -0.8967357

(I changed the rownames to use the data more easily. Actually there are hundreds of tickers for the real list but I'll omit the others for easy understandings.)

I have managed to make a code that works well for the ggplot animation.

CC <- sub(".", "", colnames(EXTRACTION))

a <- data.frame(ticker=c("SPY"), values=EXTRACTION[c("SPY"),c(2)], frame=rep(CC[2],3))
#trying to extract the data of SPY on the right date.
b <- data.frame(ticker=c("SPY"), values=EXTRACTION[c("SPY"),c(3)], frame=rep(CC[3],3))
c <- data.frame(ticker=c("SPY"), values=EXTRACTION[c("SPY"),c(4)], frame=rep(CC[4],3))
.....so on
data<-rbind(a,b,c)

library(gifski)


myPlot <- ggplot(data, aes(x=ticker,y=values, fill = ticker))+geom_bar(stat='identity')+theme_bw()+
transition_states(frame, transition_length = 6, state_length = 2)+ ease_aes('sine-in-out')+
  labs(title = 'sector: {closest_state}')
                                                                                                      

animate(myPlot, duration = 5, fps = 20, width = 1000, height = 800, renderer = gifski_renderer())

so for the frame part, I have made a code CC in order to delete the first letter X in 'X2020.11.02'

Anyways, the code worked well but a user from stackoverflow told me once to "DON'T REPEAT YOURSELF" and the code seemed to be able to be looped. So I tried to make a code but it was too tough for me and did not work.

lapply(letters[1:3],function(x){x<-data.frame(ticker=c("SPY"),for(j in 2:4)
{values=EXTRACTION[c("SPY"),c(j)],frame=rep(CC[j],3))}})

what I was trying to do was list the alphabets a,b,c and cover them for function x. and in the same time with j in 2:4 , I wanted to match the a,b,c and 2,3,4.

So like

a<- .........,c(2).... rep(CC[2].....
b<- ........,c(3).... rep(CC[3].....
c<- .........,c(4).... rep(CC[4].....

How could I loop the codes? Thank you in advance.

The way you are using lapply is not correct. Take a look at the documentation for lapply

lapply returns a list of the same length as X, each element of which is the result of applying FUN to the corresponding element of X.

There are some confusions you are making using lapply and in the function you are declaring inside lapply .

But I think this is the kind of task that the functions in the tidyverse package are perfect for (rearranging your dataset in a different format).

So I think it is more useful to show you how to do it with tidyverse . Take a look at their tutorial. It will be very useful!

https://www.tidyverse.org/packages/

Using their functions you can accomplish what you want with few lines of code:

library(tidyverse)

data <- EXTRACTION %>%
  # convert to long format
  # this will take the data in all columns (except `TICKERS`) and "stack"" them vertically
  # it will also create another column with the dates where each data came from
  tidyr::pivot_longer(-TICKERS) %>%
  # fix names of dates (remove 'X') 
  dplyr::mutate(name=gsub('X', '', name, fixed = TRUE)) %>%
  # rename columns to match yours
  dplyr::rename(ticker=TICKERS, values=value, frame=name)


myPlot <- ggplot(data, aes(x=ticker,y=values, fill = ticker)) + 
  geom_bar(stat='identity')+theme_bw()+
  transition_states(frame, transition_length = 6, state_length = 2)+ ease_aes('sine-in-out')+
  labs(title = 'sector: {closest_state}')

The most important function I used here was tidyr::pivot_longer . Also, the %>% operator is a "pipe operator". It gets what is on the left side and uses as argument in the function on the right side. So, x %>% f(y) turns into f(x, y) so you can use it to rewrite multiple operations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM