I need some help creating dynamic plots that go inside dynamic tabs. Here's the situation ... I have a data file that contains digital marketing data. The file has the following pieces of information: Campaign Name, Channel Name, Page Views, and Visits. Campaign Names are unique and roll up to one of four different marketing channels. This will change in the future depending on the data I feed it (for example, I may have six marketing channels in the next file I use), but this will do for troubleshooting purposes. I want to dynamically create tabs and output for each marketing channel in the file. I have been able to figure out how to create the tabs, but I'm having a hard time figuring out how to create other types of output (like a plot) to go with each tab.
The tabs were created using renderUI in the following code in the server file:
output$mytabs = renderUI({
if(is.null(rawData())){return ()}
channels = unique(rawData()$Channel)
myTabs = lapply(channels, tabPanel)
do.call(tabsetPanel, myTabs)
})
output$scatterPlot <- renderUI({
if(is.null(rawData())){return()}
createPlots()
myData = rawData()
channels = unique(myData$Channel)
plot_output_list <- lapply(seq_along(channels), function(i) {
plotname <- paste("plot", i, sep="")
plotOutput(plotname)
})
do.call(tagList, plot_output_list)
})
createPlots <- reactive ({
myData = rawData()
channels = unique(myData$Channel)
for (i in seq_along(channels)) {
local({
my_i <- i
plotname <- paste("plot", my_i, sep="")
tempRows = which(myData$Channel==channels[i])
output[[plotname]] <- renderPlot({
plot(x = myData$Spend[tempRows], y = myData$Return[tempRows])
})
})
}
})
These were then referenced in the ui file as follows:
mainPanel(
tabsetPanel(
tabPanel("Data Summary", uiOutput("dataSummary")),
tabPanel("Parameters & Model Fit",
uiOutput('mytabs'),
uiOutput('scatterPlot')),
tabPanel("Budget & Spend Summary"),
tabPanel("Testing", plotOutput('plot5'))
)
)
Ultimately, I'd like to plot Page Views vs Visits for each Marketing Channel on the corresponding marketing channel tab. At the moment, all four plots are showing up in each of marketing channel tab. In my global file, I've created two functions -- one function plots one channel at a time and another function that plots all the channels and saves each one as separate elements within a list. I'm not sure which one of these will end up being useful, if either.
I'm certain that I'm not understanding how to set 'myTabs' or I'm referencing it incorrectly from the ui. Even with this snippet of the code, someone here might be able to quickly spot the error and recommend a fix, but I am happy to provide the rest of my code if that would be helpful.
Thanks! Jess
EDIT: For Reference, here is all of my code. Just changed the dir object to be the directory you want to work in.
library(shiny)
dir = ""
setwd(dir)
#######################
### Generate Data ###
#######################
channels = c("Affiliate","Email","Media","SEO")
nObs = c(round(runif(1,100,200)))
pageViews = runif(nObs*length(channels),50,500)
visits = runif(nObs*length(channels),10,100)
campaignNames = unlist(lapply(channels, FUN = function(x) paste(x,seq(from=1,to=nObs,by=1),sep="")))
channelNames = rep(channels,nObs)
myData = data.frame(Campaign = campaignNames, Channel = channelNames, Return = pageViews, Spend = visits)
write.table(myData,file="myTestData.csv",sep=",",col.names=TRUE,row.names=FALSE)
########################
### Global Functions #
########################
summarizeData = function(myDat){
summaryData = summarize(group_by(myDat,Channel), 'Campaign Count' = length(Campaign), Return = sum(Return), Spend = sum(Spend))
return(summaryData)
}
### PLOT DATA AND MODEL FIT ###
plotSingle = function(myData, channelName){
p1 <- ggplot(myData[which(myData$Channel==channelName),], aes(x = Spend, y = Return)) +
geom_point(color="black") +
theme(panel.background = element_rect(fill = 'grey85'),
panel.grid.major = element_line(colour = "white"))
return(p1)
}
plotAll = function(myData){
channels = unique(myData$Channel)
plots <- list() # new empty list
for (i in 1:length(channels)) {
channelName = channels[i]
p1 = plotSingle(myData = myData, channelName = channelName)
plots[[i]] = p1
}
return(plots)
}
############
### UI ###
############
ui <- fluidPage(
headerPanel('Plot Testing'),
sidebarPanel(
h3(helpText("Data Input")),
fileInput(inputId = "rawDataInput", label = "Upload Data"),
h5(helpText("Select the file parameters below")),
checkboxInput(inputId = 'header', label = 'Header', value = TRUE),
checkboxInput(inputId = "stringAsFactors", "stringAsFactors", FALSE),
br(),
radioButtons(inputId = 'sep', label = 'Separator', choices = c(Comma=',',Semicolon=';',Tab='\t', Space=''), selected = ',')
),
mainPanel(
tabsetPanel(
tabPanel("Data Summary", uiOutput("dataSummary")),
tabPanel("Parameters & Model Fit",
uiOutput('mytabs'),
uiOutput('scatterPlot')),
tabPanel("Budget & Spend Summary"),
tabPanel("Testing", plotOutput('plot5'))
)
)
)
################
### Server ###
################
server = function(input, output) {
rawData <- reactive({
file1 <- input$rawDataInput
if(is.null(file1)){return()}
read.table(file=file1$datapath, sep=input$sep, header = input$header, stringsAsFactors = input$stringAsFactors)
})
# this reactive output contains the summary of the dataset and display the summary in table format
output$filedf <- renderTable({
if(is.null(rawData())){return ()}
input$rawDataInput
})
# this reactive output contains the summary of the dataset and display the summary in table format
output$sum <- renderTable({
if(is.null(rawData())){return ()}
summarizeData(rawData())
})
# This reactive output contains the dataset and display the dataset in table format
output$table <- renderTable({
if(is.null(rawData())){return ()}
rawData()
})
dataPlots = reactive({
channels = unique(rawData()$Channel)
plots = plotAll(rawData())
})
output$mytabs = renderUI({
if(is.null(rawData())){return ()}
channels = unique(rawData()$Channel)
createPlots()
plot_output_list <- lapply(seq_along(channels), function(i) {
plotname <- paste("plot", i, sep="")
plotOutput(plotname)
})
myTabs = lapply(channels, tabPanel)
do.call(tabsetPanel, myTabs)
})
createPlots <- reactive ({
myData = rawData()
channels = unique(myData$Channel)
for (i in seq_along(channels)) {
local({
my_i <- i
plotname <- paste("plot", my_i, sep="")
tempRows = which(myData$Channel==channels[i])
output[[plotname]] <- renderPlot({
plot(x = myData$Spend[tempRows], y = myData$Return[tempRows])
})
})
}
})
output$scatterPlot <- renderUI({
if(is.null(rawData())){return()}
createPlots()
myData = rawData()
channels = unique(myData$Channel)
plot_output_list <- lapply(seq_along(channels), function(i) {
plotname <- paste("plot", i, sep="")
plotOutput(plotname)
})
do.call(tagList, plot_output_list)
})
output$dataSummary <- renderUI({
if(is.null(rawData())){return()}
else
tabsetPanel(tabPanel("About file", tableOutput("filedf")),tabPanel("Data", tableOutput("table")),tabPanel("Summary", tableOutput("sum")))
})
output$plot5 = renderPlot({
if(is.null(rawData())){return ()}
myData = rawData()
channelName = "Affiliate"
p1 <- ggplot(myData[which(myData$Channel==channelName),], aes(x = Spend, y = Return)) +
geom_point(color="black") +
theme(panel.background = element_rect(fill = 'grey85'),
panel.grid.major = element_line(colour = "white"))
return(p1)
})
}
### Run App ###
shinyApp(ui = ui, server = server)