Plotly animation in shiny. Text does not stay in centre of yaxis. Error message: non-numeric argument to binary operator. How to convert to numeric?

Question:
I am trying to keep the text in my plotly animation in shiny in the centre of the yaxis.
I get the following error message: non-numeric argument to binary operator.
How do I convert Die_1 into numeric? I have used: mutate(frame = as.numeric(frame))

The data:

dput(LifeExpCH$Age)
c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 
66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 
82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 
98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 
111)
> dput(LifeExpCH$Die)
c(380, 16, 11, 9, 9, 8, 7, 7, 7, 8, 7, 7, 8, 8, 8, 10, 11, 13, 
16, 19, 20, 20, 21, 20, 19, 21, 20, 21, 23, 24, 25, 27, 30, 31, 
35, 37, 41, 44, 48, 52, 57, 63, 70, 76, 84, 94, 104, 115, 129, 
143, 159, 176, 195, 215, 237, 258, 283, 307, 334, 363, 392, 424, 
458, 495, 534, 578, 624, 677, 734, 798, 869, 952, 1044, 1149, 
1271, 1411, 1569, 1750, 1955, 2184, 2440, 2723, 3032, 3363, 3711, 
4064, 4404, 4710, 4952, 5106, 5143, 5041, 4795, 4408, 3908, 3342, 
2753, 2190, 1679, 1243, 888, 612, 406, 259, 158, 93, 51, 27, 
13, 5, 2, 1)

> dput(LifeExpCH_M$Age)
c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 
66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 
82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 
98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110
)
>dput(LifeExpCH_M$Die)
c(413, 16, 13, 11, 11, 9, 9, 8, 7, 8, 8, 8, 10, 11, 15, 18, 26, 
33, 43, 51, 55, 57, 54, 51, 50, 48, 48, 49, 49, 51, 52, 55, 57, 
61, 65, 69, 73, 79, 85, 92, 100, 108, 118, 130, 141, 156, 172, 
190, 209, 231, 256, 282, 312, 345, 379, 418, 458, 503, 551, 601, 
656, 715, 776, 842, 911, 985, 1063, 1147, 1237, 1335, 1441, 1557, 
1687, 1828, 1987, 2162, 2352, 2558, 2776, 3005, 3239, 3472, 3698, 
3903, 4079, 4213, 4290, 4298, 4227, 4072, 3831, 3513, 3129, 2702, 
2256, 1820, 1415, 1059, 763, 528, 351, 224, 137, 80, 45, 24, 
13, 6, 3, 1, 1)

The code:


library(shiny)
library(shinydashboard)
library(readxl)
library(plotly)
library(purrr)
library(dplyr)


LifeExpCH <- read_excel("LifeExpCH.xlsx") 
LifeExpCH_M <- read_excel("LifeExpCH_M.xlsx") 



Die <- function(Gender, Age) {
  if(Gender == 0){
    
    Die_1 <- cumsum(LifeExpCH$Die[1:111])
    Die_1 <- Die_1[(Age + 1) : length(Die_1)]
    Age   <- LifeExpCH$Age[(Age + 1):111]
    df2   <- data.frame(Age, Die_1)
    
    
  } else {
    
    Die_1 <- cumsum(LifeExpCH_M$Die)
    Die_1 <- Die_1[(Age + 1) : length(Die_1)]
    Age   <- LifeExpCH_M$Age[(Age + 1):111]
    df2   <- data.frame(Age, Die_1)
    
    
  } 
}




header <- dashboardHeader()


sidebar <- dashboardSidebar(
  
  selectInput("Gender", "Please select gender:", c("Female" = 0, "Male" = 1)),
  sliderInput("Age", "Please select age:", value = 0, min = 0, max = 100)
  
)

body <- dashboardBody(
  
  fluidRow(
    
    box(width = 6, plotlyOutput(outputId = "DI"))
    
  )
)


ui <- dashboardPage(skin = "black",
                    header = header,
                    sidebar = sidebar,
                    body = body)


server <- function(input, output){
  
  DieN <- reactive({
    Die(input$Gender, input$Age)
  })
  
  output$DI <- renderPlotly({
    
    DieN() %>% split(.$Age) %>% accumulate(~bind_rows(.x, .y)) %>%
      set_names(input$Age:110) %>%
      bind_rows(.id = "frame") %>%

#mutate(frame = as.numeric(frame)) => should convert into numeric?
      mutate(frame = as.numeric(frame)) %>% 
      plot_ly(x = ~Age, y = ~Die_1) %>%
      
      add_lines(frame = ~frame, showlegend = FALSE) %>%


#Here I am trying to keep the text in the centre of the yaxis. 
#I get the following error message: non-numeric argument to binary operator. 
#How do I convert Die_1 #into numeric?
      
      add_text(x = ((111 + input$Age)/2), y= (~Die_1[1] + 100000)/2, text = ~Die_1, frame = ~Age,
               textfont = list(size = 50, color = toRGB("steelblue")) ) %>%
      


      animation_opts(frame = 300) %>%
      animation_slider(hide = TRUE)
    
    
  })
  
  
  
}



shinyApp(ui = ui, server = server)

This is probably character and not numeric

Sorry, don't understand your answer. Are you referring to the xaxis or the yaxis? xaxis works, just yaxis is not working as I would like to. Is there an alternative solution to keeping the text in the middle of the yaxis?

add_text(x = ((111 + input$Age)/2), y= (~Die_1[1] + 100000)/2, text = ~Die_1, frame = ~Age,
               textfont = list(size = 50, color = toRGB("steelblue")) )

This is of class character even if the values are digits, so you have to convert it to numeric.

as.numeric(input$Age)

Hi Andre,
turns out input$Age is numeric, so its a misdirection haha.
There is some issue relating to

~Die_1[1]

I'm wondering if the formula is simply failing to evaluate properly. Eitherway, documentation/examples on how to combine animations with changing add_text is scant when I google around, so I'm going to sit this one out.

Hi @Martin123. The error caused by the y argument. The formula is not correct. You can change it to (~Die_1/2 + 50000).

LifeExpCH <- data.frame(Age = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 
                                18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 
                                34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 
                                50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 
                                66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 
                                82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 
                                98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 
                                111),
                        Die = c(380, 16, 11, 9, 9, 8, 7, 7, 7, 8, 7, 7, 8, 8, 8, 10, 11, 13, 
                                16, 19, 20, 20, 21, 20, 19, 21, 20, 21, 23, 24, 25, 27, 30, 31, 
                                35, 37, 41, 44, 48, 52, 57, 63, 70, 76, 84, 94, 104, 115, 129, 
                                143, 159, 176, 195, 215, 237, 258, 283, 307, 334, 363, 392, 424, 
                                458, 495, 534, 578, 624, 677, 734, 798, 869, 952, 1044, 1149, 
                                1271, 1411, 1569, 1750, 1955, 2184, 2440, 2723, 3032, 3363, 3711, 
                                4064, 4404, 4710, 4952, 5106, 5143, 5041, 4795, 4408, 3908, 3342, 
                                2753, 2190, 1679, 1243, 888, 612, 406, 259, 158, 93, 51, 27, 
                                13, 5, 2, 1))

LifeExpCH_M <- data.frame(Age = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 
                                  18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 
                                  34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 
                                  50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 
                                  66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 
                                  82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 
                                  98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110),
                          Die = c(413, 16, 13, 11, 11, 9, 9, 8, 7, 8, 8, 8, 10, 11, 15, 18, 26, 
                                  33, 43, 51, 55, 57, 54, 51, 50, 48, 48, 49, 49, 51, 52, 55, 57, 
                                  61, 65, 69, 73, 79, 85, 92, 100, 108, 118, 130, 141, 156, 172, 
                                  190, 209, 231, 256, 282, 312, 345, 379, 418, 458, 503, 551, 601, 
                                  656, 715, 776, 842, 911, 985, 1063, 1147, 1237, 1335, 1441, 1557, 
                                  1687, 1828, 1987, 2162, 2352, 2558, 2776, 3005, 3239, 3472, 3698, 
                                  3903, 4079, 4213, 4290, 4298, 4227, 4072, 3831, 3513, 3129, 2702, 
                                  2256, 1820, 1415, 1059, 763, 528, 351, 224, 137, 80, 45, 24, 
                                  13, 6, 3, 1, 1))

library(shiny)
library(shinydashboard)
library(readxl)
library(plotly)
library(purrr)
library(dplyr)


Die <- function(Gender, Age) {
  if(Gender == 0){
    
    Die_1 <- cumsum(LifeExpCH$Die[1:111])
    Die_1 <- Die_1[(Age + 1) : length(Die_1)]
    Age   <- LifeExpCH$Age[(Age + 1):111]
    df2   <- data.frame(Age, Die_1)
    
    
  } else {
    
    Die_1 <- cumsum(LifeExpCH_M$Die)
    Die_1 <- Die_1[(Age + 1) : length(Die_1)]
    Age   <- LifeExpCH_M$Age[(Age + 1):111]
    df2   <- data.frame(Age, Die_1)
    
    
  } 
}




header <- dashboardHeader()


sidebar <- dashboardSidebar(
  
  selectInput("Gender", "Please select gender:", c("Female" = 0, "Male" = 1)),
  sliderInput("Age", "Please select age:", value = 0, min = 0, max = 100)
  
)

body <- dashboardBody(
  
  fluidRow(
    
    box(width = 6, plotlyOutput(outputId = "DI"))
    
  )
)


ui <- dashboardPage(skin = "black",
                    header = header,
                    sidebar = sidebar,
                    body = body)


server <- function(input, output){
  
  DieN <- reactive({
    Die(input$Gender, input$Age)
  })
  
  output$DI <- renderPlotly({
    
    
    
    DieN() %>% split(.$Age) %>% accumulate(~bind_rows(.x, .y)) %>%
      set_names(input$Age:110) %>%
      bind_rows(.id = "frame") %>%
      
      #mutate(frame = as.numeric(frame)) => should convert into numeric?
      mutate(frame = as.numeric(frame)) %>% 
      plot_ly(x = ~Age, y = ~Die_1) %>%
      
      add_lines(frame = ~frame, showlegend = FALSE) %>%
      
      
      #Here I am trying to keep the text in the centre of the yaxis. 
      #I get the following error message: non-numeric argument to binary operator. 
      #How do I convert Die_1 #into numeric?
      
      # add_text(x = ((111 + input$Age)/2), y= (~Die_1[1] + 100000)/2, text = ~Die_1, frame = ~Age,
      #          textfont = list(size = 50, color = toRGB("steelblue")) )
      
      add_text(x = ((111 + input$Age)/2), y= (~Die_1/2 + 50000), text = ~Die_1, frame = ~Age,
               textfont = list(size = 50, color = toRGB("steelblue"))) %>%
      
      
      
      animation_opts(frame = 300) %>%
      animation_slider(hide = TRUE)
    
    
  })
  
  
  
}



shinyApp(ui = ui, server = server)
1 Like

Hi Raytong,

Sorry, but your suggestion did not work. As soon as I start the animation the
text moves and does not stay centered.

Kind regards

I solved the issue by writing a new reactive function. And using output as input into the plotly animation.

@Martin123. Sorry that I didn't check the animate to the end and the text going up. I am glad that you got the solution. But I still want to provide my solution for your reference. :grin:

add_text(x = ((111 + input$Age)/2), y= sum(range(DieN()$Die_1))/2, text = ~Die_1, frame = ~Age,
               textfont = list(size = 50, color = toRGB("steelblue")))

Hi Raytong, no worries, thank you for your solution. It is simpler and thus better (more elegant) than mine. I will use yours. Kind regards

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