Spaces:
Running
Running
| # setwd("~/Downloads") | |
| { | |
| # app.R | |
| options(error = NULL) | |
| # ------------------------------ | |
| # 1. Load Packages | |
| # ------------------------------ | |
| library(shiny) | |
| library(shinydashboard) | |
| library(leaflet) | |
| library(raster) | |
| library(DT) | |
| library(readr) | |
| library(dplyr) # For data manipulation | |
| library(ggplot2) # For histogram | |
| library(RColorBrewer) | |
| # ------------------------------ | |
| # 2. Data & Config | |
| # ------------------------------ | |
| # Define time periods corresponding to each band in the GeoTIFF | |
| time_periods <- c("1990β1992", "1993β1995", "1996β1998", "1999β2001", "2002β2004", | |
| "2005β2007", "2008β2010", "2011β2013", "2014β2016", "2017β2019") | |
| # Load GeoTIFF data | |
| wealth_stack <- stack("wealth_map.tif") | |
| # Clean up out-of-range values | |
| wealth_stack[wealth_stack <= 0 | wealth_stack > 1] <- NA | |
| # Load improvement data | |
| improvement_data <- read_csv("poverty_improvement_by_state.csv") | |
| # ------------------------------ | |
| # 3. UI | |
| # ------------------------------ | |
| ui <- dashboardPage( | |
| # -- Header | |
| dashboardHeader(title = "Africa Living Conditions Explorer"), | |
| # -- Sidebar | |
| dashboardSidebar( | |
| sidebarMenu(id = "tabs", | |
| menuItem("Wealth Map", tabName = "mapTab", icon = icon("map")), | |
| menuItem("Improvement Data", tabName = "improvementTab", icon = icon("table")) | |
| ), | |
| # Show inputs only for the map tab | |
| conditionalPanel( | |
| condition = "input.tabs == 'mapTab'", | |
| br(), | |
| selectInput("time_period", "Select Time Period:", | |
| choices = time_periods, | |
| selected = time_periods[1] # Load the first time period by default | |
| ), | |
| selectInput("color_palette", "Select Color Palette:", | |
| choices = c("Viridis" = "viridis", | |
| "Plasma" = "plasma", | |
| "Magma" = "magma", | |
| "Inferno"= "inferno", | |
| "Spectral (Brewer)" = "Spectral"), | |
| selected = "viridis"), | |
| sliderInput("opacity", "Map Opacity:", min = 0.2, max = 1, value = 0.8, step = 0.1) | |
| # Removed the 'Update Map' button | |
| ) | |
| ), | |
| # -- Body | |
| dashboardBody( | |
| tabItems( | |
| # ---------- MAP TAB ---------- | |
| tabItem( | |
| tabName = "mapTab", | |
| fluidRow( | |
| # Value Boxes across the top for key stats | |
| valueBoxOutput("highest_iwi_vb", width = 4), | |
| valueBoxOutput("lowest_iwi_vb", width = 4), | |
| valueBoxOutput("avg_iwi_vb", width = 4) | |
| ), | |
| fluidRow( | |
| # Map | |
| box( | |
| title = "Wealth Map of Africa", width = 8, solidHeader = TRUE, status = "primary", | |
| leafletOutput("map", height = "550px") | |
| ), | |
| # Histogram | |
| box( | |
| title = "IWI Distribution (Selected Period)", width = 4, solidHeader = TRUE, status = "info", | |
| plotOutput("iwi_histogram", height = "250px"), | |
| p("This histogram shows the distribution of the International Wealth Index (IWI) values for the selected time period across Africa.") | |
| ) | |
| ) | |
| ), | |
| # ---------- IMPROVEMENT DATA TAB ---------- | |
| tabItem( | |
| tabName = "improvementTab", | |
| fluidRow( | |
| box( | |
| width = 12, title = "Poverty Improvement by State", status = "primary", solidHeader = TRUE, | |
| p("This table shows the estimated improvement in mean IWI between 1990β1992 and 2017β2019 for each province in Africa. | |
| The 'Improvement' column indicates the change in IWI over this period. You can sort or filter the table, | |
| and use the download button to export the data."), | |
| downloadButton("download_data", "Download CSV", icon = icon("download")), | |
| br(), br(), | |
| DTOutput("improvement_table") | |
| ) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ) | |
| # ------------------------------ | |
| # 4. Server | |
| # ------------------------------ | |
| server <- function(input, output, session) { | |
| # ---------------------------------- | |
| # Reactive expression for selected raster layer | |
| # ---------------------------------- | |
| selected_raster <- reactive({ | |
| req(input$time_period) | |
| band_index <- which(time_periods == input$time_period) | |
| wealth_stack[[band_index]] | |
| }) | |
| # ---------------------------------- | |
| # Custom color palette function | |
| # (reactive to user-selected palette) | |
| # ---------------------------------- | |
| color_pal <- reactive({ | |
| palette_choice <- switch( | |
| input$color_palette, | |
| "viridis" = "viridis", | |
| "plasma" = "plasma", | |
| "magma" = "magma", | |
| "inferno" = "inferno", | |
| # Fallback to a Brewer palette for "Spectral" | |
| "Spectral" = "Spectral" | |
| ) | |
| colorNumeric( | |
| palette = palette_choice, | |
| domain = c(0, 1), | |
| na.color = "transparent" | |
| ) | |
| }) | |
| # ---------------------------------- | |
| # 1. MAP OUTPUT | |
| # ---------------------------------- | |
| output$map <- renderLeaflet({ | |
| leaflet() %>% | |
| addProviderTiles(providers$OpenStreetMap) %>% | |
| setView(lng = 20, lat = 0, zoom = 3) %>% # Center on Africa | |
| addLegend( | |
| pal = color_pal(), | |
| values = c(1, 0), | |
| bins = 2, | |
| title = "IWI", | |
| position = "bottomright", | |
| labFormat = labelFormat( | |
| prefix = "", | |
| suffix = "", | |
| between = " – ", | |
| digits = 3, | |
| big.mark = "," | |
| ) | |
| ) | |
| }) | |
| # Any time one of the controls changes, redraw the raster | |
| observe({ | |
| req(input$time_period, input$color_palette, input$opacity) | |
| leafletProxy("map") %>% | |
| clearImages() %>% | |
| addRasterImage( | |
| selected_raster(), | |
| colors = color_pal(), | |
| opacity = input$opacity, | |
| project = TRUE | |
| ) | |
| }) | |
| # ---------------------------------- | |
| # 2. HISTOGRAM OUTPUT | |
| # ---------------------------------- | |
| output$iwi_histogram <- renderPlot({ | |
| # Extract raster values for histogram | |
| r_vals <- values(selected_raster()) | |
| r_vals <- r_vals[!is.na(r_vals)] | |
| ggplot(data.frame(iwi = r_vals), aes(x = iwi)) + | |
| geom_histogram(binwidth = 0.02, fill = "#2c7bb6", color = "white", alpha = 0.7) + | |
| labs(x = "IWI (0 to 1)", y = "Frequency") + | |
| theme_minimal(base_size = 14) | |
| }) | |
| # ---------------------------------- | |
| # 3. VALUE BOXES FOR KEY STATS | |
| # ---------------------------------- | |
| # Compute stats for current raster | |
| raster_stats <- reactive({ | |
| r_vals <- values(selected_raster()) | |
| r_vals <- r_vals[!is.na(r_vals)] | |
| list( | |
| highest = max(r_vals, na.rm = TRUE), | |
| lowest = min(r_vals, na.rm = TRUE), | |
| average = mean(r_vals, na.rm = TRUE) | |
| ) | |
| }) | |
| # Highest IWI | |
| output$highest_iwi_vb <- renderValueBox({ | |
| valueBox( | |
| value = round(raster_stats()$highest, 3), | |
| subtitle = "Highest IWI", | |
| icon = icon("arrow-up"), | |
| color = "green" | |
| ) | |
| }) | |
| # Lowest IWI | |
| output$lowest_iwi_vb <- renderValueBox({ | |
| valueBox( | |
| value = round(raster_stats()$lowest, 3), | |
| subtitle = "Lowest IWI", | |
| icon = icon("arrow-down"), | |
| color = "red" | |
| ) | |
| }) | |
| # Average IWI | |
| output$avg_iwi_vb <- renderValueBox({ | |
| valueBox( | |
| value = round(raster_stats()$average, 3), | |
| subtitle = "Average IWI", | |
| icon = icon("balance-scale"), | |
| color = "blue" | |
| ) | |
| }) | |
| # ---------------------------------- | |
| # 4. IMPROVEMENT DATA TABLE | |
| # ---------------------------------- | |
| output$improvement_table <- renderDT({ | |
| datatable( | |
| improvement_data, | |
| filter = "top", | |
| options = list( | |
| scrollX = TRUE, | |
| pageLength = 20, | |
| autoWidth = TRUE | |
| ) | |
| ) | |
| }) | |
| # Download CSV | |
| output$download_data <- downloadHandler( | |
| filename = function() { | |
| paste0("poverty_improvement_", Sys.Date(), ".csv") | |
| }, | |
| content = function(file) { | |
| write.csv(improvement_data, file, row.names = FALSE) | |
| } | |
| ) | |
| } | |
| # ------------------------------ | |
| # 5. Run the App | |
| # ------------------------------ | |
| shinyApp(ui = ui, server = server) | |
| } |