diff --git a/NAMESPACE b/NAMESPACE index 1fe4e0ef..ceb9c5bc 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -125,7 +125,10 @@ export(od_aggregate_to) export(od_coords) export(od_coords2line) export(od_dist) +export(od_id_max_min) export(od_id_order) +export(od_id_szudzik) +export(od_oneway) export(od_radiation) export(od_to_odmatrix) export(odmatrix_to_od) @@ -154,7 +157,6 @@ export(sln2points) export(sp_aggregate) export(sum_network_links) export(sum_network_routes) -export(szudzik_pairing) export(table2matrix) export(toptail_buff) export(toptailgs) diff --git a/R/oneway.R b/R/oneway.R index 141d05d2..0bff27fa 100644 --- a/R/oneway.R +++ b/R/oneway.R @@ -158,56 +158,189 @@ od_id_order <- function(x, id1 = names(x)[1], id2 = names(x)[2]) { ) ) } -#' Combines two ID values to create a single ID number +#' Combine two ID values to create a single ID number #' #' @details -#' In OD data it is common to have many flows from "A to B" and "B to A". +#' In OD data it is common to have many 'oneway' flows from "A to B" and "B to A". #' It can be useful to group these an have a single ID that represents pairs of IDs -#' with or without directionality. +#' with or without directionality, so they contain 'twoway' or bi-directional values. #' -#' This function implements the Szudzik pairing function, on two vectors of equal +#' `od_id*` functions take two vectors of equal length and return a vector of IDs, +#' which are unique for each combination but the same for twoway flows. +#' +#' - the Szudzik pairing function, on two vectors of equal #' length. It returns a vector of ID numbers. #' #' This function superseeds od_id_order as it is faster on large datasets -#' -#' @param val1 a vector of numeric, character, or factor values -#' @param val2 a vector of numeric, character, or factor values +#' @param x a vector of numeric, character, or factor values +#' @param y a vector of numeric, character, or factor values #' @param ordermatters logical, does the order of values matter to pairing, default = FALSE #' +#' @name od_id #' @examples #' -#' szudzik_pairing(od_data_sample[[1]], od_data_sample[[2]]) -#' od_id_order(od_data_sample) +#' head(od_id_order(od_data_sample), 9) +#' od_id_szudzik(od_data_sample[[1]], od_data_sample[[2]]) +#' od_id_max_min(od_data_sample[[1]], od_data_sample[[2]]) #' n = 1000 #' ids <- as.character(runif(n, 1e4, 1e7 - 1)) -#' x <- data.frame(id1 = rep(ids, times = n), -#' id2 = rep(ids, each = n), -#' val = 1, -#' stringsAsFactors = FALSE) -#' system.time(od_id_order(x)) -#' system.time(szudzik_pairing(x$id1, x$id2)) +#' # benchmark of methods: +#' # x <- data.frame(id1 = rep(ids, times = n), +#' # id2 = rep(ids, each = n), +#' # val = 1, +#' # stringsAsFactors = FALSE) +#' # bench::mark( +#' # check = FALSE, +#' # od_id_order(x), +#' # od_id_szudzik(x$id1, x$id2), +#' # od_id_max_min(x$id1, x$id2) +#' # ) +NULL +#' @rdname od_id #' @export -szudzik_pairing <- function(val1, val2, ordermatters = FALSE) { - if(length(val1) != length(val2)){ - stop("val1 and val2 are not of equal length") +od_id_szudzik <- function(x, y, ordermatters = FALSE) { + if(length(x) != length(y)){ + stop("x and y are not of equal length") } - if(class(val1) == "factor"){ - val1 <- as.character(val1) + if(class(x) == "factor"){ + x <- as.character(x) } - if(class(val2) == "factor"){ - val2 <- as.character(val2) + if(class(y) == "factor"){ + y <- as.character(y) } - lvls <- unique(c(val1, val2)) - val1 <- as.integer(factor(val1, levels = lvls)) - val2 <- as.integer(factor(val2, levels = lvls)) + lvls <- unique(c(x, y)) + x <- as.integer(factor(x, levels = lvls)) + y <- as.integer(factor(y, levels = lvls)) if(ordermatters){ - ismax <- val1 > val2 - stplanr.key <- (ismax * 1) * (val1^2 + val1 + val2) + ((!ismax) * 1) * (val2^2 + val1) + ismax <- x > y + stplanr.key <- (ismax * 1) * (x^2 + x + y) + ((!ismax) * 1) * (y^2 + x) }else{ - a <- ifelse(val1 > val2, val2, val1) - b <- ifelse(val1 > val2, val1, val2) + a <- ifelse(x > y, y, x) + b <- ifelse(x > y, x, y) stplanr.key <- b^2 + a } return(stplanr.key) } +#' @export +#' @rdname od_id +od_id_max_min <- function(x, y) { + d <- convert_to_numeric(x, y) + a <- pmax(d$x, d$y) + b <- pmin(d$x, d$y) + a * (a + 1) / 2 + b +} + +convert_to_numeric <- function(x, y) { + if (length(x) != length(y)) stop("x and y are not of equal length") + if (class(x) == "factor") x <- as.character(x) + if (class(y) == "factor") y <- as.character(y) + lvls <- unique(c(x, y)) + x <- as.integer(factor(x, levels = lvls)) + y <- as.integer(factor(y, levels = lvls)) + list(x = x, y = y) +} + +od_id_order_base <- function(x, y) { + d <- convert_to_numeric(x, y) + x <- d$x + y <- d$y + paste(pmin(x, y), pmax(x, y)) +} + +not_duplicated <- function(x) { + !duplicated(x) +} +#' Aggregate od pairs they become non-directional +#' +#' For example, sum total travel in both directions. +#' @param x A data frame or SpatialLinesDataFrame, representing an OD matrix +#' @param attrib A vector of column numbers or names +#' for deciding which attribute(s) of class numeric to +#' aggregate +#' @param id1 Optional (it is assumed to be the first column) +#' text string referring to the name of the variable containing +#' the unique id of the origin +#' @param id2 Optional (it is assumed to be the second column) +#' text string referring to the name of the variable containing +#' the unique id of the destination +#' @return `oneway` outputs a data frame (or `sf` data frame) with rows containing +#' results for the user-selected attribute values that have been aggregated. +#' @family lines +#' @export +#' @details +#' Flow data often contains movement in two directions: from point A to point B +#' and then from B to A. This can be problematic for transport planning, because +#' the magnitude of flow along a route can be masked by flows the other direction. +#' If only the largest flow in either direction is captured in an analysis, for +#' example, the true extent of travel will by heavily under-estimated for +#' OD pairs which have similar amounts of travel in both directions. +#' Flows in both direction are often represented by overlapping lines with +#' identical geometries (see [flowlines()]) which can be confusing +#' for users and are difficult to plot. +#' @examples +#' flow_oneway <- od_oneway(flow, attrib = 3) +#' nrow(flow_oneway) < nrow(flow) # result has fewer rows +#' sum(flow$All) == sum(flow_oneway$All) # but the same total flow +#' # using names instead of index for attribute +#' od_oneway(flow, attrib = "All") +#' # using many attributes to aggregate +#' attrib <- which(vapply(flow, is.numeric, TRUE)) +#' flow_oneway <- od_oneway(flow, attrib = attrib) +#' colSums(flow_oneway[attrib]) == colSums(flow[attrib]) # test if the colSums are equal +#' # Demonstrate the results from oneway and onewaygeo are identical +#' flow_oneway_geo <- onewaygeo(flowlines, attrib = attrib) +#' plot(flow_oneway$All, flow_oneway_geo$All) +#' flow_oneway_sf <- od_oneway(flowlines_sf, 3) +#' plot(flow_oneway_geo, lwd = flow_oneway_geo$All / mean(flow_oneway_geo$All)) +#' plot(flow_oneway_sf$geometry, lwd = flow_oneway_sf$All / mean(flow_oneway_sf$All)) +#' # benchmark performance +#' # bench::mark(check = F, +#' # onewayid(flowlines_sf, 3), +#' # od_oneway(flowlines_sf, 3) +#' # ) +#' @export +od_oneway <- function(x, attrib, id1 = names(x)[1], id2 = names(x)[2]) { + + stplanr.key = od_id_max_min(x[[id1]], x[[id2]]) + + if (is.numeric(attrib)) { + attrib_names <- names(x)[attrib] + } else { + attrib_names <- attrib + attrib <- which(names(x) %in% attrib) + } + + # separate geometry for sf objects + is_sf <- is(x, "sf") + if(is_sf) { + x_sf <- sf::st_sf(data.frame(stplanr.key), geometry = sf::st_geometry(x)) + x <- sf::st_drop_geometry(x) + } + + x <- dplyr::bind_cols(x, stplanr.key = stplanr.key) + + x_oneway_numeric <- dplyr::group_by(x, stplanr.key) %>% + dplyr::summarise_at(attrib, sum) + + x_oneway_character <- x %>% + dplyr::group_by(stplanr.key) %>% + dplyr::summarise(id1 = dplyr::first(!!rlang::sym(id1)), id2 = dplyr::first(!!rlang::sym(id2))) %>% + dplyr::select(-stplanr.key) + + x_oneway <- dplyr::bind_cols( + x_oneway_character, + x_oneway_numeric + ) + + if(is_sf) { + x_sf <- x_sf[!duplicated(x_sf$stplanr.key), ] + x_oneway <- sf::st_as_sf(dplyr::inner_join(x_oneway, x_sf)) + # class(x_oneway) # sf + } + + x_oneway$stplanr.key <- NULL + names(x_oneway)[1:2] <- c(id1, id2) + + return(x_oneway) +} diff --git a/man/angle_diff.Rd b/man/angle_diff.Rd index c699d285..84b85b5c 100644 --- a/man/angle_diff.Rd +++ b/man/angle_diff.Rd @@ -43,9 +43,10 @@ Other lines: \code{\link{geo_toptail}}, \code{\link{line_midpoint}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, - \code{\link{n_vertices}}, \code{\link{onewaygeo}}, - \code{\link{onewayid}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{n_vertices}}, \code{\link{od_oneway}}, + \code{\link{onewaygeo}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/geo_toptail.Rd b/man/geo_toptail.Rd index a815b859..1239ef75 100644 --- a/man/geo_toptail.Rd +++ b/man/geo_toptail.Rd @@ -43,9 +43,10 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_midpoint}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, - \code{\link{n_vertices}}, \code{\link{onewaygeo}}, - \code{\link{onewayid}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{n_vertices}}, \code{\link{od_oneway}}, + \code{\link{onewaygeo}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/is_linepoint.Rd b/man/is_linepoint.Rd index b51bfcb1..f6164569 100644 --- a/man/is_linepoint.Rd +++ b/man/is_linepoint.Rd @@ -33,9 +33,10 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_midpoint}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, - \code{\link{n_vertices}}, \code{\link{onewaygeo}}, - \code{\link{onewayid}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{n_vertices}}, \code{\link{od_oneway}}, + \code{\link{onewaygeo}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/line2df.Rd b/man/line2df.Rd index c42da5aa..9b92259b 100644 --- a/man/line2df.Rd +++ b/man/line2df.Rd @@ -27,9 +27,10 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_midpoint}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, - \code{\link{n_vertices}}, \code{\link{onewaygeo}}, - \code{\link{onewayid}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{n_vertices}}, \code{\link{od_oneway}}, + \code{\link{onewaygeo}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/line_bearing.Rd b/man/line_bearing.Rd index dbf4716b..f55eacff 100644 --- a/man/line_bearing.Rd +++ b/man/line_bearing.Rd @@ -34,9 +34,10 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_midpoint}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, - \code{\link{n_vertices}}, \code{\link{onewaygeo}}, - \code{\link{onewayid}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{n_vertices}}, \code{\link{od_oneway}}, + \code{\link{onewaygeo}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/line_match.Rd b/man/line_match.Rd index 74bede81..155e2375 100644 --- a/man/line_match.Rd +++ b/man/line_match.Rd @@ -41,9 +41,10 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_midpoint}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, - \code{\link{n_vertices}}, \code{\link{onewaygeo}}, - \code{\link{onewayid}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{n_vertices}}, \code{\link{od_oneway}}, + \code{\link{onewaygeo}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/line_midpoint.Rd b/man/line_midpoint.Rd index baf38d66..44edcc4b 100644 --- a/man/line_midpoint.Rd +++ b/man/line_midpoint.Rd @@ -24,9 +24,10 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_match}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, - \code{\link{n_vertices}}, \code{\link{onewaygeo}}, - \code{\link{onewayid}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{n_vertices}}, \code{\link{od_oneway}}, + \code{\link{onewaygeo}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/line_sample.Rd b/man/line_sample.Rd index 9cb208aa..4693bb8f 100644 --- a/man/line_sample.Rd +++ b/man/line_sample.Rd @@ -33,9 +33,10 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_match}}, \code{\link{line_midpoint}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, - \code{\link{n_vertices}}, \code{\link{onewaygeo}}, - \code{\link{onewayid}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{n_vertices}}, \code{\link{od_oneway}}, + \code{\link{onewaygeo}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/line_segment.Rd b/man/line_segment.Rd index bcdce815..e62f7007 100644 --- a/man/line_segment.Rd +++ b/man/line_segment.Rd @@ -30,9 +30,10 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_match}}, \code{\link{line_midpoint}}, \code{\link{line_sample}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, - \code{\link{n_vertices}}, \code{\link{onewaygeo}}, - \code{\link{onewayid}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{n_vertices}}, \code{\link{od_oneway}}, + \code{\link{onewaygeo}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/line_via.Rd b/man/line_via.Rd index b4987fed..5aa96daf 100644 --- a/man/line_via.Rd +++ b/man/line_via.Rd @@ -46,9 +46,10 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_match}}, \code{\link{line_midpoint}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, - \code{\link{n_vertices}}, \code{\link{onewaygeo}}, - \code{\link{onewayid}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{n_vertices}}, \code{\link{od_oneway}}, + \code{\link{onewaygeo}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/mats2line.Rd b/man/mats2line.Rd index 9ecb118e..1a6272cf 100644 --- a/man/mats2line.Rd +++ b/man/mats2line.Rd @@ -33,9 +33,10 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_match}}, \code{\link{line_midpoint}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{n_sample_length}}, - \code{\link{n_vertices}}, \code{\link{onewaygeo}}, - \code{\link{onewayid}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{n_vertices}}, \code{\link{od_oneway}}, + \code{\link{onewaygeo}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/n_sample_length.Rd b/man/n_sample_length.Rd index 24a976a6..2c7e4921 100644 --- a/man/n_sample_length.Rd +++ b/man/n_sample_length.Rd @@ -41,9 +41,10 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_match}}, \code{\link{line_midpoint}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, - \code{\link{n_vertices}}, \code{\link{onewaygeo}}, - \code{\link{onewayid}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{n_vertices}}, \code{\link{od_oneway}}, + \code{\link{onewaygeo}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/n_vertices.Rd b/man/n_vertices.Rd index 677bc50b..ef5c4cc1 100644 --- a/man/n_vertices.Rd +++ b/man/n_vertices.Rd @@ -27,9 +27,10 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_match}}, \code{\link{line_midpoint}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, - \code{\link{n_sample_length}}, \code{\link{onewaygeo}}, - \code{\link{onewayid}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{n_sample_length}}, \code{\link{od_oneway}}, + \code{\link{onewaygeo}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/od_id.Rd b/man/od_id.Rd new file mode 100644 index 00000000..f7cec15a --- /dev/null +++ b/man/od_id.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/oneway.R +\name{od_id} +\alias{od_id} +\alias{od_id_szudzik} +\alias{od_id_max_min} +\title{Combine two ID values to create a single ID number} +\usage{ +od_id_szudzik(x, y, ordermatters = FALSE) + +od_id_max_min(x, y) +} +\arguments{ +\item{x}{a vector of numeric, character, or factor values} + +\item{y}{a vector of numeric, character, or factor values} + +\item{ordermatters}{logical, does the order of values matter to pairing, default = FALSE} +} +\description{ +Combine two ID values to create a single ID number +} +\details{ +In OD data it is common to have many 'oneway' flows from "A to B" and "B to A". +It can be useful to group these an have a single ID that represents pairs of IDs +with or without directionality, so they contain 'twoway' or bi-directional values. + +\code{od_id*} functions take two vectors of equal length and return a vector of IDs, +which are unique for each combination but the same for twoway flows. +\itemize{ +\item the Szudzik pairing function, on two vectors of equal +length. It returns a vector of ID numbers. +} + +This function superseeds od_id_order as it is faster on large datasets +} +\examples{ + +head(od_id_order(od_data_sample), 9) +od_id_szudzik(od_data_sample[[1]], od_data_sample[[2]]) +od_id_max_min(od_data_sample[[1]], od_data_sample[[2]]) +n = 1000 +ids <- as.character(runif(n, 1e4, 1e7 - 1)) +# benchmark of methods: +# x <- data.frame(id1 = rep(ids, times = n), +# id2 = rep(ids, each = n), +# val = 1, +# stringsAsFactors = FALSE) +# bench::mark( +# check = FALSE, +# od_id_order(x), +# od_id_szudzik(x$id1, x$id2), +# od_id_max_min(x$id1, x$id2) +# ) +} diff --git a/man/od_oneway.Rd b/man/od_oneway.Rd new file mode 100644 index 00000000..638e5dc4 --- /dev/null +++ b/man/od_oneway.Rd @@ -0,0 +1,77 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/oneway.R +\name{od_oneway} +\alias{od_oneway} +\title{Aggregate od pairs they become non-directional} +\usage{ +od_oneway(x, attrib, id1 = names(x)[1], id2 = names(x)[2]) +} +\arguments{ +\item{x}{A data frame or SpatialLinesDataFrame, representing an OD matrix} + +\item{attrib}{A vector of column numbers or names +for deciding which attribute(s) of class numeric to +aggregate} + +\item{id1}{Optional (it is assumed to be the first column) +text string referring to the name of the variable containing +the unique id of the origin} + +\item{id2}{Optional (it is assumed to be the second column) +text string referring to the name of the variable containing +the unique id of the destination} +} +\value{ +\code{oneway} outputs a data frame (or \code{sf} data frame) with rows containing +results for the user-selected attribute values that have been aggregated. +} +\description{ +For example, sum total travel in both directions. +} +\details{ +Flow data often contains movement in two directions: from point A to point B +and then from B to A. This can be problematic for transport planning, because +the magnitude of flow along a route can be masked by flows the other direction. +If only the largest flow in either direction is captured in an analysis, for +example, the true extent of travel will by heavily under-estimated for +OD pairs which have similar amounts of travel in both directions. +Flows in both direction are often represented by overlapping lines with +identical geometries (see \code{\link[=flowlines]{flowlines()}}) which can be confusing +for users and are difficult to plot. +} +\examples{ +flow_oneway <- od_oneway(flow, attrib = 3) +nrow(flow_oneway) < nrow(flow) # result has fewer rows +sum(flow$All) == sum(flow_oneway$All) # but the same total flow +# using names instead of index for attribute +od_oneway(flow, attrib = "All") +# using many attributes to aggregate +attrib <- which(vapply(flow, is.numeric, TRUE)) +flow_oneway <- od_oneway(flow, attrib = attrib) +colSums(flow_oneway[attrib]) == colSums(flow[attrib]) # test if the colSums are equal +# Demonstrate the results from oneway and onewaygeo are identical +flow_oneway_geo <- onewaygeo(flowlines, attrib = attrib) +plot(flow_oneway$All, flow_oneway_geo$All) +flow_oneway_sf <- od_oneway(flowlines_sf, 3) +plot(flow_oneway_geo, lwd = flow_oneway_geo$All / mean(flow_oneway_geo$All)) +plot(flow_oneway_sf$geometry, lwd = flow_oneway_sf$All / mean(flow_oneway_sf$All)) +# benchmark performance +# bench::mark(check = F, +# onewayid(flowlines_sf, 3), +# od_oneway(flowlines_sf, 3) +# ) +} +\seealso{ +Other lines: \code{\link{angle_diff}}, + \code{\link{geo_toptail}}, \code{\link{is_linepoint}}, + \code{\link{line2df}}, \code{\link{line_bearing}}, + \code{\link{line_match}}, \code{\link{line_midpoint}}, + \code{\link{line_sample}}, \code{\link{line_segment}}, + \code{\link{line_via}}, \code{\link{mats2line}}, + \code{\link{n_sample_length}}, \code{\link{n_vertices}}, + \code{\link{onewaygeo}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, + \code{\link{update_line_geometry}} +} +\concept{lines} diff --git a/man/onewaygeo.Rd b/man/onewaygeo.Rd index de6f1020..3cd08141 100644 --- a/man/onewaygeo.Rd +++ b/man/onewaygeo.Rd @@ -56,8 +56,9 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, \code{\link{n_vertices}}, - \code{\link{onewayid}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{od_oneway}}, \code{\link{onewayid}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/onewayid.Rd b/man/onewayid.Rd index bd834911..63779861 100644 --- a/man/onewayid.Rd +++ b/man/onewayid.Rd @@ -89,8 +89,9 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, \code{\link{n_vertices}}, - \code{\link{onewaygeo}}, \code{\link{points2line}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{od_oneway}}, \code{\link{onewaygeo}}, + \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/points2line.Rd b/man/points2line.Rd index 5e702249..58e2b7ea 100644 --- a/man/points2line.Rd +++ b/man/points2line.Rd @@ -34,8 +34,9 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, \code{\link{n_vertices}}, - \code{\link{onewaygeo}}, \code{\link{onewayid}}, - \code{\link{toptail_buff}}, \code{\link{toptailgs}}, + \code{\link{od_oneway}}, \code{\link{onewaygeo}}, + \code{\link{onewayid}}, \code{\link{toptail_buff}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/szudzik_pairing.Rd b/man/szudzik_pairing.Rd deleted file mode 100644 index 936a6143..00000000 --- a/man/szudzik_pairing.Rd +++ /dev/null @@ -1,41 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/oneway.R -\name{szudzik_pairing} -\alias{szudzik_pairing} -\title{Combines two ID values to create a single ID number} -\usage{ -szudzik_pairing(val1, val2, ordermatters = FALSE) -} -\arguments{ -\item{val1}{a vector of numeric, character, or factor values} - -\item{val2}{a vector of numeric, character, or factor values} - -\item{ordermatters}{logical, does the order of values matter to pairing, default = FALSE} -} -\description{ -Combines two ID values to create a single ID number -} -\details{ -In OD data it is common to have many flows from "A to B" and "B to A". -It can be useful to group these an have a single ID that represents pairs of IDs -with or without directionality. - -This function implements the Szudzik pairing function, on two vectors of equal -length. It returns a vector of ID numbers. - -This function superseeds od_id_order as it is faster on large datasets -} -\examples{ - -szudzik_pairing(od_data_sample[[1]], od_data_sample[[2]]) -od_id_order(od_data_sample) -n = 1000 -ids <- as.character(runif(n, 1e4, 1e7 - 1)) -x <- data.frame(id1 = rep(ids, times = n), - id2 = rep(ids, each = n), - val = 1, - stringsAsFactors = FALSE) -system.time(od_id_order(x)) -system.time(szudzik_pairing(x$id1, x$id2)) -} diff --git a/man/toptail_buff.Rd b/man/toptail_buff.Rd index 0846ddb4..e69ba9aa 100644 --- a/man/toptail_buff.Rd +++ b/man/toptail_buff.Rd @@ -35,8 +35,9 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, \code{\link{n_vertices}}, - \code{\link{onewaygeo}}, \code{\link{onewayid}}, - \code{\link{points2line}}, \code{\link{toptailgs}}, + \code{\link{od_oneway}}, \code{\link{onewaygeo}}, + \code{\link{onewayid}}, \code{\link{points2line}}, + \code{\link{toptailgs}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/toptailgs.Rd b/man/toptailgs.Rd index e21fea17..902ea1d5 100644 --- a/man/toptailgs.Rd +++ b/man/toptailgs.Rd @@ -38,8 +38,9 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, \code{\link{n_vertices}}, - \code{\link{onewaygeo}}, \code{\link{onewayid}}, - \code{\link{points2line}}, \code{\link{toptail_buff}}, + \code{\link{od_oneway}}, \code{\link{onewaygeo}}, + \code{\link{onewayid}}, \code{\link{points2line}}, + \code{\link{toptail_buff}}, \code{\link{update_line_geometry}} } \concept{lines} diff --git a/man/update_line_geometry.Rd b/man/update_line_geometry.Rd index 272020f9..eb59cdc7 100644 --- a/man/update_line_geometry.Rd +++ b/man/update_line_geometry.Rd @@ -37,8 +37,8 @@ Other lines: \code{\link{angle_diff}}, \code{\link{line_sample}}, \code{\link{line_segment}}, \code{\link{line_via}}, \code{\link{mats2line}}, \code{\link{n_sample_length}}, \code{\link{n_vertices}}, - \code{\link{onewaygeo}}, \code{\link{onewayid}}, - \code{\link{points2line}}, \code{\link{toptail_buff}}, - \code{\link{toptailgs}} + \code{\link{od_oneway}}, \code{\link{onewaygeo}}, + \code{\link{onewayid}}, \code{\link{points2line}}, + \code{\link{toptail_buff}}, \code{\link{toptailgs}} } \concept{lines}