Accessing RXSpreadsheet data for further manipulation? - shiny

I am making a Shiny app that should have an empty spreadsheet (like excel), where I can paste some data, which can be further processed to get some desired output.
How can I access the data from the spreadsheet for further manipulation in my app?
In the code below, I successfully load an empty spreadsheet that is editable, I can also paste whatever I want into it, but I don't know how to manipulate the data further. I tried to at least load it like a DT table just to see if I managed to convert it to data.frame.
library(shiny)
library(RXSpreadsheet)
ui <- fluidPage(
tabsetPanel(
tabPanel(
"Spreadsheet",
RXSpreadsheet("table"),
RXSpreadsheetOutput("spreadsheet")
),
tabPanel(
"Tabela",
DT::dataTableOutput("dataframe")
)
)
)
server <- function(input, output) {
data <- reactive({
input$table
})
output$spreadsheet <- renderRXSpreadsheet({
data()
})
data_2 <- reactive({
as.data.frame(data())
})
output$dataframe <- DT::renderDT({
data_2()
})
}
shinyApp(ui, server)

Related

R shiny: Updating mulitple areas of the interface with single renderUI

I am creating a shiny dashboard. I have a single selectInput that will update multiple places in the UI. Currently I am having to us multiple renderUI functions to do this. I was wondering whether there was a way to only use 1. For example I have this:
output$fig_con_1 <- renderUI({
commodity_impact_graph(l_impact_val)
})
output$tab1 <- renderUI({
includeHTML(wetland_path)
})
output$tab2 <- renderUI({
includeHTML(river_path)
})
I wish to achieve something akin to this:
output[all areas of the UI] <- renderUI({
commodity_impact_graph(l_impact_val)
includeHTML(wetland_path)
includeHTML(river_path)
})
Try this
output$all <- renderUI({
tagList(
commodity_impact_graph(l_impact_val)
includeHTML(wetland_path)
includeHTML(river_path)
)
})

isolate input in a module shiny when using insert ui

I'd like to create several ui which use an input parameter. The problem is that the new UI created are still reacting to the input even when I put an isolate()
The right behaviour would give a custom UI created and isolated from the new inputs coming from the selectInput()
For instance I'd like a first UI with the year 2019 selected and second UI with the year 2020.
Here we can see that adding 2020 will change in each UI which is wrong.
library(shiny)
customplotUI <- function(id){
ns <- NS(id)
fluidPage(
sidebarPanel(id=ns("sidebarpanel"),
actionButton(ns("add"),label = "Add"),
selectInput(inputId=ns("years"),label="Year :", choices = c(2019,2020),selected = 2019, multiple = TRUE)),
mainPanel(div(id=ns("placeholder"))
)
)
}
customplot <- function(input,output,session){
ns <- session$ns
output$res <- renderPrint({
data <- data.frame(year=c(2019,2020),value=c("mtcars2019","mtcars2020"))
data[data$year %in% input$years,]})
ctn <- reactiveVal(0)
Id <- reactive({
function(id){
paste0(id, ctn())
}
})
IdNS <- reactive({
function(id){
ns(paste0(id, ctn()))
}
})
observeEvent(input$add, {
ctn(ctn() + 1)
print(Id()('div'))
insertUI(
selector = paste0('#', ns('placeholder')),
ui = div(
id = Id()('div'),
verbatimTextOutput(IdNS()('chart'))
)
)
id <- Id()('chart')
output[[id]] <- renderPrint({
data <- data.frame(year=c(2019,2020),value=c("mtcars2019","mtcars2020"))
#data[data$year %in% isolate(input$years),]
data[data$year %in% input$years,]
})
})
}
ui <- fluidPage(
customplotUI(id="customplot")
)
server <- function(input, output, session){
callModule(customplot,id="customplot",session=session)
}
shinyApp(ui, server)
Perhaps I'm misunderstanding what you're trying to accomplish, but when I run the code, using the commented line with isolate seems to work as intended.
I'm guessing that in creating the minimal reprex (thank you for doing this btw!), you might have gone a little too minimal and removed another reactive that updates data. If you are trying to have the individual UI elements update based on some other input but keep the same filtering scheme, you need to capture the current value of input$years outside of the renderPrint statement.
Here you can see the subset of rows is unchanged, but the last column updates based on input box:
...
id <- Id()('chart')
targetYears <- input$years
output[[id]] <- renderPrint({
data <- data.frame(year=c(2019,2020),
value=c("mtcars2019","mtcars2020"),
yrInput = paste(input$years, collapse =" "))
data[data$year %in% targetYears, ]
...
isolate only prevents a change in the reactive from triggering an update. If the update is triggered by something else, the current/updated value of the reactive is still used. Through the wonders of R's scoping rules, by capturing the value of input$years in non-reactive variable, targetYears, outside of the renderPrint call and then using that in the renderPrint expression it will always use the the value of the input when output[[id]] was created. The isolate is not needed as you are using observeEvent which will prevent the observer from executing when you change the input.

I want to filter my data using the reactive function in Shiny. But I am not getting any output

I am trying filter my data using the dplyr package inside the reactive function in Shiny, but nothing is being displayed in the output. The data is supposed to be filtered by levels of the variable "Country".
Here is the code I have used and the dataframe
datos<-data.frame(time=c(rep(c(2001, 2002),3)), values=c(100,200,300,600,700,800), country=c(rep("Uruguay",2),rep("France",2),rep("United States",2)))
ui <- fluidPage(
selectInput(inputId ="pais", label="Choose a country",
choices =levels(datos$country), selected = "Uruguay"),
plotOutput(outputId ="barplot")
)
server <- function(input, output) {
datos3 <- reactive({
datos%>%
filter(country=="input$pais")
})
output$barplot<-renderPlot({
ggplot(datos3(),aes(x=time,y=values))+geom_bar(stat="Identity")
})
}
shinyApp(ui = ui, server = server)
I am supposed to obtain the values for the selected country, by time period.
You didn't need the quotation marks on "input$pais".
Here is the code with that and the extra + in the ggplot section removed.
library(shiny)
library(tidyverse)
datos<-data.frame(time=c(rep(c(2001, 2002),3)), values=c(100,200,300,600,700,800), country=c(rep("Uruguay",2),rep("France",2),rep("United States",2)))
ui <- fluidPage(
selectInput(inputId ="pais", label="Choose a country",
choices =levels(datos$country), selected = "Uruguay"),
plotOutput(outputId ="barplot")
)
server <- function(input, output) {
datos3 <- reactive({
datos%>%
filter(country==input$pais) #this bit has been changed
})
output$barplot<-renderPlot({
ggplot(datos3(),aes(x=time,y=values))+geom_bar(stat="Identity")
})
}
shinyApp(ui = ui, server = server)

Selecting rows from a DT table using Crosstalk in Shiny

I confess, I did post this question over on RStudio three days ago but it has not had enough love yet, so I'm trying again here. I hope that's okay. The original question is here (the text is the same in both, I'm just being transparent). https://community.rstudio.com/t/selecting-rows-from-a-dt-table-using-crosstalk-in-shiny/4079
So I would like to brush across points in D3Scatter and use it to filter the rows of a datatable produced using the DT package with crosstalk.
Just like this, which totally works outside of shiny:
library(crosstalk)
library(d3scatter)
library(DT)
shared_iris <- SharedData$new(iris)
bscols(d3scatter(shared_iris, ~Petal.Length, ~Petal.Width, ~Species, width = "100%",
x_lim = range(iris$Petal.Length), y_lim = range(iris$Petal.Width)),
datatable(shared_iris))
But when I put it in Shiny, I can select points on the scatter from the table, but not vice versa:
library(shiny)
library(crosstalk)
library(d3scatter)
library(DT)
ui <- fluidPage(
fluidRow(
column(6, d3scatterOutput("scatter1")),
column(6, DT::dataTableOutput("scatter2"))
)
)
server <- function(input, output, session) {
jittered_iris <- reactive({
iris
})
shared_iris <- SharedData$new(jittered_iris)
output$scatter1 <- renderD3scatter({
d3scatter(shared_iris, ~Petal.Length, ~Petal.Width, ~Species, width = "100%",
x_lim = range(iris$Petal.Length), y_lim = range(iris$Petal.Width))
})
output$scatter2 <- DT::renderDataTable({
datatable(shared_iris)
})
}
shinyApp(ui, server)
They’ve got it working here: https://rstudio-pubs-static.s3.amazonaws.com/215948_95c1ab86ad334d2f82856d9e5ebc16af.html
I’m at a loss. I feel like I’ve tried everything. Any clues anyone?
Thanks,
Crosstalk integration in DT only works with client-side processing . Try DT::renderDataTable with server = FALSE
library(shiny)
library(crosstalk)
library(d3scatter)
library(DT)
ui <- fluidPage(
fluidRow(
column(6, d3scatterOutput("scatter1")),
column(6, DT::dataTableOutput("scatter2"))
)
)
server <- function(input, output, session) {
jittered_iris <- reactive({
iris
})
shared_iris <- SharedData$new(jittered_iris)
output$scatter1 <- renderD3scatter({
d3scatter(shared_iris, ~Petal.Length, ~Petal.Width, ~Species, width = "100%",
x_lim = range(iris$Petal.Length), y_lim = range(iris$Petal.Width))
})
output$scatter2 <- DT::renderDataTable({
datatable(shared_iris)
}, server = FALSE)
}
shinyApp(ui, server)
DT should throw an error when using Crosstalk with server-side processing
Error in widgetFunc: Crosstalk only works with DT client mode: DT::renderDataTable({...}, server=FALSE)
but I think that broke here: https://github.com/rstudio/DT/commit/893708ca10def9cfe0733598019b62a8230fc52b
Guess I can file an issue on this if no one else has.

Click on marker to open plot / data table

I'm working on leaflet with shiny. The tools is basic, i have a map with some markers (coming from a table with LONG and LAT).
What I want to do is to open a table or a graph when i click on the marker.
Is there a simple way to do it?
Do you have a really simple example: you have a maker on a map, you click on the marker, and there is a plot or a table or jpeg that s opening?
Here is another example, taken from here and a little bit adapted. When you click on a marker, the table below will change accordingly.
Apart from that, a good resource is this manual here:
https://rstudio.github.io/leaflet/shiny.html
library(leaflet)
library(shiny)
myData <- data.frame(
lat = c(54.406486, 53.406486),
lng = c(-2.925284, -1.925284),
id = c(1,2)
)
ui <- fluidPage(
leafletOutput("map"),
p(),
tableOutput("myTable")
)
server <- shinyServer(function(input, output) {
data <- reactiveValues(clickedMarker=NULL)
# produce the basic leaflet map with single marker
output$map <- renderLeaflet(
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
addCircleMarkers(lat = myData$lat, lng = myData$lng, layerId = myData$id)
)
# observe the marker click info and print to console when it is changed.
observeEvent(input$map_marker_click,{
print("observed map_marker_click")
data$clickedMarker <- input$map_marker_click
print(data$clickedMarker)
output$myTable <- renderTable({
return(
subset(myData,id == data$clickedMarker$id)
)
})
})
})
shinyApp(ui, server)
There is a leaflet example file here:
https://github.com/rstudio/shiny-examples/blob/ca20e6b3a6be9d5e75cfb2fcba12dd02384d49e3/063-superzip-example/server.R
# When map is clicked, show a popup with city info
observe({
leafletProxy("map") %>% clearPopups()
event <- input$map_shape_click
if (is.null(event))
return()
isolate({
showZipcodePopup(event$id, event$lat, event$lng)
})
})
Online demo (see what happens when you click on a bubble):
http://shiny.rstudio.com/gallery/superzip-example.html
On the client side, whenever a click on a marker takes place, JavaScript takes this event and communicates with the Shiny server-side which can handle it as input$map_shape_click.