Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dodgr_flows_aggregate with argument pairwise #229

Closed
chinhqho opened this issue Jun 5, 2024 · 5 comments
Closed

dodgr_flows_aggregate with argument pairwise #229

chinhqho opened this issue Jun 5, 2024 · 5 comments

Comments

@chinhqho
Copy link

chinhqho commented Jun 5, 2024

Can I request for a new feature: pairwise = TRUE to be included in the newer version of dodgr_flows_aggregate function. Very often, I have a list of O-D pairs that I need find the shortest paths and then aggregate the paths to flows for visualising the results. Currently this function only supports multiple froms to multiple tos , giving a matrix of length(from) * length(to).

@mpadge
Copy link
Member

mpadge commented Jun 5, 2024

@chinhqho That's a great idea, and the above commits show I've already managed to implement it. It's currently still in PR #230, which gives results like this:

library (dodgr)
packageVersion ("dodgr")
#> [1] '0.4.0.6'

graph <- weight_streetnet (hampi)
n <- 20
set.seed (2L)
from <- sample (graph$from_id, size = n)
to <- sample (graph$to_id, size = n)
stopifnot (!to %in% from)
flows <- runif (n)

graph0 <- dodgr_flows_aggregate (graph, from = from, to = to, flows = flows, pairwise = FALSE)
index0 <- which (graph0$flow > 0)
graph1 <- dodgr_flows_aggregate (graph, from = from, to = to, flows = flows, pairwise = TRUE)
index1 <- which (graph1$flow > 0)
message ("num flows for pairwise = (FALSE, TRUE) = (", length (index0), ", ", length (index1), ")")
#> num flows for pairwise = (FALSE, TRUE) = (772, 1299)

library (ggplot2)
dat <- data.frame (
    pairwise = c (rep (FALSE, length (index0)), rep (TRUE, length (index1))),
    flow = c (graph0$flow [index0], graph1$flow [index1])
)
ggplot (dat, aes (x = flow, colour = pairwise)) +
    geom_freqpoly (lwd = 1) +
    theme_minimal () +
    theme (
        legend.position = "inside",
        legend.position.inside = c (0.8, 0.9)
    )
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Created on 2024-06-05 with reprex v2.1.0

And flow aggregation with pairwise = TRUE produces fewer non-zero flows, and edges with flows have lower values on average, as should be expected. I'll just have to implement tests and should be good to merge.

mpadge added a commit that referenced this issue Jun 5, 2024
mpadge added a commit that referenced this issue Jun 5, 2024
@mpadge
Copy link
Member

mpadge commented Jun 5, 2024

Done. Let me know how you go.

@chinhqho
Copy link
Author

chinhqho commented Jun 6, 2024

Thanks heap @mpadge. I have tested the development version 0.4.0.11 which works if froms and tos are both vertex ids. However, the new dodgr_flows_aggregate function does not work if froms and tos are in xy (lat/long) coordinates. A work around solution is to use the match_pts_to_verts function. I can live with that.

remotes::install_github("UrbanAnalyst/dodgr", INSTALL_opts = '--no-lock')
library(dodgr)
library(tictoc)
packageVersion("dodgr") # ‘0.4.0.11’

verts <- dodgr_vertices(sydnet)
n <- 400
verts <- dodgr_vertices(sydnet)
orig_idx <- match_pts_to_verts(verts, xy = head(from, n), connected = FALSE) # an index into verts
dest_idx <- match_pts_to_verts(verts, xy = head(to, n), connected = FALSE) 
orig <- verts$id[orig_idx] # names of vertices
dest <- verts$id[dest_idx]

flows <- rep(1, n) # route individual trip
tic() # 100 routes take 140 seconds 
graph_f <- dodgr_flows_aggregate (sydnet, 
                                  from = orig, to = dest, 
                                  flows = flows, 
                                  pairwise = TRUE, # available in dev version
                                  norm_sums = FALSE) # to get number of trips, not density

(graph_f <- graph_f[graph_f$flow > 0, ])

dodgr_flowmap(graph_f, linescale = 5)
toc() #169 secs for 400 routes

# Then merge directed flows and convert to sf for plotting
f <- merge_directed_graph (graph_f)
geoms <- dodgr_to_sfc (f)
gc <- dodgr_contract_graph (f)
gsf <- sf::st_sf (geoms)
gsf$flow <- gc$flow
# sf plot:
library(tmap)
gsf %>% tm_shape() + tm_lines("flow", lwd = "flow", scale = 3)

@mpadge
Copy link
Member

mpadge commented Jun 6, 2024

Hmmm... submitting as coordinate matrices should work. I'll re-open to fix that

@mpadge mpadge reopened this Jun 6, 2024
mpadge added a commit that referenced this issue Jun 6, 2024
mpadge added a commit that referenced this issue Jun 6, 2024
mpadge added a commit that referenced this issue Jun 6, 2024
@mpadge
Copy link
Member

mpadge commented Jun 6, 2024

All works now:

library (dodgr)
packageVersion ("dodgr")
#> [1] '0.4.0.14'

graph <- weight_streetnet (hampi, wt_profile = "foot")
v <- dodgr_vertices (graph)
set.seed (1)
n <- 10L
from <- sample (v$id, n)
to <- sample (v$id, n)
flows <- runif (n)
graph_f1 <- dodgr_flows_aggregate (graph, from = from, to = to, flows = flows, pairwise = TRUE)

Then convert to matrix forms:

from <- v [match (from, v$id), c ("x", "y")]
to <- v [match (to, v$id), c ("x", "y")]
graph_f2 <- dodgr_flows_aggregate (graph, from = from, to = to, flows = flows, pairwise = TRUE)

identical (graph_f1, graph_f2)
#> [1] TRUE

Created on 2024-06-06 with reprex v2.1.0

@mpadge mpadge closed this as completed Jun 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants