I am currently creating a RShiny website for a project that models the data for Murder, Assault and Rape in the United States. I've made significant progress so far but I am having trouble with two issues.
I am attempting to implement a for or while loop as part of my project and I'm unable to get the output to be displayed when I run the app. I want the for/while loop to return the states that also shared a Low/Medium/High risk of crime in the form of a text "The other states which have a low/medium/high rate of crime are State1, State2, State3, etc". This is dependent on the state the user selected in the drop down box in the sidebar. I have had no luck in writing the code for this. I understand theres 100% easier ways to do this without a looping structure but my project requires me to use a for or while loop.
How am I able to combine more than one output on a tab panel so that both outputs show. I want there to only be one "How safe is the State?" tab, but whenever I tried to combine both, no outputs would show on the tab.
library(shiny)
library(tidyverse)
library(ggplot2)
# Define UI for application that draws the graphs
ui <- fluidPage(
# Application title
titlePanel("Rate of Crime in United States"),
p("Use the variable selector to refine your search!"),
# Sidebar with widgets adjust server output
sidebarLayout(
sidebarPanel(
checkboxGroupInput("display_var",
"Which Crime/s to Display?",
choices = c("Murder" = "Murder",
"Assault" = "Assault",
"Rape" = "Rape"),
selected = "Murder"
),
sliderInput("bins",
"Number of bins (valid for Histogram chart only):",
min = 5,
max = 10,
value = 7
),
selectInput(
"search", "How safe is this state?", choices = (attributes(USArrests)$row.names), selected = NULL)
),
# Create the tabs
mainPanel(
tabsetPanel(
tabPanel("Bar Plot", plotOutput("barplot")),
tabPanel("Histogram", plotOutput("distPlot")),
tabPanel("How Safe is the State?", textOutput("howsafe")),
tabPanel("How Safe is the State?pt2", textOutput("howsafe2"))
)
)
))
# Define server logic required to draw graphs
server <- function(input, output) {
output$barplot <- renderPlot({
marchoice <- req(input$display_var)
sd <- setdiff(names(USArrests),marchoice)
temp_df <- USArrests
temp_df[,sd] <- 0
counts <- temp_df$Murder temp_df$Assault temp_df$Rape
names(counts) <- rownames(temp_df)
barplot(counts,
main="Aggregate Sum of Crime in the United States",
xlab="State",
ylab="Frequency",las=2,col=rgb(0.2,0.4,0.6,0.6))
})
#Transform numeric variables into categorical
CategorisedMAR <- cut(USArrests$Murder USArrests$Assault USArrests$Rape, breaks=c(0,150,300,450), labels = c("Low", "Medium", "High"))
names(CategorisedMAR) <- attributes(USArrests)$row.names
st <- reactive(input$search)
output$howsafe <- renderText({
#if-else statement to state risk based on state selection
if (CategorisedMAR[[input$search]] == "Low") {
paste0(st(), " has a low rate of crime")
} else if (CategorisedMAR[[input$search]] == "Medium") {
paste0( st()," has a mid-level rate of crime")
} else if (CategorisedMAR[[input$search]] == "High") {
paste0( st(), " has a high rate of crime")
}
})
output$howsafe2 <- renderText({
for(value in CategorisedMAR) {
if(value == "Low") {
print(value)}
}
})
output$distPlot <- renderPlot({
#Create new data based on the selection
USArrests2 <-
USArrests %>%
select(!!input$display_var) %>%
mutate(cumulative_frequency = rowSums(across(where(is.numeric))))
# Create plot - Show the cumulative frequency
ggplot(USArrests2, aes(cumulative_frequency)) ggtitle("Histogram of Variable Frequency")
theme(plot.title = element_text(hjust = 0.5))
geom_histogram(bins = input$bins,
fill = rgb(0.2,0.4,0.6,0.6),
colour = "grey30")
#Create a new label based on what has been selected
xlab(str_c(input$display_var, collapse = " & "))
theme_minimal()
})
}
# Run the application
shinyApp(ui = ui, server = server)
This is the code that I have built so far. I have also attached a photo detailing what I am trying to achieve for clarity. "reprex of what I am trying to achieve
I have spent countless days working on this and any help would be greatly appreciated. Thanks in advance!
CodePudding user response:
Perhaps this will do
library(shiny)
library(tidyverse)
library(ggplot2)
library(DT)
# Define UI for application that draws the graphs
ui <- fluidPage(
# Application title
titlePanel("Rate of Crime in United States"),
p("Use the variable selector to refine your search!"),
# Sidebar with widgets adjust server output
sidebarLayout(
sidebarPanel(
checkboxGroupInput("display_var",
"Which Crime/s to Display?",
choices = c("Murder" = "Murder",
"Assault" = "Assault",
"Rape" = "Rape"),
selected = "Murder"
),
sliderInput("bins",
"Number of bins (valid for Histogram chart only):",
min = 5,
max = 10,
value = 7
),
selectInput( "search", "How safe is this state?", choices = (attributes(USArrests)$row.names), selected = NULL)
),
# Create the tabs
mainPanel(
tabsetPanel(
tabPanel("Bar Plot", plotOutput("barplot")),
tabPanel("Histogram", plotOutput("distPlot")),
tabPanel("How Safe is the State?", textOutput("howsafe"), br(),br(), textOutput("howsafe2"))
)
)
))
# Define server logic required to draw graphs
server <- function(input, output) {
output$barplot <- renderPlot({
marchoice <- req(input$display_var)
sd <- setdiff(names(USArrests),marchoice)
temp_df <- USArrests
temp_df[,sd] <- 0
counts <- temp_df$Murder temp_df$Assault temp_df$Rape
names(counts) <- rownames(temp_df)
barplot(counts,
main="Aggregate Sum of Crime in the United States",
xlab="State",
ylab="Frequency",las=2,col=rgb(0.2,0.4,0.6,0.6))
})
#Transform numeric variables into categorical
labels = c("Low", "Medium", "High")
CategorisedMAR <- cut(USArrests$Murder USArrests$Assault USArrests$Rape, breaks=c(0,150,300,450), labels = labels)
names(CategorisedMAR) <- attributes(USArrests)$row.names
st <- reactive(input$search)
output$howsafe <- renderText({
#if-else statement to state risk based on state selection
if (CategorisedMAR[[input$search]] == "Low") {
paste0(st(), " has a low rate of crime")
} else if (CategorisedMAR[[input$search]] == "Medium") {
paste0( st()," has a mid-level rate of crime")
} else if (CategorisedMAR[[input$search]] == "High") {
paste0( st(), " has a high rate of crime")
}
})
output$howsafe2 <- renderText({
myvalue = CategorisedMAR[[input$search]]
n <- length(CategorisedMAR)
list_states <- c()
for (i in 1:n){
if (CategorisedMAR[[i]]==myvalue) list_states <- c(list_states,names(CategorisedMAR)[i])
}
mylist <- list_states[! list_states %in% st()]
a <- paste0(c("The following states also had", tolower(labels[myvalue]),"rate of crime:"), collapse=" ")
b <- paste0(paste(c(a,mylist), collapse=", "),".")
aa <- gsub(":,",":", b)
paste(aa)
})
output$distPlot <- renderPlot({
#Create new data based on the selection
USArrests2 <-
USArrests %>%
dplyr::select(input$display_var) %>%
mutate(cumulative_frequency = rowSums(across(where(is.numeric))))
# Create plot - Show the cumulative frequency
ggplot(USArrests2, aes(cumulative_frequency)) ggtitle("Histogram of Variable Frequency")
theme(plot.title = element_text(hjust = 0.5))
geom_histogram(bins = input$bins,
fill = rgb(0.2,0.4,0.6,0.6),
colour = "grey30")
#Create a new label based on what has been selected
xlab(str_c(input$display_var, collapse = " & "))
theme_minimal()
})
}
# Run the application
shinyApp(ui = ui, server = server)