How is this computed?

A quick look at different approaches

Giorgio Comai https://giorgiocomai.eu (OBCT/EDJNet)https://www.europeandatajournalism.eu/
2021-11-16

Basic example with a medium-sized town - Full intersection

At the most basic, the appoach at the base of the dataset takes all the cells of the population grid that intersects with a given municipality. In the population grid, each cell has a value, that corresponds to an estimate of how many people live within that given square kilometer. If a given cell of the population grid overlaps only partially with a given LAU, then the value of that cell is adjusted proportionally to the overlapping area.

It then calculates a weighted average of the centroids of each cell of the population grid.

As the point is to identify a point close the place where most people live, as an optional additional step, the value for each grid is raised to the power of 2, to “push” the point towards the most densely populated areas rather than in the periphery when, for example, more centres are included within the same municipality.

This is how it plays out in a rather typical town, with most residents clustered in an area, and few living along the administrative boundary.

The centroid points at some location in the mountains, while the population-weighted centre falls nicely into town.

gisco_id <- "IT_007003"

current_lau_sf <- ll_get_lau_eu(gisco_id = gisco_id)

intersect_sf <- ll_get_population_grid(
  year = 2018,
  match_sf = current_lau_sf,
  match_name = stringr::str_c(gisco_id,
                              "lau_2020",
                              "pop_grid_2018",
                              "intersects",
                              sep = "-"),
  join = sf::st_intersects,
  silent = TRUE
)


custom_ll_map_pop_grid(gisco_id = gisco_id,
                       pop_grid_sf = intersect_sf,
                       use_leaflet = TRUE,
                       differentiate = FALSE) 

As highlighted in the original post outlining this method, there are however a number of situations that may complicate things, including poly-centric municipalities, municipalities with non-contiguous territories, islands, coastal areas, etc.

Examples of cases where the centre is not quite right

There are however cases when a large share of the population lives in cells that cut across the administrative boundary line, and it is unclear on which side of the line they live. In larger centres few will live within 1km of the administrative boundaries, but in smaller location this can be an issue.

Let’s look at the small Portuguese municipality of “Urros e Peredo dos Castelhanos” (PT_040921): with a total population of 376 residents, mostly living in one of the two locations that give the municipality its name. It so happens that the neighbouring village of Ligares falls largely into one of the cells cutting the boundary, skewing the population weighted centre (in blue). Notice that, by chance, the centroid - in purple, would be fine in this case.

To reduce the risk that grid cells crossing the boundary skew the result, this repository includes additional datasets, marked as “adjusted_intersection”, that takes the cells crossing the boundary, and divide the value of the population grid according to the surface of that specific cell that actually falls into the boundary. As you see (green pin), the population-weighted centre thus adjusted falls closer to where we’d want it to be. The difference is negligible in the vast majority of cases, but in particular in mountain locations it is not rare to have large municipalities with lots of residents living close to the boundary lines… in such cases, the adjusted approach is very likely preferrable. It may, however, slightly decrease accuracy in some coastal locations, if grid cells with a substantial number of residents include also sea (in principle, this may be adjusted by ignoring the adjustment in coastal locations, but this is not yet included in the current scripts).

gisco_id <- "PT_040921"
current_lau_sf <- ll_get_lau_eu(gisco_id = gisco_id)

intersect_sf <- ll_get_population_grid(
  year = 2018,
  match_sf = current_lau_sf,
  match_name = stringr::str_c(gisco_id,
                              "lau_2020",
                              "pop_grid_2018",
                              "intersects",
                              sep = "-"),
  join = sf::st_intersects,
  silent = TRUE
)


custom_ll_map_pop_grid(gisco_id = gisco_id,
                       pop_grid_sf = intersect_sf,
                       use_leaflet = TRUE) %>% 
  addAwesomeMarkers(data = 
ll_find_pop_centre(sf_location = current_lau_sf,
                   sf_population_grid = intersect_sf,
                   adjusted = TRUE),
                        popup="Adjusted pop-weighted",
                        icon = makeAwesomeIcon(icon = "home",
                                               markerColor = "green",
                                               library="ion"))

Final notes

Alternative solutions for finding the centre include: