Created
March 6, 2025 21:30
-
-
Save gadenbuie/54dd3b683f5554f19159ee05992c51fc to your computer and use it in GitHub Desktop.
shiny cows
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library(shiny) | |
library(bslib) | |
library(dplyr) | |
library(ggplot2) | |
# Sample cow data | |
cow_data <- data.frame( | |
name = c("Bessie", "Daisy", "Buttercup", "Molly", "Clover", "Rosie", "Bella", "Penny", "Lulu", "Mabel"), | |
breed = c("Holstein", "Jersey", "Angus", "Hereford", "Guernsey", "Simmental", "Holstein", "Jersey", "Angus", "Guernsey"), | |
milk_per_day = c(28, 25, 0, 0, 27, 0, 30, 24, 0, 26), | |
weight_kg = c(680, 450, 750, 720, 470, 780, 650, 430, 730, 460), | |
age_years = c(5, 4, 6, 7, 3, 8, 4, 5, 6, 3), | |
is_dairy = c(TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) | |
) | |
ui <- page_navbar( | |
title = "Fun with Cows! 🐄", | |
theme = | |
# Pick a dark green color for the navbar background (see below for grass image) | |
bs_theme( | |
navbar_bg = "#314000", | |
primary = "#6E4D1D", # Brown like a Jersey cow | |
secondary = "#D6C5AB", # Light tan like a Guernsey cow | |
success = "#27422B", # Rich green like a pasture | |
"enable-shadows" = TRUE, | |
"body-bg" = "#F8F7F3" # Creamy background like milk | |
), | |
# First tab - Cow Facts | |
nav_panel( | |
title = "Cow Facts", | |
# Use a grass image for the navbar background | |
tags$style(HTML( | |
".navbar { | |
background-image: url('grass.jpg'); | |
background-size: cover; | |
background-position: center; | |
}" | |
)), | |
layout_columns( | |
fill = FALSE, | |
value_box( | |
title = "Number of Cows", | |
value = nrow(cow_data), | |
showcase = bsicons::bs_icon("clipboard-data"), | |
theme = "primary" | |
), | |
value_box( | |
title = "Average Milk (dairy cows)", | |
value = paste(round(mean(cow_data$milk_per_day[cow_data$is_dairy]), 1), "liters/day"), | |
showcase = bsicons::bs_icon("cup-hot"), | |
theme = "info" | |
), | |
value_box( | |
title = "Average Weight", | |
value = paste(round(mean(cow_data$weight_kg), 1), "kg"), | |
showcase = bsicons::bs_icon("rulers"), | |
theme = "success" | |
) | |
), | |
card( | |
card_header("Did you know?"), | |
"Cows have nearly 360° panoramic vision, but they have poor depth perception.", | |
"A cow can climb up stairs, but not down because their knees can't bend properly.", | |
"Cows have best friends and can become stressed when separated." | |
), | |
card( | |
card_header("Cow Table"), | |
DT::DTOutput("cow_table") | |
) | |
), | |
# Second tab - Cow Charts | |
nav_panel( | |
title = "Cow Charts", | |
layout_sidebar( | |
sidebar = sidebar( | |
title = "Filter Options", | |
checkboxGroupInput("breed_filter", "Select Breeds:", | |
choices = unique(cow_data$breed), | |
selected = unique(cow_data$breed)), | |
sliderInput("age_filter", "Age Range:", | |
min = min(cow_data$age_years), | |
max = max(cow_data$age_years), | |
value = c(min(cow_data$age_years), max(cow_data$age_years))), | |
checkboxInput("dairy_only", "Dairy Cows Only", FALSE) | |
), | |
card( | |
card_header("Milk Production by Breed"), | |
plotOutput("milk_plot") | |
), | |
card( | |
card_header("Cow Weight Distribution"), | |
plotOutput("weight_plot") | |
) | |
) | |
), | |
# Third tab - Cow Quiz | |
nav_panel( | |
title = "Cow Quiz", | |
card( | |
card_header("Test Your Cow Knowledge!"), | |
radioButtons("q1", "1. How many stomachs does a cow have?", | |
choices = c("1", "2", "4", "6"), | |
selected = character(0)), | |
radioButtons("q2", "2. What is a female cow that has not had a calf called?", | |
choices = c("Calf", "Heifer", "Steer", "Bull"), | |
selected = character(0)), | |
radioButtons("q3", "3. How much water does a cow drink per day on average?", | |
choices = c("5-10 liters", "25-50 liters", "100-150 liters", "More than 200 liters"), | |
selected = character(0)), | |
actionButton("check_answers", "Check Answers", class = "btn-primary"), | |
textOutput("quiz_result") | |
) | |
) | |
) | |
server <- function(input, output, session) { | |
# Cow table | |
output$cow_table <- DT::renderDT({ | |
DT::datatable(cow_data, options = list(pageLength = 5)) | |
}) | |
# Filtered data reactive | |
filtered_data <- reactive({ | |
result <- cow_data %>% | |
filter(breed %in% input$breed_filter, | |
age_years >= input$age_filter[1], | |
age_years <= input$age_filter[2]) | |
if (input$dairy_only) { | |
result <- result %>% filter(is_dairy == TRUE) | |
} | |
return(result) | |
}) | |
# Milk production plot | |
output$milk_plot <- renderPlot({ | |
data <- filtered_data() | |
# Filter to only dairy cows for milk production | |
dairy_cows <- data %>% filter(is_dairy == TRUE) | |
ggplot(dairy_cows, aes(x = breed, y = milk_per_day, fill = breed)) + | |
geom_bar(stat = "summary", fun = "mean") + | |
labs(x = "Breed", y = "Average Milk Production (liters/day)") + | |
theme_minimal() + | |
theme(legend.position = "none") + | |
coord_flip() | |
}) | |
# Weight distribution plot | |
output$weight_plot <- renderPlot({ | |
data <- filtered_data() | |
ggplot(data, aes(x = breed, y = weight_kg, fill = breed)) + | |
geom_boxplot() + | |
labs(x = "Breed", y = "Weight (kg)") + | |
theme_minimal() + | |
theme(legend.position = "none") | |
}) | |
# Quiz logic | |
observeEvent(input$check_answers, { | |
answers <- c("4", "Heifer", "25-50 liters") | |
user_answers <- c(input$q1, input$q2, input$q3) | |
correct <- sum(user_answers == answers, na.rm = TRUE) | |
output$quiz_result <- renderText({ | |
paste("You got", correct, "out of 3 correct!") | |
}) | |
}) | |
} | |
shinyApp(ui, server) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment