Locking the axis labels to the top of the plot in R shiny

My giraffe rendering is very long, and I want the x-axis values to remain visible as the user scrolls down.

Below is a sample code that demonstrates this concept. I am open to different types of plots as long as they display the labels when hovering over each block. Any suggestions are welcome!

library(shiny)
library(tidyverse)
library(ggiraph)

ui <- fluidRow(girafeOutput("my_plot"))

server <- function(input, output){
  output$my_plot <- renderGirafe({
    
    data <- data.frame(
      letter = rep(c(LETTERS, letters, paste0(LETTERS, letters))),
      year = factor(rep_len(2000:2008, 78)),
      value = floor(runif(78, 1, 6))
    )
    
    g <- ggplot(data) + 
      geom_tile_interactive(aes(x = year, y = letter, fill = value, tooltip = value)) + 
      scale_x_discrete(position = "top") + 
      coord_fixed() +
      theme_classic() + 
      theme(axis.text.x = element_text(
        angle = 90,
        hjust = 0.5,
        vjust = 0,
        size = 17
      )) 
    
    girafe(ggobj = g,  
           options = list(opts_sizing(rescale = F)),
           width_svg = 20,
           height_svg = 50
    )
  })
}

shinyApp(ui = ui, server = server)

Answer №1

Experience the interactive power of plotly, where you can seamlessly scroll the y-axis while hovering over it, as shown in the image below:

https://i.sstatic.net/51D81WhH.png

It's important for users to be aware that there isn't a visible scroll bar on the y-axis (a "rangeslider" could have been helpful here, but unfortunately not available). Nevertheless, the desired result is still achieved.

library(shiny)
library(tidyverse)

ui <- fluidRow(
  plotlyOutput("my_plot")
)

server <- function(input, output){
  output$my_plot <- renderPlotly({
    
    data <- data.frame(
      letter = rep(c(LETTERS, letters, paste0(LETTERS, letters))),
      year = factor(rep_len(2000:2008, 78)),
      value = floor(runif(78, 1, 6))
    )

    g <- ggplot(data) + 
      geom_tile(aes(x = year, y = letter, fill = value), show.legend = F) + 
      scale_x_discrete(position = "top") + 
      coord_fixed() +
      theme_classic() + 
      theme(axis.text.x = element_text(
        angle = 90,
        hjust = 0.5,
        vjust = 0,
        size = 17
      )) 

    # adjust the height to your needs:
    ggplotly(g, height = 5000) %>% 
      layout(xaxis = list(side = "top"))

  })
}

shinyApp(ui = ui, server = server)

Answer №2

Exploring with giraffe:

library(tidyverse)
library(ggiraph)

library(shiny)


ui <- fluidRow(girafeOutput("my_plot"))

server <- function(input, output){
  output$my_plot <- renderGirafe({
    
    data <- data.frame(
      letter = rep(c(LETTERS, letters, paste0(LETTERS, letters))),
      year = factor(rep_len(2000:2008, 78)),
      value = floor(runif(78, 1, 6))
    )
    
    g <- ggplot(data) + 
      geom_tile_interactive(
        aes(x = year, y = letter, fill = value, 
            tooltip = purrr::map(paste0(
              "<b>my letter</b>: ", letter ,
              "<br><b>my value</b>: ", as.character(sprintf("%.3f",value)) ,
              "<br><b>my year</b>: ", as.character(year) 
            ), shiny::HTML)# htmltools::HTML 
        )
      ) + 
      scale_x_discrete(position = "top") + 
      coord_fixed() +
      theme_classic() + 
      theme(axis.text.x = element_text(
        angle = 90,
        hjust = 0.5,
        vjust = 0,
        size = 17
      )) 
    
    girafe(ggobj = g,  
           options = list(opts_sizing(rescale = F)),
           width_svg = 20,
           height_svg = 50
    )
  })
}

shinyApp(ui = ui, server = server)

Enhancing with ggplotly

(similar to julien.leroux5, but with customization):

  • Use text in aes instead of other variable names
  • In ggplotly, set tooltip= "text"
library(tidyverse)
library(ggiraph)
library(shiny)

library(plotly)


ui <- fluidRow(
  plotlyOutput("my_plot")
)

server <- function(input, output){
  output$my_plot <- renderPlotly({
    
    data <- data.frame(
      letter = rep(c(LETTERS, letters, paste0(LETTERS, letters))),
      year = factor(rep_len(2000:2008, 78)),
      value = floor(runif(78, 1, 6))
    )
    
    g <- ggplot(
      data,
      aes(
        text=purrr::map(paste0(
          "<b>my letter</b>: ", letter ,
          "<br><b>my value</b>: ", as.character(sprintf("%.3f",value)) ,
          "<br><b> my year</b>: ", as.character(year) 
        ), shiny::HTML)  # htmltools::HTML
      )
      
    ) + 
      geom_tile(aes(x = year, y = letter, fill = value), show.legend = F) + 
      scale_x_discrete(position = "top") + 
      coord_fixed() +
      theme_classic() + 
      theme(axis.text.x = element_text(
        angle = 90,
        hjust = 0.5,
        vjust = 0,
        size = 17
      )) 
    
    # adjust the height to your needs:
    ggplotly(g, 
             height = 5000,
             tooltip= "text"
    ) %>% 
      layout(xaxis = list(side = "top"))
    
  })
}

shinyApp(ui = ui, server = server)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for sorting the echarts line chart on a weekly basis using angular

How can I filter the echarts line chart by week in Angular? Currently, it displays all records like 2019-10-27 10:15:00, 2019-10-27 10:15:30, 2019-10-27 10:16:00, 2019-10-27 10:19:00. Instead, it should only show dates like 2019-10-27. For example, if ther ...

Create a new canvas for each iteration of a Vue.JS template loop

I'm having trouble figuring out how to initialize a local "signaturePad" canvas for each loop or required signature. Additionally, I am interested in binding "dataURL" to signaturePad.toDataURL("image/jpg"). This means displaying the dataURI for ever ...

On the same line, there are two divs with different characteristics - one dynamically changing width and the

I am facing an issue with arranging two divs under one parent div. The parent div is set to have a width of 100%: <div id="parent"> <div class="left"></div> <div class="right"></div> </div> The specific conditions ...

Sorry, but the data type error occurred with bn.fit() in R: the variable is not compatible with bnlearn (data type: integer)

After constructing a data frame of 100 instances for six binary variables (x1 to x6) based on a specific network structure, I stored the values in a variable called 'input_params'. To begin, I created an empty graph using the following code snipp ...

"Enhancing User Experience with Stylish Drop-down Menu Hover

I'm working on a CSS drop-down menu that has a hover effect, but I'm facing an issue where the a element within the li is not taking up the full width of the li. I want it to utilize the entire width of the li, especially on hover. Does anyone ha ...

Exploring Deeply Nested Routing in Angular

I've been exploring the use of multiple router outlets and encountered an issue. When using the navigateBy function of the router, I am unable to view my child route and encounter an error. However, when I access it via the routerLink in HTML, I get ...

The Malihu jQuery Custom Scrollbar integrated with Meteor is failing to display on the webpage

I have successfully integrated Malihu's custom scrollbar into my meteor app using this package: The code I'm using is as follows: Template.post.rendered = function() { $('body').mCustomScrollbar({ theme: 'minimal-dar ...

Unable to specify the element within the array

I'm having trouble getting my array elements defined. When I try to alert them, I always receive NaN. Even though the jQuery selectors seem to be working perfectly. Can someone help me figure out what the problem might be? var sldr ...

Implementing a universal (click) attribute for Angular 2 in CSS

When using Angular 1, it was as easy as following this syntax: [ngClick], [data-ng-click], [x-ng-click] { cursor: pointer; } This snippet ensured that any tags with the ng-click attribute displayed a pointer cursor. How can we achieve the same effect ...

Tips for Showing Certain Slides When the Page Loads

When using jQuery filter effects to organize div slides on a page, I encountered an issue where all the divs containing different slides are displayed on page load instead of just the default chosen ['active'] div. The filter effect itself is fun ...

Explore ways to showcase a list of calendars through the Google API with the use of Java Script

I'm experiencing difficulties with displaying a list of accessible calendars from Google Calendar using the Google API. I am utilizing JavaScript and AJAX to achieve this. What specific methods do I need to implement? I have only come across event-re ...

Implementing automatic vertical scrolling for dynamically added rows in a table's body

Check out this fiddle I created: https://jsfiddle.net/desytec/m69q2xwr/34/ <style> .table-scroll tbody { position: absolute; overflow-y: auto; height: 250px; } </style> <script> var count = 0; $(document).ready(function () ...

What is the reason behind the change in style hierarchy when using ':last-child'?

I found myself in a confusing situation where using :last-child is affecting how parent classes are being applied. The task at hand is to style the last element in a list of elements. However, upon using :last-child, the priority of styles shifts and one ...

Creating a dynamic table in AngularJS with rotating values for rows and columns

I am seeking assistance in creating a table with a custom number of rows and columns. The table should have two input fields for specifying the number of rows and columns, and upon submission, the table should dynamically adjust to display the specified nu ...

Guide to transmitting and managing a JSON document utilizing JavaScript

When working on the server side, I receive a simple JSON file via REST that contains various IDs. Here is an example: [ { "_id": "5825a49dasdasdasd8417c1b6d5", } "_id": "dfsdfsdf4960932218417c1b6d5", } "_id": "23434344960932218417c1b6d5", },] To handle t ...

Utilizing the "return" keyword in Javascript outside of function declarations

Exploring the Impact of Using the Return Keyword in JavaScript Scripts Beyond Functions in Browsers and Node.js Recently, I experimented with utilizing the return keyword in a Node.js script like so: #!/usr/bin/env node return 10; My initial assumption ...

The background image does not appear on the animated div until the browser window is resized

Encountering an unusual problem - I have styled a div element using CSS to be initially hidden: .thediv { width: 100%; height: 87%; position: fixed; overflow: hidden; background-image: url(pics/FrameWithBG1280.png); background-attachment: fixe ...

What steps should I take to transform [“link”, “395868”] into [title: “link”, content: “395868”]?

As a newcomer to javascript, I am finding it challenging to articulate my issue due to lack of adequate vocabulary. My current project involves building a chart with d3 and here is the data I require : data=[ ...

Wrapping an anchor tag with a div in Codeigniter

Can a div tag be used inside an anchor function? I have a div with the following CSS: #first{ opacity:0; } Now, I want to include it in my anchor element. Here is the code snippet: <?php if(is_array($databuku)){ echo '<ol>&l ...

Enhancing ChoicePrompt with ListStyle.heroCard: Adding Personalized Data

I have developed a custom ChoicePrompt with the unique style of ListStyle.heroCard: import {ChoicePrompt, ListStyle} from 'botbuilder-dialogs'; import {PromptValidator} from 'botbuilder-dialogs/src/prompts/prompt'; import {FoundChoice} ...