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})
}
Related
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.
I'm getting this error when I run below code, can anyone please tell how to overcome this error.
Below is the code in which mydata is the main data set and I have created a shiny dashboard using the below code.
I tried to make one of the column as URL , but its showing error as in title.
And I tried giving data()$IFX_USERNAME as in his is a very common error in shiny apps. This most typically appears when you create an object such as a list, data.frame or vector using the reactive() function – that is, your object reacts to some kind of input. If you do this, when you refer to your object afterwards, you must include parentheses.
For example, let’s say you make a reactive data.frame like so:
MyDF<-reactive({ code that makes a data.frame with a column called “X” })
If you then wish to refer to the data.frame and you call it MyDF or MyDF$X you will get the error. Instead it should be MyDF() or MyDF()$X You need to use this naming convention with any object you create using reactive(), even then its showing the same error
library("shiny")
library("datasets")
library("DT")
library("shinyBS")
library(tidyr)
lapply( dbListConnections( dbDriver( drv = "MySQL")), dbDisconnect)
#connecting to database
dbListTables(mydb)
dbListFields(mydb, 'DL_COMMUNITY')
rs = dbSendQuery(mydb, "select * from DL_COMMUNITY")
mydatabase=fetch(rs)
setDT(mydatabase)
colnames(mydatabase)
header <- dashboardHeader()
ui = shinyUI(fluidPage(
DT::dataTableOutput("mtcarsTable"),
bsModal("mtCarsModal", "My Modal", "",dataTableOutput('mytext'), size = "large")
))
on_click_js = "
Shiny.onInputChange('mydata', '%s');
$('#mtCarsModal').modal('show')
"
on_click_js1 = "
Shiny.onInputChange('mydata', '%s');
$('#mtcarsTable').modal('show')
"
convert_to_link = function(x) {
as.character(tags$a(href = "#", onclick = sprintf(on_click_js,x), x))
}
convert_to_link1 = function(x) {
as.character(tags$a(href = "#", onclick = sprintf(on_click_js1,x), x))
}
shinyApp(
ui = ui,
server = function(input, output, session) {
mtcarsLinked <- reactive({
mydatabase$IFX_USERNAME <- sapply(
mydatabase$IFX_USERNAME,convert_to_link)
return(mydatabase)
})
**linked <- reactive({
myd$TEAM_MEMBERS <- sapply(
myd$TEAM_MEMBERS,convert_to_link1)
return(myd)
})**
output$mtcarsTable <- DT::renderDataTable({
DT::datatable(mtcarsLinked(),
class = 'compact',
escape = FALSE, selection='none'
)
})
output$mytext = DT::renderDataTable({
#userQuery=paste("select PROJECT,COMMENT from DL_COMMUNITY where IFX_USERNAME = '",user,"'",sep="")
#rs = dbSendQuery(mysqlCon,userQuery)
userQuery=paste("SELECT *
from Heatmap.DL_PROJECT where CONCAT(',', TEAM_MEMBERS, ',') like '%,sa,%'
or PROJECT_OWNER like '%,sa,%'
or PROJECT_LEAD like '%,sa,%'")
rs = dbSendQuery(mydb,userQuery)
myd=fetch(rs,n=-1)
myd<-data.frame(myd)
myd$TEAM_MEMBERS<- as.list(strsplit(myd$TEAM_MEMBERS, ","))
#myd<-myd %>%
#mutate(TEAM_MEMBERS = strsplit(as.character(TEAM_MEMBERS), ",")) %>%
#unnest(TEAM_MEMBERS)
#setDT(myd)
#hello <- input$mydata
#myd<-mydatabase[mydatabase$IFX_USERNAME==input$mydata,]
#myd1<-t(myd)
DT::datatable(linked(),
class='compact',
escape = FALSE,selection = 'none')
})
}
)
First, always use my_reactive() when you call a reactive function e.g. my_reactive.
Second, the object of type closure not subsettable usually means that the object you want to subset (here with $) cannot be found. You are not having the object not found error because you gave it a name already known to R.
As in the example of jogo, the same error occurs when trying to subset mean. mean is an object in R so it exists and R will not return object not found but it is a function and you cannot subset from it hence the error object is not subsettable.
Compare the results of the following lines of code.
mean[1]
mean <- c(1, 3)
mean[1]
Also note that R can still use mean to perform the mean of a numeric vector as it knows when to look for a function or for something else. But it is strongly advised not to do that. You should always properly name your objects with meaningful names.
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.
I have a shiny-app that displays a datatable using the DT-package. What I want is to be able to format columns in a custom way. For example I want a currency value to be displayed like this: 1,234.50€ instead of the DT-way, which displays it like this $1,234.5 (notice the change in the symbol, the position of the currency-symbol as well as the numbers after the decimal-point).
An MWE looks like this:
library(shiny)
library(DT)
shinyApp(
# UI
ui = fluidPage(DT::dataTableOutput('tbl')),
# SERVER
server = function(input, output) {
dat <- data.frame(cur = 1234.5, # supposed to be displayed as: 1,234.50€ | Bad!
# displayed as $1,234.5
perc = 0.123456, # 12.34% | Good!
num = 1000) # 1,000 | Bad! displayed as 1000
# render DT
output$tbl = DT::renderDataTable(
datatable(dat) %>%
formatCurrency(c('cur'), "$") %>%
formatPercentage('perc', 2) %>%
formatRound('num', digits = 0)
)
}
)
It does a fairly good job, however, when changing the currency-symbol to €, the symbol disappears. When inserting another character like "E", the character is still displayed at the beginning not at the end. Furthermore, the numeric value does not get a "big-mark".
Any ideas?
You can change the position of the currency symbol in the .js file from the datatable package.
Edit the line of the DTWidget.formatCurrency function
$(thiz.api().cell(row, col).node()).html(currency + markInterval(d, interval, mark));
to simply
$(thiz.api().cell(row, col).node()).html(markInterval(d, interval, mark) + currency);
in the DT/htmlwidgets/datatables.js file in the directory of your R librarys.
As for the € Symbol,
formatCurrency(c('cur'), currency = "\U20AC", interval = 3, mark = ",", digits = 2)
does work for me, thats what you tried and you don't see any symbol?