UrbanAnalyst / dodgr

Distances on Directed Graphs in R
https://urbananalyst.github.io/dodgr/
127 stars 16 forks source link

how to uncontract graph with new scaling of dodgr_flows #122

Closed mpadge closed 4 years ago

mpadge commented 4 years ago

The dodgr_flows_si and dodgr_flows_aggregate functions have been updated via #121 such that sum(net$flow) will equal the sum of the input origin densities (for dodgr_flows_si), or flow matrix (for dodgr_flows_aggregate). However, when the resultant graphs are uncontracted, these flows are simply allocated to additional intermediate edges, and so the sum of flows across the uncontracted graph will be greater than the sum across the contracted graph, and will no longer equal the desired values.

Simply dividing again by the total sum of flows will not give a correct re-scaling, because values along longer intermediate paths will be lower than they should, and vice-versa. The only appropriate way would be to keep a record in the contracted graph of the number of contracted edges, and to use this value to determine the flow normalisation on the contracted graph. But that still leaves the issue that values on the contracted graph will be categorically different from those on the uncontracted graph. It would seem to ultimately depend on user intentions:

This all seems too abstract to expose to the user interface, although it is ultimately very important. It might at least be argued in the context of OSM data the only "true" domain is that of the contracted graph, because intermediate vertices are effectively arbitrary? Need to ponder this further ...


Reprex to demonstrate the effect:

library(dodgr)
packageVersion ("dodgr")
#> [1] '0.2.5.26'
net <- weight_streetnet (hampi, wt_profile = "foot")
net <- net [net$component == 1, ]
net <- dodgr_contract_graph (net)
v <- dodgr_vertices (net)
set.seed (3)
from <- sample (v$id, 10)
to <- sample (v$id, 10)
#fmat <- array (1, dim = c (10, 10))
fmat <- array (runif (100), dim = c (10, 10))
diag (fmat) <- 0
f <- dodgr_flows_aggregate (net, from, to, flows = fmat)
sum (fmat); sum (f$flow)
#> [1] 43.95693
#> [1] 43.89932
sum (dodgr_uncontract_graph (f)$flow, na.rm = TRUE)
#> [1] 228.2367

Created on 2019-11-12 by the reprex package (v0.3.0)

That second number does not currently mean anything, and is arbitrarily dependent on variable numbers of intermediate edges along each of the contracted edges.

mpadge commented 4 years ago

A bit more food for thought:

library(dodgr)
packageVersion ("dodgr")
#> [1] '0.2.5.27'
net <- weight_streetnet (hampi, wt_profile = "foot")
net <- net [net$component == 1, ]
net <- dodgr_contract_graph (net)
v <- dodgr_vertices (net)
set.seed (3)
from <- sample (v$id, 10)
to <- sample (v$id, 10)
fmat <- array (runif (100), dim = c (10, 10))
diag (fmat) <- 0

f <- dodgr_flows_aggregate (net, from, to, flows = fmat)
message ("sum (flowmat) = ", signif (sum (fmat), 4),
         "; sum flows on graph (", nrow (f), " rows) = ",
         signif (sum (f$flow), 4))
#> sum (flowmat) = 43.96; sum flows on graph (438 rows) = 43.9

fu <- dodgr_uncontract_graph (f)
message ("sum flows on uncontracted graph (", nrow (fu),
         " rows) = ", signif (sum (fu$flow, na.rm = TRUE), 4))
#> sum flows on uncontracted graph (5973 rows) = 228.2

fm <- merge_directed_graph (fu)
message ("sum flows on merged graph (", nrow (fm),
         " rows) = ", signif (sum (fm$flow, na.rm = TRUE), 4))
#> sum flows on merged graph (608 rows) = 228.2

fum <- dodgr_contract_graph (fm)
message ("sum flows on re-contracted merged graph (", nrow (fum),
         " rows) = ", signif (sum (fum$flow, na.rm = TRUE), 4))
#> sum flows on re-contracted merged graph (84 rows) = 34.57

fsf <- dodgr_to_sf (fm)
#> Loading required namespace: sf
message ("sum flows on sf graph (", nrow (fsf),
         " rows) = ", signif (sum (fsf$flow, na.rm = TRUE), 4))
#> sum flows on sf graph (84 rows) = 34.57

Created on 2019-11-12 by the reprex package (v0.3.0)

mpadge commented 4 years ago

There is no resolution to this, and the issue just has to be well documented in the vignette, as has been done in the who3 report on the NYC pedestrian model (under "Flow Layers"). Just have to take that graphic and put it in the flow vignette.