Use data.table package in shiny app - r

I want to use the data.table package in a Shiny App to improve speed.
However, it's not clear to me how to select the right columns based on the user input.
The following example works for the case when the data is in the data.frame format but not when it is in data.table format.
# load packages
library(data.table)
# global ----------------------------------------
library(shiny)
# use cars dataset
data(cars)
# create datatable from cars data
cars <- as.data.table(cars)
# user interface ---------------------------------
ui <- fluidPage(
sidebarLayout(
selectInput(inputId = 'col', label = 'column', choices = names(cars)),
numericInput(inputId = 'filter',label = 'filter', value = 5)
),
mainPanel(plotOutput("plot"))
)
# server ----------------------------------------
server <- function(input, output) {
output$plot <- renderPlot({
# filter example
d1 <- cars[speed>input$filter,]
x <- d1[[input$col]]
hist(x)
})
}
# run app --------------------------------------
shinyApp(ui = ui, server = server)

Related

Shiny rhandsontable automatic values depending on User

I have a table, in which the user will give as input some groups. As a result, I want another column to automatically update and show the frequency (or replicate) of each group:
This code creates this app:
library(shiny)
library(rhandsontable)
library(tidyverse)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Automatic data rhandsontable"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
),
# Show a plot of the generated distribution
mainPanel(
rhandsontable::rHandsontableOutput('ed_out'),
shiny::actionButton('start_input', 'save final table')
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
# This has to be reactive
data <- reactive({
df <- data.frame(Animal = c('Dog', 'Cat', 'Mouse', 'Elephant', 'Tiger'),
Group = ' ',
replicate = as.numeric(' '))
})
output$ed_out <- rhandsontable::renderRHandsontable({
df <- data()
rhandsontable(
df,
height = 500,
width = 600) %>%
hot_col('replicate', format = '0a', readOnly = TRUE) %>%
hot_col('Animal', readOnly = TRUE)
})
# This is just to save the table when the user has finished, can be ignored
group_finals <- reactiveValues()
observeEvent(input$start_input, {
group_finals$data <- rhandsontable::hot_to_r(input$ed_out)
print(group_finals$data)
}
)
}
# Run the application
shinyApp(ui = ui, server = server)
So the idea is that the user, inputs the groups and the replicate is automatically updated: (here the user gives as input B, B, A, A, B.
I am able to count the replicates of each group, but I'm not sure how where to implement this part to calculate them and display them at the same time after the user inputs each group.
df <- df %>%
group_by(Group) %>%
mutate(replicate = 1:n())
Not sure if this is the best approach, I tried a bit with the hot_to_col renderer to use javascript but I'm unfamiliar with that language.
Sorry but I'm not familiar with the tidyverse - so I switched to data.table.
hot_to_r is the right way to go:
library(shiny)
library(rhandsontable)
library(data.table)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Automatic data rhandsontable"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
),
# Show a plot of the generated distribution
mainPanel(
rhandsontable::rHandsontableOutput('ed_out'),
shiny::actionButton('start_input', 'save final table')
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
# This has to be reactive
data <- reactive({
data.frame(Animal = c('Dog', 'Cat', 'Mouse', 'Elephant', 'Tiger'),
Group = '',
replicate = NA_integer_)
})
myData <- reactiveVal()
observeEvent(data(),{
myData(data())
})
output$ed_out <- rhandsontable::renderRHandsontable({
rhandsontable(
myData(),
height = 500,
width = 600) %>%
hot_col('replicate', format = '0a', readOnly = TRUE) %>%
hot_col('Animal', readOnly = TRUE)
})
observeEvent(input$ed_out, {
userDT <- rhandsontable::hot_to_r(input$ed_out)
setDT(userDT)
userDT[, replicate := seq_len(.N), by = Group][is.na(Group) | Group == "", replicate := NA_integer_]
myData(userDT)
})
# This is just to save the table when the user has finished, can be ignored
group_finals <- reactiveValues()
observeEvent(input$start_input, {
group_finals$myData <- rhandsontable::hot_to_r(input$ed_out)
print(group_finals$myData)
})
}
# Run the application
shinyApp(ui = ui, server = server)

Get rownames of a reactive data frame in R shiny and create a date range slider

I have a dataframe with a time series as index. The data in the data frame are updated by a dashboard action (e.g. a download button) and therefore the dataframe is reactive. With a slider I want to be able to select only certain rows of the dataframe. The min max values of the slider therefore refer to the rownames of the reactive data frame. So far I am not able to get this implemented. Below the code. The if(0) part in the SERVER section is the one I am talking about. Any help appreciated.
require(shiny)
AquireData <- function(){
# In this function the data are created
df <- data.frame(replicate(3,sample(0:50,1000,rep=TRUE)))
rownames(df) <- seq(from = as.POSIXct("2012-05-15 07:00"),
to = as.POSIXct("2019-05-17 18:00"), by = "min")[0:dim(df)[1]]
names(df) <- c('A','B','C')
return (df)
}
ui <- fluidPage(
# App title
titlePanel("my dashboard"),
# define stuff for the sidebar (buttons, selectlists etc.). These items will
# be displayed for all panels
sidebarLayout(
sidebarPanel(
actionButton("Button_GetAndUpdate", "Update data"),
sliderInput("start_end_dates", "Date range", min =0, max=0, value=1)
),
# Main panel. Here you can display your graphs, plots and tables
mainPanel("observed data", tableOutput("rawdata"))
)
)
server <- function(input, output,session) {
# When the app is called an update of the data is drawn
df_data <- reactive({AquireData()})
# Check what the update button is doing. If its getting pressed pull and update
observeEvent (input$Button_GetAndUpdate,{df_data <<- reactive({AquireData()})})
# set date range slider values using the dates from the data frame index
if(0){
updateSliderInput(session, "start_end_dates",
label = "Date range",
min = as.POSIXct(min(rownames(df_data())),"%Y-%m-%d %H:%M:%S",tz=""),
max = as.POSIXct(max(rownames(df_data())),"%Y-%m-%d %H:%M:%S",tz="")
)
}
# get the head of the dataframe
data_head <- reactive({
input$Button_GetAndUpdate
isolate({
head(df_data())
})
})
output$rawdata <- renderTable({
data_head()
})
}
shinyApp(ui = ui, server = server)
runApp("Header_dashboard")
You could use shinyWidgets::sliderTextInput and shinyWidgets::updateSliderTextInput respectively instead of sliderInputfor this:
shinyWidgets::updateSliderTextInput(
session, "start_end_dates",
choices = rownames(df_data())
)
That means for your app:
require(shiny)
AquireData <- function(){
# In this function the data are created
df <- data.frame(replicate(3,sample(0:50,1000,rep=TRUE)))
rownames(df) <- seq(from = as.POSIXct("2012-05-15 07:00"),
to = as.POSIXct("2019-05-17 18:00"), by = "min")[0:dim(df)[1]]
names(df) <- c('A','B','C')
return (df)
}
ui <- fluidPage(
# App title
titlePanel("my dashboard"),
# define stuff for the sidebar (buttons, selectlists etc.). These items will
# be displayed for all panels
sidebarLayout(
sidebarPanel(
actionButton("Button_GetAndUpdate", "Update data"),
shinyWidgets::sliderTextInput(
"start_end_dates",
label = "Time range",
choices = c(as.POSIXct("2019-01-01 12:00:00"), as.POSIXct("2019-12-31 14:00:00")),
)
),
# Main panel. Here you can display your graphs, plots and tables
mainPanel("observed data", tableOutput("rawdata"))
)
)
server <- function(input, output,session) {
# When the app is called an update of the data is drawn
df_data <- reactive({AquireData()})
# Check what the update button is doing. If its getting pressed pull and update
observeEvent (input$Button_GetAndUpdate,{df_data <<- reactive({AquireData()})})
# set date range slider values using the dates from the data frame index
observe({
shinyWidgets::updateSliderTextInput(
session, "start_end_dates",
choices = rownames(df_data())
)
})
# get the head of the dataframe
data_head <- reactive({
input$Button_GetAndUpdate
isolate({
head(df_data())
})
})
output$rawdata <- renderTable({
data_head()
})
}
shinyApp(ui = ui, server = server)

Dynamically display column names in shiny app flashes error when dataset is changed

I have a shiny app where I want to allow the user to select a dataset based on a set of uploaded files and then specify the columns to display from the selected dataset. If I leave some columns selected and then switch datasets, an error flashes and is output to the console stating that the selected columns are unknown before the app switches datasets and displays it correctly. In my full app however, the app crashes, though I wasn't able to figure out how to reproduce the crash. I thought it might be related to some preprocessing that is done to add additional columns which are the same across datasets and which remain selected, but the error is the same without that feature.
library(shiny)
library(tidyverse)
library(DT)
ui <- fluidPage(
checkboxGroupInput("select_var", label = "Select Variables"),
selectInput("dataset", label = NULL, choices = c("mtcars", "rock")),
DT::dataTableOutput("table")
)
server <- function(session, input, output) {
# define the dataset
data <- reactive({switch(input$dataset,"rock" = rock,"mtcars" = mtcars)})
# add a common column name that is always selected
dataprocessed <- reactive({data <- data()
data$num <- seq(1:nrow(data))
return(data)})
# dynamically generate the variable names
observe({
vchoices <- names(dataprocessed())
updateCheckboxGroupInput(session, "select_var", choices = vchoices, selected = c("num"))
})
# select the variables based on checkbox
data_sel <- reactive({
req(input$select_var)
df_sel <- dataprocessed() %>% select(input$select_var)
})
output$table <- DT::renderDataTable(data_sel())
}
# Run the application
shinyApp(ui = ui, server = server)
We can add a conditional requirement using req() to test for column existence before rendering:
library(shiny)
library(tidyverse)
library(DT)
ui <- fluidPage(
checkboxGroupInput("select_var", label = "Select Variables"),
selectInput("dataset", label = NULL, choices = c("mtcars", "rock")),
DT::dataTableOutput("table")
)
server <- function(session, input, output) {
# define the dataset
data <- reactive({
switch(input$dataset,"rock" = rock,"mtcars" = mtcars)
})
# add a common column name that is always selected
dataprocessed <- reactive({
data <- data()
data$num <- seq(1:nrow(data))
return(data)
})
# dynamically generate the variable names
observe({
vchoices <- names(dataprocessed())
updateCheckboxGroupInput(session, "select_var", choices = vchoices, selected = c("num"))
})
# select the variables based on checkbox
data_sel <- reactive({
req(input$select_var)
req(names(dataprocessed()) %in% input$select_var)
a <- names(dataprocessed())[names(dataprocessed()) %in% input$select_var]
df_sel <- dataprocessed() %>% select(a)
})
output$table <- DT::renderDataTable(data_sel())
}
# Run the application
shinyApp(ui = ui, server = server)

Shiny DT Highlight Cells if Value Appears in Another Set

Issue:
I have a data frame where row A is the names of people in my organization. I have a separate data frame that is a subset of row A in the original table. I would like to highlight all rows in the first data table that match names in the second table. Essentially, I have two sets. Set A and Set B. Both are names, I would like to highlight the data table for all names in Set A that match Set B. However, I keep getting an error: length(levels) must be equal to length(values)
How would I avoid receiving this error?
Reproducible Example:
I have a data frame of mtcars. I am filtering the mtcars dataset based on a slider input for mpg. I would like to highlight the data frame of mtcars that meet the filtering criteria. In effect, this would mean highlighting the output table for all observations where the mpg are <= the slider input mpg.
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Highlight Cell Test (Sets)"),
sidebarLayout(
sidebarPanel = 'side',
sliderInput('slider', 'slider input', 1, 30, 20)),
# Show a plot of the generated distribution
mainPanel(
dataTableOutput("test")
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
subset <- reactive({
mtcars %>%
filter(mpg <= input$slider)
})
output$test <- DT::renderDataTable(
mtcars %>%
DT::datatable(
options = list(
dom = 'ftipr',
searching = TRUE
) %>%
formatStyle(
'test',
background = styleEqual(
(subset()$mpg %in% mtcars$mpg), 'lightgreen'))
)
)
}
# Run the application
shinyApp(ui = ui, server = server)
Any help is much appreciated. Thanks in advance.
You can do this via rowCallback like so:
library(shiny)
library(dplyr)
library(DT)
fnc <- JS('function(row, data, index, rowId) {','console.log(rowId)','if(rowId >= ONE && rowId < TWO) {','row.style.backgroundColor = "lightgreen";','}','}')
ui <- fluidPage(
# Application title
titlePanel("Highlight Cell Test (Sets)"),
sidebarLayout(
sidebarPanel = 'side',
sliderInput('slider', 'slider input', 1, 30, 16)),
# Show a plot of the generated distribution
mainPanel(
dataTableOutput("test")
)
)
# Define server logic required to draw a histogram
server <- function(input, output, session) {
subset <- reactive({
mtcars %>% filter(mpg <= input$slider)
})
Coloring <- eventReactive(subset(),{
a <- which(subset()$mpg %in% mtcars$mpg)
print(a)
if(length(a) <= 0){
return()
}
fnc <- sub("ONE",a[1],fnc)
fnc <- sub("TWO",max(a),fnc)
fnc
})
output$test <- DT::renderDataTable(
mtcars %>%
DT::datatable(options = list(dom = 'ftipr',searching = TRUE,pageLength = 20, scrollY = "400px",rowCallback = Coloring()))
)
}
shinyApp(ui = ui, server = server)

R shiny: Display data set in shiny app

I am trying to print dataset values in shiny web app. But I am only able to print data set name using below code. How can I print dataset values?
library(MASS)
library(shinythemes)
library(shiny)
library(ggplot2)
mass.tmp <- data(package = "MASS")[3]
mass.datasets <- as.vector(mass.tmp$results[,3])
ui <- fluidPage(
theme = shinytheme("superhero"),
titlePanel("Linear Regression Modelling"),
sidebarLayout(
sidebarPanel(
selectInput("dsname", "Dataset:",choices = c(mass.datasets))
,
uiOutput("x_axis")
# ,
# textOutput("txt"),
# tableOutput("tab")
),
mainPanel(
tags$br(),
tags$br()
)
)
)
server <- function(input, output) {
num_ds <- function(ds)
{
nums <- sapply(ds,is.numeric)
num_ds <- ds[,nums]
return(num_ds)
}
ds_ext <- reactive({ num_ds(input$dsname) })
output$x_axis <- renderUI({
col_opts <- get(ds_ext())
selectInput("x_axis2", "Independent Variable:", choices = names(col_opts))
})
}
shinyApp(ui = ui, server = server)
Actually I am trying to solve error in above code "Incorrect number of dimensions". I have written function which would return data frame with only numeric variables so that I can analyze. But getting error in line I guess where I am creating object x_axis. pls help.

Resources