I have two questions:
1) I want to serve several text Input fields that look like a table. My solution is ok, but there is too much space between the lines due to the title for each field required. How can I shorten the distance between the text Input fields?
2) The Output shall be a data.frame which includes data from the Input. How can I create a data.frame out of Input data in "Output$contents"?
Thank you.
Shortened extract of the code:
ui <- fluidPage(
# App title ----
titlePanel("Stochastische Cashflows"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
h4("Psychologisch motivierte Abflüsse aus Einlagen"),
tags$hr(),
fluidRow(
column(6,
textInput("file1", "Passive Bilanzpostionen eingeben"),
textInput("file2", "")
),
column(6,
textInput("file3", "Passive Bilanzpostionen eingeben"),
textInput("file4", "")
)
),
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
tableOutput("contents"),
)
)
)
################################################################################################################
################################################################################################################
server <- function(input, output) {
output$contents <- renderTable({
print(9)
})
################################################################################################################
################################################################################################################
# Create Shiny app ----
shinyApp(ui, server)
###########################################################################################################
You can use a css to reduce the top margin:
tags$style(type="text/css", "#file2 { margin-top: -20px }")
You can put it just after you create the text input.
To get the contents as a dataframe, a reactive conductor is nice:
df <- reactive({
data.frame(A=c(input$file1, input$file2), B=c(input$file3, input$file4))
})
output$contents <- renderTable({
df()
})
Complete code:
library(shiny)
ui <- fluidPage(
# App title ----
titlePanel("Stochastische Cashflows"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
h4("Psychologisch motivierte Abflüsse aus Einlagen"),
tags$hr(),
fluidRow(
column(6,
textInput("file1", "Passive Bilanzpostionen eingeben"),
textInput("file2", ""),
tags$style(type="text/css", "#file2 { margin-top: -20px }")
),
column(6,
textInput("file3", "Passive Bilanzpostionen eingeben"),
textInput("file4", ""),
tags$style(type="text/css", "#file4 { margin-top: -20px }")
)
)
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
tableOutput("contents")
)
)
)
# server ----
server <- function(input, output) {
df <- reactive({
data.frame(A=c(input$file1, input$file2), B=c(input$file3, input$file4))
})
output$contents <- renderTable({
df()
})
}
# Create Shiny app ----
shinyApp(ui, server)
Related
I have a simple shiny app below. In this app I want the user to be able to upload his own csv and then automatically this will be added as a choice in the checkbox group below the other dataset "D.B" (which I create in my original app).
#ui.r
ui <- fluidPage(
# App title ----
titlePanel("Uploading Files"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Select a file ----
fileInput("file1", "Choose CSV File",
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
uiOutput("checkbox"),
textInput("filename","Set Filename")
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
tableOutput("contents")
)
)
)
#server.r
server <- function(input, output) {
output$contents <- renderTable({
req(input$file1)
df <- read.csv(input$file1$datapath)
})
D.B <- reactive({
#some code that creates the dataset D.B.
})
output$checkbox<-renderUI({
checkboxGroupInput("datasetSelector","Specify the datasets to compare:", choices = c("D.B")
)
})
}
You could use a reactive value to store choices then add a choice everytime a file is uploaded. Use an observer to watch for file uploads (I also used the library rlist which gives me the append method).
library(rlist)
#ui.r
ui <- fluidPage(
# App title ----
titlePanel("Uploading Files"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Select a file ----
fileInput("file1", "Choose CSV File",
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
uiOutput("checkbox"),
textInput("filename","Set Filename")
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
tableOutput("contents")
)
)
)
#server.r
#fileOptions = list("D.B.")
server <- function(input, output, session) {
output$contents <- renderTable({
req(input$file1)
df <- read.csv(input$file1$datapath)
head(df)
})
fileOptions <- reactiveValues(currentOptions=c("D.B."))
observeEvent(input$file1, {
fileOptions$currentOptions = list.append(fileOptions$currentOptions, input$file1$datapath)
})
D.B <- reactive({
#some code that creates the dataset D.B.
})
output$checkbox<-renderUI({
checkboxGroupInput("datasetSelector","Specify the datasets to compare:", choices = fileOptions$currentOptions
)
})
}
I am looking for a way to link from an HTML text (nested in the server part) to a specific Shiny tabPanel (nested in UI). Let's say we have the following app:
library(shiny)
shinyUI(fluidPage(
sidebarLayout(
mainPanel(
tabsetPanel(
type="tabs",
tabPanel("Contents", htmlOutput("contents")),
tabPanel("Plot", plotOutput("plot")) # <- A link to here
)
)
)
))
shinyServer(function(input, output) {
output$contents <- renderText({
HTML("A link to <a href='#Plot'>Plot</a>") # <- from there
})
output$plot({
some ggplot
})
})
How could I create a link within the text that then redirects to a certain tab. I tried anchor tags but they don't seem to work as the id keeps changing upon each start of the app.
Thanks in advance.
I don't know whether this is possible with a link. But you can use a button and updateTabsetPanel.
library(shiny)
library(ggplot2)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(),
mainPanel(
tabsetPanel(
type="tabs",
id = "tabset",
tabPanel("Contents", actionButton("go", "Go to plot")),
tabPanel("Plot", plotOutput("plot"))
)
)
)
)
server <- function(input, output, session) {
observeEvent(input$go, {
updateTabsetPanel(session, "tabset", "Plot")
})
output$plot <- renderPlot({
ggplot(mtcars, aes(x=cyl, y=disp)) + geom_point()
})
}
shinyApp(ui, server)
Thanks to Stéphane Laurent, who pointed me in the right direction, I managed to create the solution I wanted. In order to keep all the HTML text in the server function I used a combination of renderUI and actionLink. The solution now looks as follows:
library(shiny)
shinyUI(fluidPage(
sidebarLayout(
mainPanel(
tabsetPanel(
type="tabs",
id = "tabset", # <- Key element 1
tabPanel("Contents", htmlOutput("contents")),
tabPanel("Plot", plotOutput("plot"))
)
)
)
))
shinyServer(function(input, output, session) {
output$contents <- renderUI({ # <- Key element 2
list(
HTML(<p>Some text..</p>),
actionLink("link", "Link to Plot") # <- Key element 3
)
})
observeEvent(input$link, {updateTabsetPanel(session, "tabset", "Plot")}) # <- Key element 4
output$plot({
some ggplot
})
})
Is there some way to have a dynamic titlePanel title that pulls directly from UI kind of like below? If it's not possible, is it possible to have a second row that's similar to titlepanel right below titlepanel?
# Define UI ----
ui <- fluidPage(
##Whatever UI code here
titlepanel_text = paste0("Some string", variable_with_text)
)
# Define server logic ----
server <- function(input, output) {
titlePanel("title panel"),
#Rest of server code here
}
Render the text in the server and grab the text output in the UI:
library(shiny)
# Define UI ----
ui <- fluidPage(
##Whatever UI code here
titlePanel(textOutput("title_panel")),
sidebarLayout(
sidebarPanel(),
mainPanel(h1("text"))
)
)
# Define server logic ----
server <- function(input, output) {
output$title_panel <- renderText({
paste0("This is the date/time: ", Sys.time() )
})
}
shiny::shinyApp(ui, server)
you can insert this kind of code to structure your title panel
# Application title
titlePanel(
fixedRow(
column(9,
"My Template",
fixedRow(
column(9,
paste0("Author : ", author)
),
column(3,
paste0("date : ", today(tzone = ""))
)
)
)
) ),
I am using shiny to upload different data files from a certain folder and plot a histogram based on a certain column. The name of each file looks like "30092017ARB.csv" (date + ARB.csv).
The code loops over all file names in the data-folder and print the name of files in a drop-down bottom. After selecting the name of file it should be uploaded and plot a histogram of the mw-column (the name of column is "mw). My GUI looks as follows:
library("shiny")
dataset <- list.files("C:/R_myfirstT/data", pattern=".*.csv$")
# Define UI for dataset viewer app ----
ui <- fluidPage(
# App title ----
titlePanel("Data plot"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Selector for choosing dataset ----
selectInput(inputId = "date",
label = "Choose a date:",
choices = dataset)
),
# Main panel for displaying outputs ----
mainPanel(
plotOutput("plot")
)
)
)
and the server
# Define server ----
dataset <- list.files("C:/R_myfirstT/data", pattern=".*.csv$")
dat.name<-paste("C:/R_myfirstT/data/",dataset,sep = "")
server <- function(input, output) {
datasetInput <- reactive({
switch(input$dataset,
for (i in 1:length(dataset)){
toString(dataset[i])=read.csv(file=dat.name[i], header=TRUE, sep=";")
}
)
output$plot <- renderPlot({
hist(dataset.mw, breaks = 40)
})
})
}
My problem is: I do not get any histogram! I get just the which is nice however, not entirely my goal!
Any idea what could be the reason?
Something like this works:
ui.R
library("shiny")
# Define UI for dataset viewer app ----
ui <- fluidPage(
# App title ----
titlePanel("Data plot"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Selector for choosing dataset ----
selectInput(inputId = 'date',
label = 'Choose a date:',
choices = list.files(path = "./data",
full.names = FALSE,
recursive = FALSE))
),
# Main panel for displaying outputs ----
mainPanel(
plotOutput("plot")
)
)
)
server.R
# Define server ----
server <- function(input, output) {
dataset <- reactive({
infile <- input$date
if (is.null(infile)){
return(NULL)
}
read.csv(paste0('./data/',infile))
})
output$plot <- renderPlot({
x <- dataset()[,1]
hist(x, breaks = 40)
})
}
I am trying to subset data frame of three column (StockCode,Price,label)
but I had to used reactive and my ask is how to render label
I need somethink like renderText(dataset()$label)
ui.R
library(shiny)
# Define UI for app that draws a histogram ----
ui <- fluidPage(
# App title ----
titlePanel("Hello Shiny!"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
uiOutput("codePanel")
),
# Main panel for displaying outputs ----
mainPanel(
textOutput("text")
)
)
)
server.R
server <- function(input, output) {
output$codePanel<-renderUI({
selectInput("codeInput",label ="choose code",choices =data$StockCode)
})
dataset<-reactive({
subset(data,data$StockCode==input$codeInput)
})
output$text<-renderText(dataset())
}
If we are looking to show the data.frame output use the renderDataTable from DT. For reproducibility, used the inbuilt dataset iris
library(shiny)
library(DT)
ui <- fluidPage(
# App title ----
titlePanel("Hello Shiny!"),
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
uiOutput("codePanel")
),
mainPanel(
DT::dataTableOutput("text")
)
)
)
server <- function(input, output) {
filt <- selectInput("codeInput",label ="choose code",
choices = as.list(unique(iris$Species)))
output$codePanel <- renderUI({ filt
})
dataset<-reactive({
subset(iris, Species == input$codeInput)
})
output$text<-renderDataTable(dataset())
}
shinyApp(ui = ui, server = server)
-output
The dataset rows can be pasted together to a string to be used in the renderText
ui <- fluidPage(
# App title ----
titlePanel("Hello Shiny!"),
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
uiOutput("codePanel")
),
mainPanel(
verbatimTextOutput("text")
)
)
)
server <- function(input, output) {
filt <- selectInput("codeInput",label ="choose code",
choices = as.list(unique(iris$Species)))
output$codePanel <- renderUI({ filt
})
iris$Species <- as.character(iris$Species)
dataset<-reactive({
do.call(paste, c(collapse = "\n", rbind(colnames(iris), subset(iris, Species == input$codeInput))))
})
output$text<-renderText(dataset())
}
shinyApp(ui = ui, server = server)
-output
Or use htmlOutput with renderUI
ui <- fluidPage(
# App title ----
titlePanel("Hello Shiny!"),
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
uiOutput("codePanel")
),
mainPanel(
htmlOutput("text")
)
)
)
server <- function(input, output) {
filt <- selectInput("codeInput",label ="choose code",
choices = as.list(unique(iris$Species)))
output$codePanel <- renderUI({ filt
})
dataset<-reactive({
do.call(paste, c(collapse = "<br/>", rbind(colnames(iris), subset(iris, Species == input$codeInput))))
})
output$text<-renderUI(HTML(dataset()))
}
shinyApp(ui = ui, server = server)
I could not get renderDataTable from DT to work. A message said some functions were masked. So, I removed DT and added in some code from the R Studio tutorial on tables and data.frames. This is what I came up with:
library(shiny)
ui <- fluidPage(
# App title ----
titlePanel("Subsetting Iris Dataset"),
sidebarLayout(
# Sidebar panel for inputs
sidebarPanel(
uiOutput("codePanel"),
# Input: Numeric entry for number of obs to view
numericInput(inputId = "obs",
label = "Number of observations to view:",
value = 10)
),
mainPanel(
tableOutput("view")
)
)
)
server <- function(input, output) {
filt <- selectInput("codeInput", label = "choose code",
choices = unique(iris$Species))
output$codePanel <- renderUI({ filt
})
dataset <- reactive({
subset(iris, Species == input$codeInput)
})
output$view <- renderTable(head(dataset(), n = input$obs))
}
shinyApp(ui = ui, server = server)