|
|
|
|
|
library(shiny) |
|
library(dplyr) |
|
library(ggplot2) |
|
library(data.table) |
|
|
|
ui <- fluidPage( |
|
titlePanel("Country Representation Rankings Explorer"), |
|
|
|
sidebarLayout( |
|
sidebarPanel( |
|
h4("Controls"), |
|
selectInput( |
|
inputId = "metric", |
|
label = "Select a Representation Metric:", |
|
choices = c( |
|
"Overall", |
|
"Representation Gap", |
|
"Ethnicity", |
|
"Gender", |
|
"Religion", |
|
"Language" |
|
), |
|
selected = "Overall" |
|
), |
|
checkboxInput( |
|
inputId = "sort_desc", |
|
label = "Sort in descending order", |
|
value = TRUE |
|
), |
|
hr(), |
|
sliderInput( |
|
inputId = "top_n", |
|
label = "Number of Countries to Display in Plot:", |
|
min = 5, |
|
max = 50, |
|
value = 10, |
|
step = 1 |
|
) |
|
), |
|
|
|
mainPanel( |
|
tabsetPanel( |
|
tabPanel( |
|
title = "Plot", |
|
plotOutput("bar_plot", height = "600px") |
|
), |
|
tabPanel( |
|
title = "Data Table", |
|
DTOutput("data_table") |
|
), |
|
tabPanel( |
|
title = "Summary", |
|
verbatimTextOutput("summary_text") |
|
) |
|
) |
|
) |
|
) |
|
) |
|
|
|
server <- function(input, output, session) { |
|
|
|
|
|
data_raw <- reactive({ |
|
read.csv("CountryRepresentationRankings.csv", stringsAsFactors = FALSE) |
|
}) |
|
|
|
|
|
data_prepared <- reactive({ |
|
req(data_raw()) |
|
|
|
df <- tibble::as_tibble(data_raw()) |
|
|
|
|
|
|
|
|
|
df <- df %>% |
|
mutate( |
|
across(all_of(input$metric), as.numeric) |
|
) %>% |
|
filter(!is.na(.data[[input$metric]])) |
|
|
|
|
|
if (input$sort_desc) { |
|
df <- df %>% arrange(desc(.data[[input$metric]])) |
|
} else { |
|
df <- df %>% arrange(.data[[input$metric]]) |
|
} |
|
|
|
|
|
df <- df %>% slice_head(n = input$top_n) |
|
|
|
df |
|
}) |
|
|
|
|
|
output$bar_plot <- renderPlot({ |
|
df <- data_prepared() |
|
|
|
|
|
df <- df %>% |
|
mutate(Country = factor(Country, levels = Country)) |
|
|
|
ggplot(df, aes(x = Country, y = .data[[input$metric]])) + |
|
geom_col(fill = "steelblue") + |
|
coord_flip() + |
|
labs( |
|
x = "Country", |
|
y = paste0(input$metric, " Index"), |
|
title = paste("Top", input$top_n, "Countries by", input$metric) |
|
) + |
|
theme_minimal(base_size = 14) |
|
}) |
|
|
|
|
|
output$data_table <- renderDT({ |
|
req(data_raw()) |
|
datatable( |
|
data_raw(), |
|
options = list(pageLength = 10, autoWidth = TRUE), |
|
filter = "top", |
|
rownames = FALSE |
|
) |
|
}) |
|
|
|
|
|
output$summary_text <- renderPrint({ |
|
df <- data_raw() |
|
req(df) |
|
|
|
df[[input$metric]] <- suppressWarnings(as.numeric(df[[input$metric]])) |
|
|
|
valid_metric <- df[[input$metric]][!is.na(df[[input$metric]])] |
|
if (length(valid_metric) == 0) { |
|
cat("No valid numeric data for the selected metric.") |
|
} else { |
|
summary_stats <- summary(valid_metric) |
|
cat("Summary of", input$metric, "across all countries:\n") |
|
print(summary_stats) |
|
} |
|
}) |
|
} |
|
|
|
shinyApp(ui = ui, server = server) |
|
|