In R Shiny, the data frame looks like below without the index.
However, after downloading the data, index column is automatically added to the data frame, please see below for illustration. How can I avoid this index being added? Because the downloaded template will be for user to populate the data, ideally would want no unnecessary fields.
My code for the download is listed below.
# UI
downloadButton("download1", "Download Template")
# reactive data frame df1 which contains other input from UI, can edit
# it to be a generic data frame for this to be reproducible
df1 = reactive({tibble(Year=strftime(seq(date_seq1(),
date_seq2(),
by = '1 week'), format = "%G"),
Week=strftime(seq(date_seq1(),
date_seq2(),
by = '1 week'), format = "%V"),
Date=seq(date_seq1(),
date_seq2(),
by = '1 week'),
!!input$urgency1 := "",
!!input$urgency2 := "",
!!input$urgency3 := "")})
# download the data frame
output$download1 <- downloadHandler(
filename = function(){"user_template.csv"},
content = function(file){
write.csv(df1(), file)
}
)
You have to set the option row.names = FALSE in the write.csv function.
Related
In my shiny app for time series forecasting, I want to accept uploads of a single column csv file. This should be quarterly demand. Since the users may have different format for dates, I don't ask for dates in the csv, but ask for starting dates and create a sequence for the other dates. Downloading the uploaded data works perfect. But in displaying the table format, the dates are displayed as numbers. This is a known problem and I saw the discussions here: Shiny showing numbers instead of dates. My problem is that I want to display the date as Year quarter ("2002 Q3") and I don't know how to do it. My guess is that I need to add some format in the renderTable function and tried to search for that but could not find it. Please help.
(I also tried DT but DT was not able to display the tsibble table and it showed some text in red about a problem with year quarter)
I have created a sample dataset that can be uploaded on this app: https://drive.google.com/file/d/17OPRK0g1veCEvTZWOpQwm9lZ6sb20Ill/view?usp=sharing
UI:
library(shiny)
shinyUI(fluidPage(
titlePanel("Upload and Download"),
sidebarLayout(
sidebarPanel(
h5(helpText("Enter the starting point of your data below")),
selectInput("qrtr","Quarter",choices = c("Q1","Q2", "Q3","Q4")),
selectInput("yrr", "Year", choices = seq(from= 1990, to = 2020, by = 1)),
fileInput("datafile","Upload data file"),
h5(helpText("Data should be single column csv file with a header"))
),
mainPanel(
downloadButton("dldata","Download data"),
tableOutput("content")
)
)
))
Server:
library(shiny)
library(fpp3)
shinyServer(
function(input,output){
getdata <- reactive({
#dbz <- as.data.frame(c(1,2,3,4), colnames = "Demand")
infile <- input$datafile
if(is.null(input$datafile))
return(NULL)
dte <- paste(input$yrr,input$qrtr)
dte <- yearquarter(dte)
db <- read.csv(infile$datapath, header = TRUE, sep = ",")
db$Quarter <- seq(from = dte, by = 1, length = nrow(db))
db <- as_tsibble(db, index = Quarter)
return(db)
})
output$content <- renderTable(getdata())
output$dldata <- downloadHandler(
filename = "data.csv",
content = function(file){write.csv(getdata(),file, , row.names = FALSE)}
)
}
)
have a data file that I read in in my Shiny server function. I would like to display a frequency table of the two columns the user selects using drop-downs. I get the error "table of extent 0". I have looked at R error - Table of extent 0 and Can't solve table issue but I have imported my data correctly and the column names match as well. The same line of code works when I run it in the console.
Here is my code:
shinyServer(function(input, output) {
output$courseData = renderTable( {
data = read.csv(file = 'FourCourseTableLetterGrades_POLISHED.tsv', sep = '\t', header = TRUE)
c1 = input$course1
c2 = input$course2
tbl = table(data[[c1]], data[[c2]])
tbl
}
)
}
)
This is how the output looks right now:
I would like it to be like the output you get when you run the same code in console. Like so:
What is wrong with my code? Also, I don't know where names Var1, Var2, and Freq come from and where I should change them.
renderTable will change any input to a dataframe before sending it to the UI, so you end up with something like data.frame(table(mtcars$cyl, mtcars$gear)). We can try
output$courseData = renderTable(rownames=TRUE, {
data = mtcars
c1 = input$course1
c2 = input$course2
tbl = as.data.frame.matrix(table(data[[c1]], data[[c2]]))
tbl})
}
I am trying to add source information to a downloaded table which contains a dataframe. I am using the download file handler to download the file. I have implemented downloading of just the dataframe without appending additional text and that works fine. On attempting to add text with the table, I get the csv formatted download file but the source information is missing and the last row has NA in the 1st and 2nd column respectively. Rest of the last row is empty.
Here is my code for the download handler that do not produce the appended text output:
downloadHandler(
filename = function() {
paste("Estimation_", Sys.Date(), ".csv", sep="")
},
content = function(file) {
df <- localTable()
df[nrow(df)+1,] <- NA
df[nrow(df),1] <- "Source: This is the source information for the table"
write.csv(df,
file,
na = "",
row.names=FALSE,
append = TRUE)
},
contentType = "text/csv",
outputArgs = list(label = "Download Table")
)
On the other hand I have tried the same functionality separately that works fine. Here is the code I used in a separate R script that does the same thing.
df = data.frame(hello=rnorm(1:5), world=rnorm(1:5));
df[nrow(df)+1,] <- NA
df[nrow(df),1] <- "Source: This is the source information for the table"
write.csv(df,
file ="abc.csv",
na = "",
row.names=FALSE)
I do not know if the issue is with Shiny in particular or something else. Please note that I am using this code as part of Flexdashboard that runs a RMD file to generate the output.
I have tried several other ways of creating the dataframe like the one below; and then passing to the downloadHandler but no luck.
dlTable <- reactive({
df_results <- localTable()
df_notes <- "Source: This is the source information for the table"
df_to_dl <- rbindlist(list(df_results,df_notes))
return(df_to_dl)
})
Any suggestion and help is highly appreciated.
Thanks
I wrote a shiny app which will be used for searching and downloading a quite large dataset. The app works and is nearly done, but some functionalities do not work as I want:
I tried several ways of adding a function in order to download the chosen data as .csv-file. All of them failed and I was only able to download all data instead of the displayed ones.
I was not able to include a function to round data and show some columns as percentage instead of numbers. The formatRound() function within datatable() works well and I would like to use it, but the problem is that I was not able to include it in the server function. Since the user should get the whole number (with all numbers also behind the comma) for his or her work, the data should only be rounded when displayed. If I would be able to fix the rounding, the percentage problem will also be solved, since I would use the similar function formatPercentage().
I made an example using the mtcars-data and removed all wrong or not-working codes for the download and rounding problem. Any hints how I could solve my problem would be extremely appreciated! Thanks in advance!
EDIT3: Rounding problem solved with the code below thanks to #Claud H. The download function exports an empty file (no file-type) named download. Do you have any idea where the error is?
EDIT4: problems solved thanks to #Claud H. I changed mt_cars_filtered()[, c(input$results_columns_selected)]into mt_cars_filtered()[, input$indicator]. Also, I didn't know first that I had to open the web browser to download the data.
library(tidyverse)
library(shiny)
library(shinythemes)
library(DT)
library(ggthemes)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(width=3,
h3("title", align = 'center'),
checkboxGroupInput("cylinder", "Cylinder", choices = c(4,6), selected = c(4)),
checkboxGroupInput('indicator', label = 'Indicators', choices = colnames(mtcars)[1:7],
selected = colnames(mtcars)[c(1:7)]),
fluidRow(p(class = 'text-center', downloadButton('download', label = 'Download')))),
mainPanel(
tabsetPanel(
tabPanel('Table',
DT::dataTableOutput('results'))
)
)
))
server <- function(input, output){
mtcars_filtered <- reactive({
mtcars %>%
filter(cyl %in% input$cylinder)
})
# Output Table
output$results <- DT::renderDataTable({
columns = input$indicator
mtcars_filtered()[, columns, drop = FALSE] %>%
datatable(style = 'bootstrap', selection = list(target = 'column'), options = list(paging = FALSE, dom = 't')) %>%
formatRound(input$indicator[grep('t', input$indicator)], 2)
})
# Download Data
output$download <- downloadHandler(
filename = function() { paste('filename', '.csv', sep = '') },
content = function(file) {
write.csv(mtcars_filtered()[,input$indicator], file, row.names = FALSE)
})
}
shinyApp(ui = ui, server = server)
Suggest looking at ?"%>%" from magrittr package
Also, check this and this answers on SO.
Your table should be fine with this kind of syntax
output$results <- DT::renderDataTable({
columns = input$indicator
mtcars_filtered()[, columns, drop = FALSE] %>%
datatable() %>%
formatCurrency( input your code here) %>%
formatPercentage( and so on ... )
}, style = 'bootstrap', options = list(paging = FALSE, dom = 't'))
Also, I didnt quite get the question about downloading. If you want to download a data FROM server, use downloadHandler() function. Something like:
output$save_data <- downloadHandler(
filename = function() { paste("filename", '.csv', sep = '') },
content = function(file) {
write.csv(mydata(), file, row.names = FALSE)
})
and downloadButton("save_data", "download") in ui.R
edit: as per your changes, download isn't working because you got wrong columns selected: there is no table called tableId, and you need to take the columns from the table called results:
write.csv(mtcars_filtered()[, c(input$results_columns_selected)], file, row.names = FALSE)
as of rounding problem, you can use your indicator variable to see if column is selected input$indicator %in% c('drat', 'qsec', 'wt') then use subsetting to select only columns with TRUE, if there are any: formatRound(input$indicator[input$indicator %in% c('drat', 'qsec', 'wt')], 2)
edit2
Seems I've understood everything you wanted to do right.
To select columns in the downloadHandler function based on your checkboxes , use indicator variable to filter it:
mtcars_filtered()[, input$indicator]
Otherwise, if you want to select them from the table itself with the mouse clicks, use input$results_columns_selected, like this:
mtcars_filtered()[, c(input$results_columns_selected)]
I'm stuck trying to get dates to show up in a Shiny table. I have done some research and see that in the past xtable does not work nicely with Shiny. There are a couple of questions on SO that dealt with this issue. The one routinely reference can be found here R: xtable and dates.
My problem is that 1)I'm extremely new at programming in Shiny and using xtable. 2) I am unfamiliar with using POSIXct. 3) I don't understand the solution provided in the link above.
Please provide a helping hand for the basic code below. The idea is that somebody would use this app to enter data daily. These data would be stored on a .csv. When stored on the .csv only the numeric value of the R date is stored. This is what shows up on the Shiny table as well. Please teach me how to format correctly in both the table and the .csv file.
Before examining the code below, know that there would be a .csv file stored that would have the Headers Date, A, B. Let's call this file "log" and it would be stored locally. Here is the code:
library(shiny)
log <- read.table("V:\\My\\Path\\log.csv",sep=",",header=T)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(width=2,
#Enter Date
dateInput("date","Date",min="2016-07-04", max = "2017-07-04"),
#Enter Combo
selectInput(inputId = "a", "A", c("Choose one" = "","A1", "A2", "A3"), multiple = FALSE, selectize = TRUE, width = NULL, size = NULL),
#Enter Number
numericInput(inputId = "b", "Favorite Number", NULL, min = 0, max = NA),
#Enter Submit to write info to file
actionButton(inputId = "submit", "Submit", icon = NULL, width = NULL)
),
mainPanel(
# Application title
titlePanel("Read Date"),
tableOutput("summary"))
)
)
server <- function(input, output) {
#Create vector of current trial results
data <- eventReactive(input$submit, {
cbind(input$date,input$a, input$b)
})
#Append current trial results to master list
observeEvent(input$submit, {
write.table(data(), file="V:\\My\\Path\\log.csv", sep=",", col.names= FALSE, row.names=F, append = T)
})
#Create datatable variable reading in latest log
datatable <- eventReactive(c(input$agent,input$submit), { #Putting both reactive variables allow to see dataset without running and see updated dataset after running.
data.frame(read.table("V:\\My\\Path\\log.csv",sep=",",header=T))
})
#Create Table
output$summary <- renderTable({
datatable() }, digits=2,align = "cccc" )
}
shinyApp(ui = ui, server = server)
It seems the answer is to write as character to the log file and read it back in as a character. I can't figure out to do this. Am I on the right track? Because I'm learning I'll take any other suggestions on how to improve my code.
I finally figured out the simple solution.
I just changed the code when I build the dataframe from
data <- eventReactive(input$submit, {
cbind(input$date,input$a, input$b)
to
data <- eventReactive(input$submit, {
cbind(as.character(input$date),input$a, input$b))
Adding the as.character() seems to have done the trick. I don't know if this will have consequences later, but the displayed table now looks nice.