cjerzak commited on
Commit
f02e31c
·
verified ·
1 Parent(s): 9cbee06

Update app.R

Browse files
Files changed (1) hide show
  1. app.R +90 -100
app.R CHANGED
@@ -1,122 +1,112 @@
1
- # app.R
2
-
3
- # Load necessary libraries
4
  library(shiny)
5
- library(readr) # for reading CSVs
6
- library(dplyr) # for data manipulation
7
- library(ggplot2) # for plotting
8
- library(DT) # for rendering data tables interactively
 
 
 
 
9
 
10
- # Define UI
11
- ui <- fluidPage(
12
-
13
- # Title of the application
14
- titlePanel("Country Representation Explorer"),
15
-
16
- # Sidebar layout
17
- sidebarLayout(
18
- sidebarPanel(
19
- # Input: Select which representation metric to visualize
20
- selectInput(
21
- inputId = "metric",
22
- label = "Choose representation metric:",
23
- choices = c("Overall", "Representation Gap", "Ethnicity",
24
- "Gender", "Religion", "Language"),
25
- selected = "Overall"
26
- ),
27
-
28
- # Input: Numeric slider to filter based on the chosen metric
29
- sliderInput(
30
- inputId = "metricRange",
31
- label = "Filter countries by metric range:",
32
- min = -10, # set a plausible minimum range
33
- max = 10, # set a plausible maximum range
34
- value = c(-10, 10),
35
- step = 0.1
36
- ),
37
-
38
- # Checkbox to toggle data table
39
- checkboxInput(
40
- inputId = "showDataTable",
41
- label = "Show data table of filtered results",
42
- value = TRUE
43
- )
44
  ),
45
-
46
- # Main panel to display outputs
47
- mainPanel(
48
- # Output: Bar plot
49
- plotOutput("repPlot", height = "600px"),
50
-
51
- # Output: Data table (shown only when checkbox is TRUE)
52
- conditionalPanel(
53
- condition = "input.showDataTable == true",
54
- DTOutput("tableOut")
 
 
 
 
 
 
 
 
 
55
  )
56
  )
57
  )
58
  )
59
 
60
- # Define server logic
 
 
61
  server <- function(input, output, session) {
62
 
63
- # Read in the CSV
64
- # Make sure your 'CountryRepresentationRankings.csv' file is in the same folder as this script
65
- full_data <- reactive({
66
- read_csv("CountryRepresentationRankings.csv", show_col_types = FALSE)
 
 
 
67
  })
68
 
69
- # Reactive subset of the data based on the metric range selected
70
- filtered_data <- reactive({
71
- req(input$metricRange)
72
- req(input$metric)
73
-
74
- # Ensure data is loaded
75
- data <- full_data()
 
 
 
 
 
76
 
77
- # Filter based on user-selected metric range
78
- data %>%
79
- filter(
80
- # get() dynamically selects the column name based on input$metric
81
- get(input$metric) >= input$metricRange[1] &
82
- get(input$metric) <= input$metricRange[2]
83
- )
84
  })
85
 
86
- # Render the bar plot
87
- output$repPlot <- renderPlot({
88
- data_for_plot <- filtered_data()
89
 
90
- # Proceed only if there's data to plot
91
- validate(
92
- need(nrow(data_for_plot) > 0, "No data available within this range.")
93
- )
 
94
 
95
- # Order countries by the chosen metric
96
- ggplot(data_for_plot, aes(
97
- x = reorder(Country, get(input$metric)),
98
- y = get(input$metric)
99
- )) +
100
- geom_col(fill = "steelblue") +
101
- coord_flip() + # Flip coordinates for easier reading of country names
102
  labs(
103
- x = "Country",
104
- y = paste(input$metric, "Index"),
105
- title = paste("Countries by", input$metric, "Representation")
 
106
  ) +
107
- theme_minimal(base_size = 14)
108
- })
109
-
110
- # Render the data table (only if checkbox is selected)
111
- output$tableOut <- renderDT({
112
- data_for_table <- filtered_data()
113
- datatable(
114
- data_for_table,
115
- options = list(pageLength = 10, autoWidth = TRUE),
116
- rownames = FALSE
117
- )
118
  })
119
  }
120
 
121
- # Create Shiny app
122
- shinyApp(ui, server)
 
 
 
1
+ # =============================
2
+ # Global options & libraries
3
+ # =============================
4
  library(shiny)
5
+ library(shinydashboard) # or bslib / thematic, if desired
6
+ library(dplyr)
7
+ library(readr)
8
+ library(sf)
9
+ library(cartogram)
10
+ library(ggplot2)
11
+ library(rnaturalearth)
12
+ library(rnaturalearthdata)
13
 
14
+ # =============================
15
+ # UI
16
+ # =============================
17
+ ui <- dashboardPage(
18
+ dashboardHeader(title = "Country Representation Rankings"),
19
+ dashboardSidebar(
20
+ sidebarMenu(
21
+ menuItem("Cartogram", tabName = "cartogramTab", icon = icon("globe"))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  ),
23
+ # User input: which representation index to display
24
+ selectInput(
25
+ inputId = "indexChoice",
26
+ label = "Select Representation Index:",
27
+ choices = c("Overall", "Representation Gap", "Ethnicity",
28
+ "Gender", "Religion", "Language"),
29
+ selected = "Overall"
30
+ )
31
+ ),
32
+ dashboardBody(
33
+ tabItems(
34
+ tabItem(
35
+ tabName = "cartogramTab",
36
+ fluidRow(
37
+ box(
38
+ width = 12,
39
+ plotOutput("cartogramPlot", height = "600px")
40
+ )
41
+ )
42
  )
43
  )
44
  )
45
  )
46
 
47
+ # =============================
48
+ # SERVER
49
+ # =============================
50
  server <- function(input, output, session) {
51
 
52
+ # ---- Read CSV data ----
53
+ # Modify the path to your CSV as needed
54
+ rankings_data <- reactive({
55
+ read_csv("CountryRepresentationRankings.csv") %>%
56
+ # Make sure "Country" and "Population" columns are present:
57
+ # e.g., rename columns if your CSV differs
58
+ rename(name = Country) # rename to match natural earth "name" field
59
  })
60
 
61
+ # ---- Read/prepare world map shapefile ----
62
+ world_sf <- reactive({
63
+ # Download a simple polygons set
64
+ ne_countries(scale = "medium", returnclass = "sf") %>%
65
+ select(name, iso_a3, geometry) # keep only relevant columns
66
+ })
67
+
68
+ # ---- Join data and create cartogram ----
69
+ cartogram_sf <- reactive({
70
+ # Join your data on "name"
71
+ merged_sf <- world_sf() %>%
72
+ left_join(rankings_data(), by = "name")
73
 
74
+ # cartogram_cont scales polygon area proportionally to your "Population" column
75
+ # If you do NOT have a "Population" column, you could use "pop_est" from
76
+ # the natural earth data or from your CSV if provided.
77
+ cartogram_cont(merged_sf, weight = "Population", prepare = TRUE)
 
 
 
78
  })
79
 
80
+ # ---- Plot output ----
81
+ output$cartogramPlot <- renderPlot({
82
+ req(input$indexChoice)
83
 
84
+ # The user’s chosen index to display
85
+ index_col <- input$indexChoice
86
+
87
+ # Prepare the cartogram for plotting
88
+ plot_data <- cartogram_sf()
89
 
90
+ # Basic ggplot: color fill by the chosen index
91
+ ggplot(plot_data) +
92
+ geom_sf(aes_string(fill = index_col), color = "grey20", size = 0.1) +
93
+ scale_fill_viridis_c(option = "D", na.value = "white") +
94
+ theme_minimal(base_size = 14) +
 
 
95
  labs(
96
+ fill = paste(index_col, "Index"),
97
+ title = "Country Representation Rankings",
98
+ subtitle = "Cartogram sized by Population, colored by selected Index",
99
+ caption = "Source: Global Leadership Project (GLP)"
100
  ) +
101
+ theme(
102
+ plot.title = element_text(face = "bold"),
103
+ axis.text = element_blank(),
104
+ axis.ticks = element_blank()
105
+ )
 
 
 
 
 
 
106
  })
107
  }
108
 
109
+ # =============================
110
+ # Launch the Shiny App
111
+ # =============================
112
+ shinyApp(ui = ui, server = server)