I like to think one of my strengths in what I do is presenting data in an interesting manner that tells a story AND anticipating questions that may arise from the presentation of data. When I was a graduate student I had an adviser who encouraged his students to add slides following a presentation for questions that we would anticipate from our audience. You couldn't cover all of the material in a 20 minute talk, but you could use the 10 minutes of questions/follow-up to add material if you anticipated those questions ahead.
Today, I apply the same method to data reports and data presentations. I cannot point out and answer all questions that may arise from data discovery in a data report, but I can use my data presentation to anticipate those questions.
Here's an example:
I have some data looking at stress levels, energy levels, etc. from six different locations. This data set will likely add more locations as it grows. The story that I want the data to show will be the data trends in each location. At the moment, I'm really not sure the importance of each location and I'm going to predict that importance of locations will change as I continue doing data discovery on this set.
Below is an example of a figure that I would add to a data report as a part of a dynamic document (see note below). With six different locations, the figure is kind of busy (and I will probably add more locations in the future)! To follow a location, you really need to outline the location and study it on its own. So I could split this figure into six figures with one location per figure. That's one solution, but if I want to compare it to the other locations I'm left having to deal with flipping between figures. Flipping figures gets messy and I know I have trouble keeping everything straight in my head.
So my solution is to include the above figure in the data report and to create a data dashboard with Shiny where I can highlight selected locations that I can then present later. This allows me to highlight all of the data from the second location to emphasize a point or answer a specific question concerning a specific location with a strong visual.
A plus to creating a Shiny dashboard for use in a presentation is that it can be given to your stakeholders to interact with at a later date. You can host Shiny apps through Shiny itself or create your own Shiny server. Hosting apps through Shiny usually makes them public and is limited to the number of apps you can host (unless you pay to use Shiny's cloud services). If you have your own hardware or use another cloud service, you can create your own Shiny server and host your apps from there. I choose the latter because I enjoy having admin rights.
Note: Dynamic documents are incredibly important for all data, but are especially important to data that will grow. I can create a single word document/HTML/presentation that will change all of my figures as new data is integrated (plus add my own unseen notes <- everybody should make dynamic documents).
SNID BITS of CODE:
I use the following function to create figures with shared legends. I found this off of stackoverflow:
grid_arrange_shared_legend <- function(...) {
plots <- list(...)
g <- ggplotGrob(plots[[1]] + theme(legend.position="bottom"))$grobs
legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
lheight <- sum(legend$height)
grid.arrange(
do.call(arrangeGrob, lapply(plots, function(x)
x + theme(legend.position="none"))),
legend,
ncol = 1,
heights = unit.c(unit(1, "npc") - lheight, lheight))
}
For my Shiny App, the UI is pretty straight forward:
ui <- shinyUI(fluidPage(
# title
titlePanel(""),
# Conditional sidebars
sidebarLayout(
sidebarPanel(
conditionalPanel(condition="input.conditionedPanels==1",
radioButtons("", label = h3(""),
choices = list("" = 1, "" = 2,
"" = 3, "" = 4),selected = 1)
),
conditionalPanel(condition="input.conditionedPanels==2",
radioButtons("",label=h3(""),
choices = list("" = 1, "" = 2, "" = 3), selected=1)
),
conditionalPanel(condition="input.conditionedPanels==3",
radioButtons("Wellness",label=h3(""),
choices=list(""=1,""=2,""=3,
""=4,""=5,""=6), selected=1)),
conditionalPanel(condition="input.conditionedPanels==4",
radioButtons("",label=h3(""),
choices=list(""=1,""=2,""=3,
""=4,""=5)))
),
# Main panel separated into tabbed conditional panels
mainPanel(
tabsetPanel(type = "tabs",
tabPanel("", value =1, plotOutput("")),
tabPanel("", value=2, plotOutput("")),
tabPanel("Wellness", value=3, plotOutput("WellnessPlot")),
tabPanel("", value=4, plotOutput("")),
id="conditionedPanels"
)
)
)
))
Server (Redacted):
server <- shinyServer(function(input, output) {
# Calling requirements
require(dplyr)
require(gridExtra)
require(grid)
require(ggplot2)
grid_arrange_shared_legend <- function(...) {
...
}
# data calls
wellness<-read.table("../wellness.txt", header=TRUE)
output$WellnessPlot <- renderPlot({
p1 <- ggplot(data= wellness %>% group_by(Test) %>% filter(Test=="Stress_level"), aes(x=Date, y=Ave_score, group=, colour=)) +
geom_line() +
geom_point() +
theme_bw() +
labs(y="Stress Level", x="Date") +
theme(legend.text=element_text(face="bold", size=12)) +
theme(axis.title = element_text(face="bold", size=12)) +
theme(axis.text.x = element_text(face="bold", size=10)) +
theme(axis.text.y = element_text(face="bold", size=10))
p2 <- ggplot(data= wellness %>% group_by(Test) %>% filter(Test=="Perceived_health"), aes(x=Date, y=Ave_score, group=, colour=)) +
geom_line() +
geom_point() +
theme_bw() +
labs(y="Perceived Health", x="Date") +
theme(legend.text=element_text(face="bold", size=12)) +
theme(axis.title = element_text(face="bold", size=12)) +
theme(axis.text.x = element_text(face="bold", size=10)) +
theme(axis.text.y = element_text(face="bold", size=10))
p3 <- ggplot(data= wellness %>% group_by(Test) %>% filter(Test=="Energy_level"), aes(x=Date, y=Ave_score, group=, colour=)) +
geom_line() +
geom_point() +
theme_bw() +
labs(y="Energy Level", x="Date") +
theme(legend.text=element_text(face="bold", size=12)) +
theme(axis.title = element_text(face="bold", size=12)) +
theme(axis.text.x = element_text(face="bold", size=10)) +
theme(axis.text.y = element_text(face="bold", size=10))
p4 <- ggplot(data= wellness %>% group_by(Test) %>% filter(Test=="SatisfiedwHealth"), aes(x=Date, y=Ave_score, group=, colour=)) +
geom_line() +
geom_point() +
theme_bw() +
labs(y="% Satisfied w/ health", x="Date") +
theme(legend.text=element_text(face="bold", size=12)) +
theme(axis.title = element_text(face="bold", size=12)) +
theme(axis.text.x = element_text(face="bold", size=10)) +
theme(axis.text.y = element_text(face="bold", size=10))
if(input$Wellness == 1) {
p1 <- p1 + geom_line(data=wellness %>% group_by(Test) %>% filter(Test=="Stress_level" & Location==""),size =3)
p2 <- p2 + geom_line(data=wellness %>% group_by(Test) %>% filter(Test=="Perceived_health" & Location==""), size =3)
p3 <- p3 + geom_line(data=wellness %>% group_by(Test) %>% filter(Test=="Energy_level" & Location==""), size =3)
p4 <- p4 + geom_line(data=wellness %>% group_by(Test) %>% filter(Test=="SatisfiedwHealth" & Location==""),size =3)
grid_arrange_shared_legend(p1,p2,p3,p4)
} else if (input$Wellness == 2) {
...
} else if (input$Wellness == 3) {
...
} else if( input$Wellness == 4) {
...
} else if (input$Wellness == 5) {
...
} else {
...
}
})
})