Hello,
I'm trying to create an app that creates 2 different plots based on one user uploaded file. My approach is to create 2 different reactive data frames, that take the original uploaded raw data, but transform it differently based on the parameters needed for the plot. In addition, I'm using dplyr to filter/select columns for each reactive data frame.
However, every time I try to call the original uploaded data in the reactive functions, I get the following errors:
"no applicable method for 'select_' applied to an object of class "function"
"Result must have length 6, not 0"
For context, my uploaded data has 6 rows.
Code:
#This app allows users to upload 2x2/contingency table data in a pre-specified format, and in return, plots the data in several different forms.
#Load libraries
library(shiny)
library(ggplot2)
library(dplyr)
library(readxl)
library(tidyverse)
library(rlang)
library(DT)
#----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Define UI for overall application
#data upload
ui <- fluidPage(
Application title
titlePanel("Data Visualization -- 2x2 Analysis"),
tabsetPanel(
#----------------------------------------------------------------------------------------------------------------------------------------------------------
#Data upload tab
tabPanel("Upload File",
titlePanel("Upload CSV File"),
#sidebar layout with input and output definitions--
sidebarLayout(
#sidebar panel for inputs ---
sidebarPanel(
#input-- select file
fileInput('file1', 'Choose CSV File', multiple = FALSE,
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv')),
# Horizontal line ----
tags$hr(),
checkboxInput('header', 'Header', TRUE),
radioButtons('sep', 'Separator',
c(Comma=',',
Semicolon=';',
Tab='\t'),
','),
radioButtons('quote', 'Quote',
c(None='',
'Double Quote'='"',
'Single Quote'="'"),
'"'),
tags$hr(),
# Input: Select number of rows to display ----
radioButtons("disp", "Display",
choices = c(Head = "head",
All = "all"),
selected = "head")
),
#main panel to display outputs
mainPanel(
#output-- data file
dataTableOutput('contents')
)
)
),
#--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#point estimate line plot
tabPanel("Point Estimate Line Plot",
pageWithSidebar(
headerPanel('Point Estimate Line Plot'),
sidebarPanel(
#drop down menu inputs
selectInput('xcol','X Variable',""),
selectInput('ycol','Y Variable',""),
sliderInput("slider_lineplot", label = h3("Select range of samples by Column ID"), min = 0,
max = 20, value = 1),
selectInput("specimen","Select Specimen Type column",""),
selectInput("LCI","Lower Confidence Interval(LCI):",""),
selectInput("UCI","Upper Confidence Interval(UCI):",""),
#label inputs
textInput("title_lineplot",label="Plot Title",value="Enter text..."),
textInput("xlabel_lineplot",label="x-axis label",value="Enter text..."),
textInput("ylabel_lineplot",label="y-axis label",value="Enter text..."),
numericInput("referenceline","Reference value",0.95,min=0,max=1,step=0.01)
),
mainPanel(
plotOutput('lineplot'),
br(),
br(),
dataTableOutput('lineplot_table')
)
)
),
#--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#concentric pie chart
tabPanel("Concentric Pie Chart",
pageWithSidebar(
headerPanel('Pie Chart'),
sidebarPanel(
#label inputs
textInput("title",label="Plot Title",value="Enter text..."),
sliderInput("slider_piechart", label = h3("Select Column ID"), min = 0,
max = 20, value = 1),
selectInput('fill','Select Result Column',""),
selectInput('upperbound','Select YMAX Column',""),
selectInput('lowerbound','Select YMIN Column',""),
selectInput('ref','Select Type Column',"")
),
mainPanel(
plotOutput('piechart'),
dataTableOutput('piechart_table')
)
)
),
#--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
)
)
#--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Define server logic required to read file, and display all the different plots
server<- function(input, output,session) {
added "session" because updateSelectInput requires it
data <- reactive({
req(input$file1) ## ?req # require that the input is available
inFile <- input$file1
# tested with a following dataset: write.csv(mtcars, "mtcars.csv")
# and write.csv(iris, "iris.csv")
df <- read.csv(inFile$datapath, header = input$header, sep = input$sep,
quote = input$quote)
#augment data set. Add Sensitivity(PPA), Specificity(NPA), False Positive Rate(1-specificity), and 95% confidence intervals for PPA and NPA
#Tp = true positive, Fp = false positive, Fn = false negative, Tn = True negative
#add PPA and NPA
df$PPA <- round((df$TP)/(df$TP+df$FN),3) #sensitivity = Tp/(Tp+Fn)
df$NPA <- round((df$TN)/(df$TN+df$FP),3) #specificity = Tn/(Tn+Fp)
#----------------------------------------------------------------------------------------------------------------------------------------------------------------------
#add wilson confidence intervals
#----------------------------------------------------------------------------------------------------------------------------------------------------------------------
#Sensitivity(PPA) calculations-- first calculate Q1, Q2, Q3 quantiles
Q1_se <- (2*df$TP)+3.84
FNR <- (df$FN)/(df$TP+df$FN) #false negative rate(FNR) = Fn/(Fn+Tp)
Q2_se <- 1.96 * sqrt(3.84 + (4*df$TP*FNR))
Q3_se <- (2*(df$TP+df$FN))+7.68
#95% confidence intervals
#lower bound CI(LCI) and upper bound CI(UCI) for PPA
df$PPA_LCI <- round((Q1_se-Q2_se)/(Q3_se),3)
df$PPA_UCI <- round((Q1_se+Q2_se)/(Q3_se),3)
#----------------------------------------------------------------------------------------------------------------------------------------------------------------------
#Specificity(NPA)calculations-- first calculate Q1, Q2, Q3 quantiles
Q1_sp <- (2*df$TN)+3.84
TNR <- (df$TN)/(df$TN+df$FP) #false negative rate(FNR) = Fn/(Fn+Tp)
Q2_sp <- 1.96 * sqrt(3.84 + (4*df$FP*TNR))
Q3_sp <- (2*(df$FP+df$TN))+7.68
#95% confidence intervals
#lower bound CI(LCI) and upper bound CI(UCI) for NPA
df$NPA_LCI <- round((Q1_sp-Q2_sp)/(Q3_sp),3)
df$NPA_UCI <- round((Q1_sp+Q2_sp)/(Q3_sp),3)
df <- as.data.frame(df)
#datalist <- list(df=df, PPA=df$PPA, NPA=df$NPA, PPA_LCI=df$PPA_LCI, PPA_UCI=df$PPA_UCI,NPA_LCI=df$NPA_LCI,NPA_UCI=df$NPA_UCI,ColumnID=df$`Column ID`)
#datalist
return(df)
})
#---------------------------------------------------------------
lineplot_dataframe <- reactive({
df_lineplot <- filter(df,df$`Column ID`==1:input$slider_lineplot)
#df_lineplot <- filter(datalist$df,datalist$ColumnID==1:input$slider_lineplot)
#line plot create data frame
df2_lineplot <- data.frame(matrix(nrow=dim(df_lineplot)[1],ncol=7))
colnames(df2_lineplot) <- c("SpecimenType","PPA","NPA","PPA_upper","PPA_lower","NPA_upper","NPA_lower")
df2_lineplot$SpecimenType <- df_lineplot$`Specimen Type`
df2_lineplot$PPA<- round(df_lineplot$PPA,3)
df2_lineplot$NPA<- round(df_lineplot$NPA,3)
df2_lineplot$PPA_lower <- round(df_lineplot$PPA_LCI,3)
df2_lineplot$PPA_upper <- round(df_lineplot$PPA_UCI,3)
df2_lineplot$NPA_lower <- round(df_lineplot$NPA_LCI,3)
df2_lineplot$NPA_upper <- round(df_lineplot$NPA_UCI,3)
df2_lineplot <- as.data.frame(df2_lineplot)
#update select input for line plot
updateSelectInput(session, inputId = 'xcol', label = 'X Variable',
choices = names(df2_lineplot), selected = "")
updateSelectInput(session, inputId = 'ycol', label = 'Y Variable',
choices = names(df2_lineplot), selected = "")
updateSelectInput(session, inputId = 'specimen', label = 'Select Specimen Type column',
choices = names(df2_lineplot), selected = "")
updateSelectInput(session, inputId = 'LCI', label = 'Lower Confidence Interval(LCI):',
choices = names(df2_lineplot), selected = "")
updateSelectInput(session, inputId = 'UCI', label = 'Upper Confidence Interval(UCI):',
choices = names(df2_lineplot), selected = "")
return(df2_lineplot)
})
#---------------------------------------------------------------
#create reactive table for pie chart information
PieData_extracted <- reactive({
#PF <- filter(select(df1,6:9),df$`Column ID`==input$slider_piechart)
PF <- filter(select(df,1,6:9),df$`Column ID`==input$slider_piechart)
PF2 <- data.frame(matrix(nrow=4, ncol=7))
colnames(PF2) <- c("Type","Result","Result_transformed","Value","Percent","YMIN","YMAX")
PF2$Result <- colnames(PF)[2:5]
PF2$Value <- c(PF$TP,PF$FN,PF$TN,PF$FP)
PF2$Result_transformed <- c(0,0,1,1)
PF2$Type <- ifelse(PF2$Result_transformed==0,"Reference Positive","Reference Negative")
#percentage calculations
PF2$Percent <- round((PF2$Value/sum(PF2$Value))*100,2)
PF2$YMAX <- cumsum(PF2$Percent)
PF2$YMIN <- c(0,cumsum(PF2$Percent)[1:3])
#update select input for pie chart
updateSelectInput(session, inputId = 'fill', label = 'Select result(i.e TP, FN)',
choices = names(PF2)[2], selected = "")
updateSelectInput(session, inputId = 'upperbound', label = 'Select YMAX Column',
choices = names(PF2)[7], selected = "")
updateSelectInput(session, inputId = 'lowerbound', label = 'Select YMIN Column',
choices = names(PF2)[6], selected = "")
updateSelectInput(session, inputId = 'ref', label = 'Select Reference Column',
choices = names(PF2)[1], selected = "")
return(PF2)
})
For the lineplot and PF data frames, I'm calling df, the data frame which shows the raw data initially uploaded. I'm wondering if there is a different syntax to call the data.