From af8c454ead2f448ddc1f62d00a1b5932f05291c5 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Tue, 16 May 2023 10:02:53 +0200 Subject: [PATCH 01/87] removing data generation code chunks --- .gitignore | 1 + R/tripsOutput.R | 311 +--------------------------------- man/plotModalSplitPieChart.Rd | 4 +- 3 files changed, 7 insertions(+), 309 deletions(-) diff --git a/.gitignore b/.gitignore index fdf97db..f564ed6 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,5 @@ network.xml.gz analysis_berlin10/ kelheim/ test/ +dashboard_test/ .sentinel* diff --git a/R/tripsOutput.R b/R/tripsOutput.R index a17d285..a2d18dd 100644 --- a/R/tripsOutput.R +++ b/R/tripsOutput.R @@ -58,7 +58,7 @@ readTripsTable <- function(input_path = ".", n_max = Inf) { #' Plot main_mode distribution as a Pie Chart #' -#' Takes Table trips_output (from readTripsTable()), +#' Takes Table trips_output (from \link{readTripsTable}), #' to plot pie chart with with values that represent #' percentage of using transport modes from trips #' @@ -67,7 +67,7 @@ readTripsTable <- function(input_path = ".", n_max = Inf) { #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' #' -#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param tripsTable tibble of trips_output (from \link{readTripsTable}) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored @@ -110,51 +110,8 @@ plotModalSplitPieChart <- function(tripsTable, unite.columns = character(0), uni ggtitle("Distribution of transport type") + theme_void() plt - if (file.exists(dump.output.to)) { - ggsave(paste0(dump.output.to, "/modalSplitPieChart.png"),width = 6,height = 10, plt) - } else { - dir.create(dump.output.to) - ggsave(paste0(dump.output.to, "/modalSplitPieChart.png"),width = 6,height = 10, plt) - } - - # Generating yaml and output_files - if (file.exists(dump.output.to)) { - write_file(paste(tripsTableCount$main_mode, collapse = "\t"), paste0(dump.output.to, "/modalSplitPieChart.txt"), append = FALSE) - write_file(paste("\r\n", paste(tripsTableCount$n, collapse = "\t")), paste0(dump.output.to, "/modalSplitPieChart.txt"), append = TRUE) - # write.csv2(tripsTableCount,paste0(matsimDumpOutputDirectory,"/modalSplitPieChart.csv")) - } else { - dir.create(dump.output.to) - write_file(paste(tripsTableCount$main_mode, collapse = "\t"), paste0(dump.output.to, "/modalSplitPieChart.txt"), append = FALSE) - write_file(paste("\r\n", paste(tripsTableCount$n, collapse = "\t")), paste0(dump.output.to, "/modalSplitPieChart.txt"), append = TRUE) - # write.csv2(tripsTableCount,paste0(matsimDumpOutputDirectory,"/modalSplitPieChart.csv")) - } - - yaml_list <- list( - header = list(tab = "Summary", title = "Dashboard", description = "Plots from output directory"), - layout = list("1" = list( - title = paste0("Modal Split Pie Chart from",attr(tripsTable,"table_name")), - description = "generated by plotModalSplitPieChart()", - type = "pie", - width = 1, - props = list(dataset = "modalSplitPieChart.txt", useLastRow = "true") - )) - ) - if (file.exists(paste0(dump.output.to, dashboard_file))) { - yaml_from_directory <- read_yaml(paste0(dump.output.to, dashboard_file)) - yaml_from_directory$layout <- append(yaml_from_directory$layout, list(new_row = list( - title = paste0("Modal Split Pie Chart from",attr(tripsTable,"table_name")), - description = "generated by plotModalSplitPieChart()", - type = "pie", - width = 1, - props = list(dataset = "modalSplitPieChart.txt", useLastRow = "true") - ))) - names(yaml_from_directory$layout) <- 1:length(names(yaml_from_directory$layout)) - write_yaml(yaml_from_directory, paste0(dump.output.to, dashboard_file)) - } else { - write_yaml(yaml_list, paste0(dump.output.to, dashboard_file)) - } if(!only.files){ return(plt) } @@ -201,59 +158,6 @@ plotModalSplitBarChart <- function(tripsTable, unite.columns = character(0), uni name = "Distribution of transport type") fig = fig %>% layout(yaxis = list(title = "Count"),barmode = "group") - if (file.exists(dump.output.to)) { - #ggsave(paste0(dump.output.to, "/modalSplitBarChart.png"),width = 6,height = 10, fig) - htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/modalSplitBarChart.html")) - } else { - dir.create(dump.output.to) - htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/modalSplitBarChart.html")) - #ggsave(paste0(dump.output.to, "/modalSplitBarChart.png"),width = 6,height = 10, fig) - } - - # Generating yaml and output_files - if (file.exists(dump.output.to)) { - write.table(tripsTableCount,paste0(dump.output.to,"/modalSplitBarChart.csv"),row.names = FALSE,sep = ",") - } else { - dir.create(dump.output.to) - #write_file(paste(tripsTableCount$main_mode, collapse = "\t"), paste0(dump.output.to, "/modalSplitBarChart.txt"), append = FALSE) - #write_file(paste("\r\n", paste(tripsTableCount$n, collapse = "\t")), paste0(dump.output.to, "/modalSplitBarChart.txt"), append = TRUE) - write.table(tripsTableCount,paste0(dump.output.to,"/modalSplitBarChart.csv"),row.names = FALSE,sep = ",") - } - - yaml_list <- list( - header = list(tab = "Summary", title = "Dashboard", description = "Plots from output directory"), - layout = list("1" = list( - title = paste0("Modal Split Bar Chart from ",attr(tripsTable,"table_name")), - description = "generated by plotModalSplitBarChart()", - type = "bar", - width = 1, - props = list(dataset = "modalSplitBarChart.csv", - x = "main_mode", - y = "n", - yAxisTitle = "Count of trips", - xAxisTitle = "Main mode of trip") - )) - ) - - if (file.exists(paste0(dump.output.to, dashboard_file))) { - yaml_from_directory <- read_yaml(paste0(dump.output.to, dashboard_file)) - yaml_from_directory$layout <- append(yaml_from_directory$layout, list(new_row = list( - title = paste0("Modal Split Bar Chart from ",attr(tripsTable,"table_name")), - description = "generated by plotModalSplitBarChart()", - type = "bar", - width = 1, - props = list(dataset = "modalSplitBarChart.csv", - x = "main_mode", - y = "n", - yAxisTitle = "Count of trips", - xAxisTitle = "Main mode of trip") - ))) - names(yaml_from_directory$layout) <- 1:length(names(yaml_from_directory$layout)) - - write_yaml(yaml_from_directory, paste0(dump.output.to, dashboard_file)) - } else { - write_yaml(yaml_list, paste0(dump.output.to, dashboard_file)) - } # plotting if(!only.files){ @@ -297,58 +201,7 @@ plotAverageTravelWait <- function(tripsTable, unite.columns = character(0), unit fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") fig = fig %>% layout(yaxis = list(title = "Time spent (in minutes)"),barmode = "group") - #files - if (file.exists(dump.output.to)) { - htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/averageTravelWait.html")) - #ggsave(paste0(dump.output.to, "/averageTravelWait.png"),width = 6,height = 10, fig) - } else { - dir.create(dump.output.to) - htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/averageTravelWait.html")) - #ggsave(paste0(dump.output.to, "/averageTravelWait.png"),width = 6,height = 10, fig) - } - - # Generating yaml and output_files - if (file.exists(dump.output.to)) { - write.table(avg_time,paste0(dump.output.to,"/averageTravelWait.csv"),row.names = FALSE,sep = ",") - } else { - dir.create(dump.output.to) - write.table(avg_time,paste0(dump.output.to,"/averageTravelWait.csv"),row.names = FALSE,sep = ",") - } - yaml_list <- list( - header = list(tab = "Summary", title = "Dashboard", description = "Plots from output directory"), - layout = list("1" = list( - title = paste0("Average Travel/Wait Time Chart from ",attr(tripsTable,"table_name")), - description = "generated by plotAverageTravelWait()", - type = "bar", - width = 1, - props = list(dataset = "averageTravelWait.csv", - x = "main_mode", - y = "[trav_time_avg,wait_time_avg]", - yAxisTitle = "Time in minutes", - xAxisTitle = "main_mode") - )) - ) - - if (file.exists(paste0(dump.output.to, dashboard_file))) { - yaml_from_directory <- read_yaml(paste0(dump.output.to, dashboard_file)) - yaml_from_directory$layout <- append(yaml_from_directory$layout, list(new_row = list( - title = paste0("Average Travel/Wait Time Chart from ",attr(tripsTable,"table_name")), - description = "generated by plotAverageTravelWait()", - type = "bar", - width = 1, - props = list(dataset = "averageTravelWait.csv", - x = "main_mode", - y = "[trav_time_avg,wait_time_avg]", - yAxisTitle = "Time in minutes", - xAxisTitle = "main_mode") - ))) - names(yaml_from_directory$layout) <- 1:length(names(yaml_from_directory$layout)) - - write_yaml(yaml_from_directory, paste0(dump.output.to, dashboard_file)) - } else { - write_yaml(yaml_list, paste0(dump.output.to, dashboard_file)) - } #plotting if(!only.files){ @@ -415,59 +268,7 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") fig = fig %>% layout(yaxis = list(title = "Time spent (in minutes)"),barmode = "group") - #files - if (file.exists(dump.output.to)) { - htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/averageTravelWait.html")) - #ggsave(paste0(dump.output.to, "/averageTravelWait.png"),width = 6,height = 10, fig) - } else { - dir.create(dump.output.to) - htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/averageTravelWait.html")) - #ggsave(paste0(dump.output.to, "/averageTravelWait.png"),width = 6,height = 10, fig) - } - - # Generating yaml and output_files - if (file.exists(dump.output.to)) { - write.table(avg_time,paste0(dump.output.to,"/averageTravelWait.csv"),row.names = FALSE,sep = ",") - } else { - dir.create(dump.output.to) - write.table(avg_time,paste0(dump.output.to,"/averageTravelWait.csv"),row.names = FALSE,sep = ",") - } - - yaml_list <- list( - header = list(tab = "Summary", title = "Dashboard", description = "Plots from output directory"), - layout = list("1" = list( - title = paste0("Average Travel/Wait Time Chart from ",attr(tripsTable1,"table_name")," and ",attr(tripsTable2,"table_name")), - description = "generated by plotAverageTravelWait()", - type = "bar", - width = 1, - props = list(dataset = "averageTravelWait.csv", - x = "main_mode", - columns = list("trav_time_avg","wait_time_avg"), - yAxisTitle = "Time in minutes", - xAxisTitle = "main_mode" - ) - )) - ) - - if (file.exists(paste0(dump.output.to, dashboard_file))) { - yaml_from_directory <- read_yaml(paste0(dump.output.to, dashboard_file)) - yaml_from_directory$layout <- append(yaml_from_directory$layout, list(new_row = list( - title = paste0("Average Travel/Wait Time Chart from ",attr(tripsTable1,"table_name")," and ",attr(tripsTable2,"table_name")), - description = "generated by plotAverageTravelWait()", - type = "bar", - width = 1, - props = list(dataset = "averageTravelWait.csv", - x = "main_mode", - columns = list("trav_time_avg","wait_time_avg"), - yAxisTitle = "Time in minutes", - xAxisTitle = "main_mode") - ))) - names(yaml_from_directory$layout) <- 1:length(names(yaml_from_directory$layout)) - write_yaml(yaml_from_directory, paste0(dump.output.to, dashboard_file)) - } else { - write_yaml(yaml_list, paste0(dump.output.to, dashboard_file)) - } #plotting if(!only.files){ @@ -529,7 +330,8 @@ plotModalDistanceDistribution <- function(tripsTable, unite.columns = character( tripsTable_result$dist_cat = factor(tripsTable_result$dist_cat,levels = c("0-1km","1-2km","2-5km","5-10km","10-20km","20-50km","50-100km","> 100km")) tableWithCounts = tripsTable_result %>% count(main_mode,dist_cat) - #print(tableWithCounts) + + #Reformat the table for simwrapper output tableToWrite = tripsTable_result %>% select(dist_cat) %>% unique() %>% arrange(dist_cat) for( mode in modes){ newColumn = tableWithCounts %>% @@ -555,58 +357,7 @@ plotModalDistanceDistribution <- function(tripsTable, unite.columns = character( ggtitle("Number of trips per travelling distance") fig = plotly::ggplotly(plt) - #files - if (file.exists(dump.output.to)) { - htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/tripsPerDistance.html")) - #ggsave(paste0(dump.output.to, "/averageTravelWait.png"),width = 6,height = 10, fig) - } else { - dir.create(dump.output.to) - htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/tripsPerDistance.html")) - #ggsave(paste0(dump.output.to, "/averageTravelWait.png"),width = 6,height = 10, fig) - } - - # Generating yaml and output_files - if (file.exists(dump.output.to)) { - write.table(tableToWrite,paste0(dump.output.to,"/tripsPerDistance.csv"),row.names = FALSE,sep = ",") - } else { - dir.create(dump.output.to) - write.table(tableToWrite,paste0(dump.output.to,"/tripsPerDistance.csv"),row.names = FALSE,sep = ",") - } - yaml_list <- list( - header = list(tab = "Summary", title = "Dashboard", description = "Plots from output directory"), - layout = list("1" = list( - title = paste0("Count of trips travelled per distance from ",attr(tripsTable,"table_name")), - description = "generated by plotTripsByDistance()", - type = "bar", - width = 1, - props = list(dataset = "tripsPerDistance.csv", - x = "dist_cat", - y = "[main_mode,n]", - yAxisTitle = "Count of trips", - xAxisTitle = "Distance") - )) - ) - - if (file.exists(paste0(dump.output.to, dashboard_file))) { - yaml_from_directory <- read_yaml(paste0(dump.output.to, dashboard_file)) - yaml_from_directory$layout <- append(yaml_from_directory$layout, list(new_row = list( - title = paste0("Count of trips travelled per distance from ",attr(tripsTable,"table_name")), - description = "generated by plotTripsByDistance()", - type = "bar", - width = 1, - props = list(dataset = "tripsPerDistance.csv", - x = "dist_cat", - y = "[main_mode,n]", - yAxisTitle = "Count of trips", - xAxisTitle = "Distance") - ))) - names(yaml_from_directory$layout) <- 1:length(names(yaml_from_directory$layout)) - - write_yaml(yaml_from_directory, paste0(dump.output.to, dashboard_file)) - } else { - write_yaml(yaml_list, paste0(dump.output.to, dashboard_file)) - } if(!only.files){ fig @@ -684,60 +435,6 @@ compareModalDistanceDistribution <- function(tripsTable1,tripsTable2, unite.colu ggtitle("Difference in number of trips per travelling distance")) - #files - if (file.exists(dump.output.to)) { - htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/modalDistanceDistributionComparison.html")) - #ggsave(paste0(dump.output.to, "/averageTravelWait.png"),width = 6,height = 10, fig) - } else { - dir.create(dump.output.to) - htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/modalDistanceDistributionComparison.html")) - #ggsave(paste0(dump.output.to, "/averageTravelWait.png"),width = 6,height = 10, fig) - } - - # Generating yaml and output_files - if (file.exists(dump.output.to)) { - write.table(tableToWrite,paste0(dump.output.to,"/modalDistanceDistributionComparison.csv"),row.names = FALSE,sep = ",") - } else { - dir.create(dump.output.to) - write.table(tableToWrite,paste0(dump.output.to,"/modalDistanceDistributionComparison.csv"),row.names = FALSE,sep = ",") - } - - #print(list(modes)) - yaml_list <- list( - header = list(tab = "Summary", title = "Dashboard", description = "Plots from output directory"), - layout = list("1" = list( - title = paste0("Modal Distance Distribution Comparison between ",attr(tripsTable1,"table_name")," and ",attr(tripsTable2,"table_name")), - description = "generated by compareModalDistanceDistribution()", - type = "bar", - width = 1, - props = list(dataset = "modalDistanceDistributionComparison.csv", - x = "dist_cat", - columns = as.list(modes), - yAxisTitle = "Number of trips", - xAxisTitle = "dist_cat") - )) - ) - - if (file.exists(paste0(dump.output.to, dashboard_file))) { - yaml_from_directory <- read_yaml(paste0(dump.output.to, dashboard_file)) - yaml_from_directory$layout <- append(yaml_from_directory$layout, list(new_row = list( - title = paste0("Modal Distance Distribution Comparison between ",attr(tripsTable1,"table_name")," and ",attr(tripsTable2,"table_name")), - description = "generated by compareModalDistanceDistribution()", - type = "bar", - width = 1, - props = list(dataset = "modalDistanceDistributionComparison.csv", - x = "dist_cat", - columns = as.list(modes), - yAxisTitle = "Number of trips", - xAxisTitle = "dist_cat") - ))) - names(yaml_from_directory$layout) <- 1:length(names(yaml_from_directory$layout)) - - write_yaml(yaml_from_directory, paste0(dump.output.to, dashboard_file)) - } else { - write_yaml(yaml_list, paste0(dump.output.to, dashboard_file)) - } - return(fig) } diff --git a/man/plotModalSplitPieChart.Rd b/man/plotModalSplitPieChart.Rd index ebd48b1..ab529e0 100644 --- a/man/plotModalSplitPieChart.Rd +++ b/man/plotModalSplitPieChart.Rd @@ -13,7 +13,7 @@ plotModalSplitPieChart( ) } \arguments{ -\item{tripsTable}{tible of trips_output (from readTripsTable())} +\item{tripsTable}{tibble of trips_output (from \link{readTripsTable})} \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} @@ -27,7 +27,7 @@ plotModalSplitPieChart( Pie Chart plot of transport mode distribution, values given in percents } \description{ -Takes Table trips_output (from readTripsTable()), +Takes Table trips_output (from \link{readTripsTable}), to plot pie chart with with values that represent percentage of using transport modes from trips } From 9cb462c037dbde709052c5714e06fae47ca75b7a Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Tue, 23 May 2023 13:26:13 +0200 Subject: [PATCH 02/87] first changes in main mode distribution plotting --- NAMESPACE | 2 + R/{tripsOutput.R => output_trips.R} | 461 +++++++++--------- man/compareAverageTravelWait.Rd | 2 +- man/compareBasePolicyOutput.Rd | 2 +- man/compareBasePolicyShapeOutput.Rd | 2 +- man/compareModalDistanceDistribution.Rd | 2 +- man/compareTripTypesBarChart.Rd | 2 +- man/deriveODMatrix.Rd | 2 +- man/filterByRegion.Rd | 2 +- man/getCrsFromConfig.Rd | 2 +- man/matsimr-deprecated.Rd | 49 ++ man/plotActivityEndTimes.Rd | 2 +- man/plotArrivalTimesPerTripPurpose.Rd | 2 +- man/plotAverageTravelWait.Rd | 2 +- man/plotDepartureTimesPerTripPurpose.Rd | 2 +- man/plotMapWithFilteredTrips.Rd | 2 +- man/plotMapWithTrips.Rd | 2 +- man/plotMapWithTripsType.Rd | 2 +- man/plotModalDistanceDistribution.Rd | 2 +- man/plotModalShiftBar.Rd | 2 +- man/plotModalShiftSankey.Rd | 2 +- man/plotTripCountByDepTime.Rd | 2 +- man/plotTripDistanceByMode.Rd | 2 +- man/plotTripDistancedByType.Rd | 2 +- man/plotTripTypesPieChart.Rd | 2 +- ...tBarChart.Rd => plot_mainmode_barchart.Rd} | 16 +- ...tPieChart.Rd => plot_mainmode_piechart.Rd} | 17 +- man/readTripsTable.Rd | 2 +- man/transformToSf.Rd | 2 +- ...test-tripsOutput.R => test-output_trips.R} | 0 30 files changed, 329 insertions(+), 264 deletions(-) rename R/{tripsOutput.R => output_trips.R} (91%) create mode 100644 man/matsimr-deprecated.Rd rename man/{plotModalSplitBarChart.Rd => plot_mainmode_barchart.Rd} (89%) rename man/{plotModalSplitPieChart.Rd => plot_mainmode_piechart.Rd} (86%) rename tests/testthat/{test-tripsOutput.R => test-output_trips.R} (100%) diff --git a/NAMESPACE b/NAMESPACE index ff824b3..17cb27d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -29,6 +29,8 @@ export(plotTripCountByDepTime) export(plotTripDistanceByMode) export(plotTripDistancedByType) export(plotTripTypesPieChart) +export(plot_mainmode_barchart) +export(plot_mainmode_piechart) export(prepareComparisonSimwrapperDashboardFromTable) export(prepareSimwrapperDashboardFromFolder) export(prepareSimwrapperDashboardFromTable) diff --git a/R/tripsOutput.R b/R/output_trips.R similarity index 91% rename from R/tripsOutput.R rename to R/output_trips.R index a2d18dd..21b8905 100644 --- a/R/tripsOutput.R +++ b/R/output_trips.R @@ -1,6 +1,12 @@ +#####Variables#### + matsimDumpOutputDirectory <- "./matsim_r_output" dashboard_file <- "/dashboard-1-trips.yaml" + +#####Reading##### + + #' Load MATSIM output_trips table into Memory #' #' Loads a MATSim CSV output_trips from file or archive, @@ -56,6 +62,8 @@ readTripsTable <- function(input_path = ".", n_max = Inf) { } +#####Deprecated#### + #' Plot main_mode distribution as a Pie Chart #' #' Takes Table trips_output (from \link{readTripsTable}), @@ -66,7 +74,8 @@ readTripsTable <- function(input_path = ".", n_max = Inf) { #' and plots pie chart. #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' -#' +#' @rdname matsimr-deprecated +#' @name matsimr-deprecated #' @param tripsTable tibble of trips_output (from \link{readTripsTable}) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart @@ -75,10 +84,21 @@ readTripsTable <- function(input_path = ".", n_max = Inf) { #' #' @return Pie Chart plot of transport mode distribution, values given in percents #' -#' @export -plotModalSplitPieChart <- function(tripsTable, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, +#' @docType package +#' @export plotModalSplitPieChart plotModalSplitBarChart +#' @aliases plotModalSplitPieChart plotModalSplitBarChart +#' @section Details: +#' \tabular{rl}{ +#' \code{plot_mainmode_piechart} \tab now a synonym for \code{\link{plotModalSplitPieChart}}\cr +#' \code{plot_mainmode_barchart} \tab now a synonym for \code{\link{plotModalSplitBarChart}}\cr +#' } +#' +plotModalSplitPieChart <- function(tripsTable, + unite.columns = character(0), united.name = "united", + dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { + .Deprecated("plot_mainmode_piechart") # If some columns should be united if (length(unite.columns) != 0) { tripsTable$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable$main_mode)] <- united.name @@ -110,13 +130,185 @@ plotModalSplitPieChart <- function(tripsTable, unite.columns = character(0), uni ggtitle("Distribution of transport type") + theme_void() plt + if (file.exists(dump.output.to)) { + ggsave(paste0(dump.output.to, "/modalSplitPieChart.png"),width = 6,height = 10, plt) + } else { + dir.create(dump.output.to) + ggsave(paste0(dump.output.to, "/modalSplitPieChart.png"),width = 6,height = 10, plt) + } + + # Generating yaml and output_files + if (file.exists(dump.output.to)) { + write_file(paste(tripsTableCount$main_mode, collapse = "\t"), paste0(dump.output.to, "/modalSplitPieChart.txt"), append = FALSE) + write_file(paste("\r\n", paste(tripsTableCount$n, collapse = "\t")), paste0(dump.output.to, "/modalSplitPieChart.txt"), append = TRUE) + # write.csv2(tripsTableCount,paste0(matsimDumpOutputDirectory,"/modalSplitPieChart.csv")) + } else { + dir.create(dump.output.to) + write_file(paste(tripsTableCount$main_mode, collapse = "\t"), paste0(dump.output.to, "/modalSplitPieChart.txt"), append = FALSE) + write_file(paste("\r\n", paste(tripsTableCount$n, collapse = "\t")), paste0(dump.output.to, "/modalSplitPieChart.txt"), append = TRUE) + # write.csv2(tripsTableCount,paste0(matsimDumpOutputDirectory,"/modalSplitPieChart.csv")) + } + + yaml_list <- list( + header = list(tab = "Summary", title = "Dashboard", description = "Plots from output directory"), + layout = list("1" = list( + title = paste0("Modal Split Pie Chart from",attr(tripsTable,"table_name")), + description = "generated by plotModalSplitPieChart()", + type = "pie", + width = 1, + props = list(dataset = "modalSplitPieChart.txt", useLastRow = "true") + )) + ) + if (file.exists(paste0(dump.output.to, dashboard_file))) { + yaml_from_directory <- read_yaml(paste0(dump.output.to, dashboard_file)) + yaml_from_directory$layout <- append(yaml_from_directory$layout, list(new_row = list( + title = paste0("Modal Split Pie Chart from",attr(tripsTable,"table_name")), + description = "generated by plotModalSplitPieChart()", + type = "pie", + width = 1, + props = list(dataset = "modalSplitPieChart.txt", useLastRow = "true") + ))) + names(yaml_from_directory$layout) <- 1:length(names(yaml_from_directory$layout)) + write_yaml(yaml_from_directory, paste0(dump.output.to, dashboard_file)) + } else { + write_yaml(yaml_list, paste0(dump.output.to, dashboard_file)) + } if(!only.files){ return(plt) } } +plotModalSplitBarChart <- function(tripsTable, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + only.files = FALSE) { + + .Deprecated("plot_mainmode_barchart") + # If some columns should be united + if (length(unite.columns) != 0) { + tripsTable$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable$main_mode)] <- united.name + } + # Get percentage + tripsTableCount <- tripsTable %>% + count(main_mode) %>% + arrange(desc(n)) + text_for_y = tripsTableCount$n + + + fig = plot_ly(data = tripsTableCount,x = ~main_mode,y = ~n,type = "bar", + text = text_for_y, + textposition = "auto", + name = "Distribution of transport type") + fig = fig %>% layout(yaxis = list(title = "Count"),barmode = "group") + + if (file.exists(dump.output.to)) { + #ggsave(paste0(dump.output.to, "/modalSplitBarChart.png"),width = 6,height = 10, fig) + htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/modalSplitBarChart.html")) + } else { + dir.create(dump.output.to) + htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/modalSplitBarChart.html")) + #ggsave(paste0(dump.output.to, "/modalSplitBarChart.png"),width = 6,height = 10, fig) + } + + # Generating yaml and output_files + if (file.exists(dump.output.to)) { + write.table(tripsTableCount,paste0(dump.output.to,"/modalSplitBarChart.csv"),row.names = FALSE,sep = ",") + } else { + dir.create(dump.output.to) + #write_file(paste(tripsTableCount$main_mode, collapse = "\t"), paste0(dump.output.to, "/modalSplitBarChart.txt"), append = FALSE) + #write_file(paste("\r\n", paste(tripsTableCount$n, collapse = "\t")), paste0(dump.output.to, "/modalSplitBarChart.txt"), append = TRUE) + write.table(tripsTableCount,paste0(dump.output.to,"/modalSplitBarChart.csv"),row.names = FALSE,sep = ",") + } + + yaml_list <- list( + header = list(tab = "Summary", title = "Dashboard", description = "Plots from output directory"), + layout = list("1" = list( + title = paste0("Modal Split Bar Chart from ",attr(tripsTable,"table_name")), + description = "generated by plotModalSplitBarChart()", + type = "bar", + width = 1, + props = list(dataset = "modalSplitBarChart.csv", + x = "main_mode", + y = "n", + yAxisTitle = "Count of trips", + xAxisTitle = "Main mode of trip") + )) + ) + + if (file.exists(paste0(dump.output.to, dashboard_file))) { + yaml_from_directory <- read_yaml(paste0(dump.output.to, dashboard_file)) + yaml_from_directory$layout <- append(yaml_from_directory$layout, list(new_row = list( + title = paste0("Modal Split Bar Chart from ",attr(tripsTable,"table_name")), + description = "generated by plotModalSplitBarChart()", + type = "bar", + width = 1, + props = list(dataset = "modalSplitBarChart.csv", + x = "main_mode", + y = "n", + yAxisTitle = "Count of trips", + xAxisTitle = "Main mode of trip") + ))) + names(yaml_from_directory$layout) <- 1:length(names(yaml_from_directory$layout)) + + write_yaml(yaml_from_directory, paste0(dump.output.to, dashboard_file)) + } else { + write_yaml(yaml_list, paste0(dump.output.to, dashboard_file)) + } + # plotting + if(!only.files){ + + fig + return(fig) + } +} + +#####Plotting##### + +#' Plot main_mode distribution as a Pie Chart +#' +#' Takes Table trips_output (from \link{readTripsTable}), +#' to plot pie chart with with values that represent +#' percentage of using transport modes from trips +#' +#' Function automatically detects transport_modes from table +#' and plots pie chart. +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' @param tripsTable tibble of trips_output (from \link{readTripsTable}) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' +#' @return Pie Chart plot of transport mode distribution, values given in percents +#' +#' @export +plot_mainmode_piechart <- function(trips_table, + unite.columns = character(0), united.name = "united", + dump.output.to = matsimDumpOutputDirectory) { + + # If some columns should be united + trips_table = process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, + united.name = united.name) + + # tripsTableCount gives percentage representation out + trips_table_count<-process_get_mainmode_distribution(trips_table, + percentage= percentage) + + + # plotting + fig <- plot_ly(trips_table_count, labels = ~main_mode, values = ~n, type = 'pie') + fig <- fig %>% layout(title = 'Main mode distribution', + xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE), + yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE)) + + return(fig) +} + #' Plot main_mode distribution as a bar Chart #' @@ -138,32 +330,28 @@ plotModalSplitPieChart <- function(tripsTable, unite.columns = character(0), uni #' @return Bar Chart plot of transport mode distribution, values given in percents #' #' @export -plotModalSplitBarChart <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE) { +plot_mainmode_barchart <- function(trips_table, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + percentage = FALSE) { # If some columns should be united - if (length(unite.columns) != 0) { - tripsTable$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable$main_mode)] <- united.name - } + trips_table <- process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, + united.name = united.name) # Get percentage - tripsTableCount <- tripsTable %>% - count(main_mode) %>% - arrange(desc(n)) - text_for_y = tripsTableCount$n - + trips_table_count <- process_get_mainmode_distribution(trips_table, + percentage = percentage) - fig = plot_ly(data = tripsTableCount,x = ~main_mode,y = ~n,type = "bar", - text = text_for_y, + # plotting + fig = plot_ly(data = trips_table_count,x = ~main_mode,y = ~n,type = "bar", + text=trips_table_count$n, textposition = "auto", - name = "Distribution of transport type") + name = "Main mode distribtion") fig = fig %>% layout(yaxis = list(title = "Count"),barmode = "group") - - # plotting - if(!only.files){ - - fig - return(fig) - } + fig + return(fig) } #' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis @@ -304,6 +492,8 @@ plotModalDistanceDistribution <- function(tripsTable, unite.columns = character( } modes = levels(factor(tripsTable$main_mode)) + + #To-do: provide array of distance categories #This is a very bad way to do that, but I see no other way to get it done #Also filtering table into a new doesn't creates new objects in memory, so it works fast tripsTable_05km = tripsTable %>% filter(traveled_distance<=1000) %>% mutate(dist_cat = "0-1km") @@ -480,58 +670,6 @@ plotTripDistanceByMode <- function(tripsTable, unite.columns = character(0), uni name = "AVG Distance traveled by a person over a day") fig = fig %>% layout(yaxis = list(title = "Distance (kms)"),barmode = "group") - #files - if (file.exists(dump.output.to)) { - htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/tripsPerDistanceByMode.html")) - #ggsave(paste0(dump.output.to, "/averageTravelWait.png"),width = 6,height = 10, fig) - } else { - dir.create(dump.output.to) - htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/tripsPerDistanceByMode.html")) - #ggsave(paste0(dump.output.to, "/averageTravelWait.png"),width = 6,height = 10, fig) - } - - # Generating yaml and output_files - if (file.exists(dump.output.to)) { - write.table(tripsTable,paste0(dump.output.to,"/tripDistancePerMode.csv"),row.names = FALSE,sep = ",") - } else { - dir.create(dump.output.to) - write.table(tripsTable,paste0(dump.output.to,"/tripDistancePerMode.csv"),row.names = FALSE,sep = ",") - } - - yaml_list <- list( - header = list(tab = "Summary", title = "Dashboard", description = "Plots from output directory"), - layout = list("1" = list( - title = paste0("Average distance traveled by person per mode from ",attr(tripsTable,"table_name")), - description = "generated by plotTripDistanceByMode()", - type = "bar", - width = 1, - props = list(dataset = "tripDistancePerMode.csv", - x = "main_mode", - y = "[avg_dist]", - yAxisTitle = "Distance (kms)", - xAxisTitle = "Main_mode") - )) - ) - - if (file.exists(paste0(dump.output.to, dashboard_file))) { - yaml_from_directory <- read_yaml(paste0(dump.output.to, dashboard_file)) - yaml_from_directory$layout <- append(yaml_from_directory$layout, list(new_row = list( - title = paste0("Average distance traveled by person per mode from ",attr(tripsTable,"table_name")), - description = "generated by plotTripDistanceByMode()", - type = "bar", - width = 1, - props = list(dataset = "tripDistancePerMode.csv", - x = "main_mode", - y = "[avg_dist]", - yAxisTitle = "Distance (kms)", - xAxisTitle = "Main_mode") - ))) - names(yaml_from_directory$layout) <- 1:length(names(yaml_from_directory$layout)) - - write_yaml(yaml_from_directory, paste0(dump.output.to, dashboard_file)) - } else { - write_yaml(yaml_list, paste0(dump.output.to, dashboard_file)) - } if(!only.files){ @@ -607,57 +745,7 @@ plotTripCountByDepTime <- function(tripsTable, unite.columns = character(0), uni fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") #files - if (file.exists(dump.output.to)) { - htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/countTripsByDep.html")) - #ggsave(paste0(dump.output.to, "/averageTravelWait.png"),width = 6,height = 10, fig) - } else { - dir.create(dump.output.to) - htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/countTripsByDep.html")) - #ggsave(paste0(dump.output.to, "/averageTravelWait.png"),width = 6,height = 10, fig) - } - - # Generating yaml and output_files - if (file.exists(dump.output.to)) { - write.table(tableToWrite,paste0(dump.output.to,"/countTripsByDep.csv"),row.names = FALSE,sep = ",") - } else { - dir.create(dump.output.to) - write.table(tableToWrite,paste0(dump.output.to,"/countTripsByDep.csv"),row.names = FALSE,sep = ",") - } - yaml_list <- list( - header = list(tab = "Summary", title = "Dashboard", description = "Plots from output directory"), - layout = list("1" = list( - title = paste0("Trips counted by departure time from ",attr(tripsTable,"table_name")), - description = "generated by plotTripCountByDepTime()", - type = "line", - width = 1, - props = list(dataset = "countTripsByDep.csv", - x = "dep_time", - y = "[n]", - yAxisTitle = "Count of trips", - xAxisTitle = "departure time") - )) - ) - - if (file.exists(paste0(dump.output.to, dashboard_file))) { - yaml_from_directory <- read_yaml(paste0(dump.output.to, dashboard_file)) - yaml_from_directory$layout <- append(yaml_from_directory$layout, list(new_row = list( - title = paste0("Trips counted by departure time from ",attr(tripsTable,"table_name")), - description = "generated by plotTripCountByDepTime()", - type = "line", - width = 1, - props = list(dataset = "countTripsByDep.csv", - x = "dep_time", - y = "[n]", - yAxisTitle = "Count of trips", - xAxisTitle = "departure time") - ))) - names(yaml_from_directory$layout) <- 1:length(names(yaml_from_directory$layout)) - - write_yaml(yaml_from_directory, paste0(dump.output.to, dashboard_file)) - } else { - write_yaml(yaml_list, paste0(dump.output.to, dashboard_file)) - } if(!only.files){ fig @@ -735,48 +823,7 @@ plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), unite # } # Generating yaml and output_files - if (! file.exists(dump.output.to)) { - dir.create(dump.output.to) - } - - write.table(tableToWrite,paste0(dump.output.to,"/activityEndTimes.csv"),row.names = FALSE,sep = ",") - yaml_list <- list( - header = list(tab = "Summary", title = "Dashboard", description = "Plots from output directory"), - layout = list("1" = list( - title = paste0("Activity End Times ",attr(tripsTable,"table_name")), - description = "generated by plotActivityEndTimes()", - type = "bar", - width = 1, - props = list(dataset = "activityEndTimes.csv", - x = "dep_time", - y = "[n]", - yAxisTitle = "Number of activities [n]", - xAxisTitle = "Time [h]", - stacked= TRUE) - )) - ) - - if (file.exists(paste0(dump.output.to, dashboard_file))) { - yaml_from_directory <- read_yaml(paste0(dump.output.to, dashboard_file)) - yaml_from_directory$layout <- append(yaml_from_directory$layout, list(new_row = list( - title = paste0("Activity End Times ",attr(tripsTable,"table_name")), - description = "generated by plotActivityEndTimes()", - type = "bar", - width = 1, - props = list(dataset = "activityEndTimes.csv", - x = "dep_time", - y = "[n]", - yAxisTitle = "Number of activities [n]", - xAxisTitle = "Time [h]", - stacked = TRUE) - ))) - names(yaml_from_directory$layout) <- 1:length(names(yaml_from_directory$layout)) - - write_yaml(yaml_from_directory, paste0(dump.output.to, dashboard_file)) - } else { - write_yaml(yaml_list, paste0(dump.output.to, dashboard_file)) - } if(!only.files){ fig return(fig) @@ -967,56 +1014,7 @@ plotDepartureTimesPerTripPurpose <- function(tripsTable, unite.columns = charact # #files - # if (file.exists(dump.output.to)) { - # htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/countEndActByArr.html")) - # } else { - # dir.create(dump.output.to) - # htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/countEndActByArr.html")) -# - # } - - # Generating yaml and output_files - if (! file.exists(dump.output.to)) { - dir.create(dump.output.to) - } - write.table(tableToWrite,paste0(dump.output.to,"/countDepartureTimesByTime.csv"),row.names = FALSE,sep = ",") - - yaml_list <- list( - header = list(tab = "Summary", title = "Dashboard", description = "Plots from output directory"), - layout = list("1" = list( - title = paste0("Trip Departure Times per Trip Purpose",attr(tripsTable,"table_name")), - description = "generated by plotDepartureTimesPerTripPurpose()", - type = "bar", - width = 1, - props = list(dataset = "countDepartureTimesByTime.csv", - x = "dep_time", - y = "[n]", - yAxisTitle = "Number of trips starting [n]", - xAxisTitle = "Time [h]", - stacked = TRUE) - )) - ) - if (file.exists(paste0(dump.output.to, dashboard_file))) { - yaml_from_directory <- read_yaml(paste0(dump.output.to, dashboard_file)) - yaml_from_directory$layout <- append(yaml_from_directory$layout, list(new_row = list( - title = paste0("Trip Departure Times per Trip Purpose",attr(tripsTable,"table_name")), - description = "generated by plotDepartureTimesPerTripPurpose()", - type = "bar", - width = 1, - props = list(dataset = "countDepartureTimesByTime.csv", - x = "dep_time", - y = "[n]", - yAxisTitle = "Number of trips starting [n]", - xAxisTitle = "Time [h]", - stacked = TRUE) - ))) - names(yaml_from_directory$layout) <- 1:length(names(yaml_from_directory$layout)) - - write_yaml(yaml_from_directory, paste0(dump.output.to, dashboard_file)) - } else { - write_yaml(yaml_list, paste0(dump.output.to, dashboard_file)) - } if(!only.files){ fig return(fig) @@ -1151,7 +1149,7 @@ plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FA #' @return plots Bar Chart of transport mode changes with additional files for simwrapper #' #' @export -plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, + plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, output.name = "modalShiftBarChart") { # If the unite.columns is specified, then #print(dump.output.to) @@ -1169,13 +1167,6 @@ plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = characte coord_flip() plotly::ggplotly(plt) - if (file.exists(dump.output.to)) { - ggsave(paste0(dump.output.to,"/",output.name,".png"), plt,device = "png") - } else { - dir.create(dump.output.to) - ggsave(paste0(dump.output.to,"/",output.name,".png"), plt,device = "png") - } - return(plotly::ggplotly(plt)) } @@ -2252,6 +2243,30 @@ getCrsFromConfig <- function(folder) { return(NA) } +#####Processing##### + +process_rename_mainmodes<-function(trips_table, + unite.columns = character(0), united.name = "united"){ + + if (length(unite.columns) != 0) { + trips_table$main_mode[grep(paste0(unite.columns, collapse = "|") + , trips_table$main_mode)] <- united.name + } + return(trips_table) +} + +process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ + + trips_table_count <- trips_table %>% + count(main_mode) + if(percentage){ + trips_table_count<- trips_table_count %>% mutate(n = n / sum(n) * 100) + } + + return(trips_table_count) +} + + appendDistanceCategory <- function(tripsTable){ modes = levels(factor(tripsTable$main_mode)) diff --git a/man/compareAverageTravelWait.Rd b/man/compareAverageTravelWait.Rd index ca9c707..ca316ec 100644 --- a/man/compareAverageTravelWait.Rd +++ b/man/compareAverageTravelWait.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{compareAverageTravelWait} \alias{compareAverageTravelWait} \title{Bar Chart with main_mode on x-axis and average travel/wait time on y-axis} diff --git a/man/compareBasePolicyOutput.Rd b/man/compareBasePolicyOutput.Rd index 6190028..16a1b0f 100644 --- a/man/compareBasePolicyOutput.Rd +++ b/man/compareBasePolicyOutput.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{compareBasePolicyOutput} \alias{compareBasePolicyOutput} \title{Chooses a function to compare output_trips from the folders. diff --git a/man/compareBasePolicyShapeOutput.Rd b/man/compareBasePolicyShapeOutput.Rd index 41278b9..a2afee6 100644 --- a/man/compareBasePolicyShapeOutput.Rd +++ b/man/compareBasePolicyShapeOutput.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{compareBasePolicyShapeOutput} \alias{compareBasePolicyShapeOutput} \title{Chooses a function to compare output_trips from the folders. diff --git a/man/compareModalDistanceDistribution.Rd b/man/compareModalDistanceDistribution.Rd index 00f0e9c..ea7f77f 100644 --- a/man/compareModalDistanceDistribution.Rd +++ b/man/compareModalDistanceDistribution.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{compareModalDistanceDistribution} \alias{compareModalDistanceDistribution} \title{Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis} diff --git a/man/compareTripTypesBarChart.Rd b/man/compareTripTypesBarChart.Rd index 8b0ef5e..9748a4f 100644 --- a/man/compareTripTypesBarChart.Rd +++ b/man/compareTripTypesBarChart.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{compareTripTypesBarChart} \alias{compareTripTypesBarChart} \title{Creates BarChart of changing trip types(originating,transit etc) between 2 tables diff --git a/man/deriveODMatrix.Rd b/man/deriveODMatrix.Rd index a616f2e..ef9f9fe 100644 --- a/man/deriveODMatrix.Rd +++ b/man/deriveODMatrix.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{deriveODMatrix} \alias{deriveODMatrix} \title{Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper} diff --git a/man/filterByRegion.Rd b/man/filterByRegion.Rd index 5554dca..d8677a3 100644 --- a/man/filterByRegion.Rd +++ b/man/filterByRegion.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{filterByRegion} \alias{filterByRegion} \title{Filtering of trips_table(from readTripsTable) depending on how they located in given shape} diff --git a/man/getCrsFromConfig.Rd b/man/getCrsFromConfig.Rd index 8aa7289..2401be7 100644 --- a/man/getCrsFromConfig.Rd +++ b/man/getCrsFromConfig.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{getCrsFromConfig} \alias{getCrsFromConfig} \title{Reads an coordinate referenec system of MATSim output directory diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd new file mode 100644 index 0000000..7a20a94 --- /dev/null +++ b/man/matsimr-deprecated.Rd @@ -0,0 +1,49 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\docType{package} +\name{matsimr-deprecated} +\alias{matsimr-deprecated} +\alias{plotModalSplitPieChart} +\alias{plotModalSplitBarChart} +\title{Plot main_mode distribution as a Pie Chart} +\usage{ +plotModalSplitPieChart( + tripsTable, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + only.files = FALSE +) +} +\arguments{ +\item{tripsTable}{tibble of trips_output (from \link{readTripsTable})} + +\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} + +\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} + +\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} + +\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} +} +\value{ +Pie Chart plot of transport mode distribution, values given in percents +} +\description{ +Takes Table trips_output (from \link{readTripsTable}), +to plot pie chart with with values that represent +percentage of using transport modes from trips +} +\details{ +Function automatically detects transport_modes from table +and plots pie chart. +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +} +\section{Details}{ + +\tabular{rl}{ + \code{plot_mainmode_piechart} \tab now a synonym for \code{\link{plotModalSplitPieChart}}\cr + \code{plot_mainmode_barchart} \tab now a synonym for \code{\link{plotModalSplitBarChart}}\cr +} +} + diff --git a/man/plotActivityEndTimes.Rd b/man/plotActivityEndTimes.Rd index 3cc8a26..9a3b92b 100644 --- a/man/plotActivityEndTimes.Rd +++ b/man/plotActivityEndTimes.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{plotActivityEndTimes} \alias{plotActivityEndTimes} \title{Line plot that shows the number of activities ending at a given time, per activity type. diff --git a/man/plotArrivalTimesPerTripPurpose.Rd b/man/plotArrivalTimesPerTripPurpose.Rd index 773b1e9..629cb8f 100644 --- a/man/plotArrivalTimesPerTripPurpose.Rd +++ b/man/plotArrivalTimesPerTripPurpose.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{plotArrivalTimesPerTripPurpose} \alias{plotArrivalTimesPerTripPurpose} \title{This function plots the number of trips ending per trip purpose over time. The trip purpose corresponds to the activity type of the destination activity of a given trip. diff --git a/man/plotAverageTravelWait.Rd b/man/plotAverageTravelWait.Rd index 1f801fb..a8b75d6 100644 --- a/man/plotAverageTravelWait.Rd +++ b/man/plotAverageTravelWait.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{plotAverageTravelWait} \alias{plotAverageTravelWait} \title{Bar Chart with main_mode on x-axis and average travel/wait time on y-axis} diff --git a/man/plotDepartureTimesPerTripPurpose.Rd b/man/plotDepartureTimesPerTripPurpose.Rd index 10f1c8b..a6f0c6f 100644 --- a/man/plotDepartureTimesPerTripPurpose.Rd +++ b/man/plotDepartureTimesPerTripPurpose.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{plotDepartureTimesPerTripPurpose} \alias{plotDepartureTimesPerTripPurpose} \title{This function plots the number of trips starting per trip purpose over time. The trip purpose corresponds to the activity type of the destination activity of a given trip.} diff --git a/man/plotMapWithFilteredTrips.Rd b/man/plotMapWithFilteredTrips.Rd index 7994067..2712476 100644 --- a/man/plotMapWithFilteredTrips.Rd +++ b/man/plotMapWithFilteredTrips.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{plotMapWithFilteredTrips} \alias{plotMapWithFilteredTrips} \title{Plots result of filtered trips on the map (from shape)} diff --git a/man/plotMapWithTrips.Rd b/man/plotMapWithTrips.Rd index 5b76b4a..aab27d7 100644 --- a/man/plotMapWithTrips.Rd +++ b/man/plotMapWithTrips.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{plotMapWithTrips} \alias{plotMapWithTrips} \title{Plots start and end coordinates of the given trips table on an osm map} diff --git a/man/plotMapWithTripsType.Rd b/man/plotMapWithTripsType.Rd index a6cdc0f..87814b0 100644 --- a/man/plotMapWithTripsType.Rd +++ b/man/plotMapWithTripsType.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{plotMapWithTripsType} \alias{plotMapWithTripsType} \title{Plots every type of trips(inside, outside, origin and destinating) on map} diff --git a/man/plotModalDistanceDistribution.Rd b/man/plotModalDistanceDistribution.Rd index 9f8d21a..e29ced2 100644 --- a/man/plotModalDistanceDistribution.Rd +++ b/man/plotModalDistanceDistribution.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{plotModalDistanceDistribution} \alias{plotModalDistanceDistribution} \title{Bar Chart with distance travelled on x-axis and number of trips on y-axis} diff --git a/man/plotModalShiftBar.Rd b/man/plotModalShiftBar.Rd index 34d6ffe..460d9c2 100644 --- a/man/plotModalShiftBar.Rd +++ b/man/plotModalShiftBar.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{plotModalShiftBar} \alias{plotModalShiftBar} \title{Plot bar chart diagram of transport mode changes} diff --git a/man/plotModalShiftSankey.Rd b/man/plotModalShiftSankey.Rd index 92534de..bbc87f2 100644 --- a/man/plotModalShiftSankey.Rd +++ b/man/plotModalShiftSankey.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{plotModalShiftSankey} \alias{plotModalShiftSankey} \title{Plot alluvial/sankey diagram of transport mode changes} diff --git a/man/plotTripCountByDepTime.Rd b/man/plotTripCountByDepTime.Rd index dce7c72..89f0329 100644 --- a/man/plotTripCountByDepTime.Rd +++ b/man/plotTripCountByDepTime.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{plotTripCountByDepTime} \alias{plotTripCountByDepTime} \title{Line plot with departure time x-axis and number of trips on y-axis} diff --git a/man/plotTripDistanceByMode.Rd b/man/plotTripDistanceByMode.Rd index 5dc6863..0bc5119 100644 --- a/man/plotTripDistanceByMode.Rd +++ b/man/plotTripDistanceByMode.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{plotTripDistanceByMode} \alias{plotTripDistanceByMode} \title{Bar Chart with distance travelled on x-axis and number of trips on y-axis} diff --git a/man/plotTripDistancedByType.Rd b/man/plotTripDistancedByType.Rd index 4225d61..18d1c3c 100644 --- a/man/plotTripDistancedByType.Rd +++ b/man/plotTripDistancedByType.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{plotTripDistancedByType} \alias{plotTripDistancedByType} \title{Bar Chart with tripType on x-axis and travelled distance on y-axis} diff --git a/man/plotTripTypesPieChart.Rd b/man/plotTripTypesPieChart.Rd index 23368ae..894363b 100644 --- a/man/plotTripTypesPieChart.Rd +++ b/man/plotTripTypesPieChart.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{plotTripTypesPieChart} \alias{plotTripTypesPieChart} \title{Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart} diff --git a/man/plotModalSplitBarChart.Rd b/man/plot_mainmode_barchart.Rd similarity index 89% rename from man/plotModalSplitBarChart.Rd rename to man/plot_mainmode_barchart.Rd index ce948f3..0fa2687 100644 --- a/man/plotModalSplitBarChart.Rd +++ b/man/plot_mainmode_barchart.Rd @@ -1,26 +1,26 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R -\name{plotModalSplitBarChart} -\alias{plotModalSplitBarChart} +% Please edit documentation in R/output_trips.R +\name{plot_mainmode_barchart} +\alias{plot_mainmode_barchart} \title{Plot main_mode distribution as a bar Chart} \usage{ -plotModalSplitBarChart( - tripsTable, +plot_mainmode_barchart( + trips_table, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE + percentage = FALSE ) } \arguments{ -\item{tripsTable}{tible of trips_output (from readTripsTable())} - \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} \item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} \item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} +\item{tripsTable}{tible of trips_output (from readTripsTable())} + \item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} } \value{ diff --git a/man/plotModalSplitPieChart.Rd b/man/plot_mainmode_piechart.Rd similarity index 86% rename from man/plotModalSplitPieChart.Rd rename to man/plot_mainmode_piechart.Rd index ab529e0..375969c 100644 --- a/man/plotModalSplitPieChart.Rd +++ b/man/plot_mainmode_piechart.Rd @@ -1,26 +1,25 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R -\name{plotModalSplitPieChart} -\alias{plotModalSplitPieChart} +% Please edit documentation in R/output_trips.R +\name{plot_mainmode_piechart} +\alias{plot_mainmode_piechart} \title{Plot main_mode distribution as a Pie Chart} \usage{ -plotModalSplitPieChart( - tripsTable, +plot_mainmode_piechart( + trips_table, unite.columns = character(0), united.name = "united", - dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE + dump.output.to = matsimDumpOutputDirectory ) } \arguments{ -\item{tripsTable}{tibble of trips_output (from \link{readTripsTable})} - \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} \item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} \item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} +\item{tripsTable}{tibble of trips_output (from \link{readTripsTable})} + \item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} } \value{ diff --git a/man/readTripsTable.Rd b/man/readTripsTable.Rd index fececb1..1081a70 100644 --- a/man/readTripsTable.Rd +++ b/man/readTripsTable.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{readTripsTable} \alias{readTripsTable} \title{Load MATSIM output_trips table into Memory} diff --git a/man/transformToSf.Rd b/man/transformToSf.Rd index ec28139..3a4f6c6 100644 --- a/man/transformToSf.Rd +++ b/man/transformToSf.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tripsOutput.R +% Please edit documentation in R/output_trips.R \name{transformToSf} \alias{transformToSf} \title{Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature)} diff --git a/tests/testthat/test-tripsOutput.R b/tests/testthat/test-output_trips.R similarity index 100% rename from tests/testthat/test-tripsOutput.R rename to tests/testthat/test-output_trips.R From 21eb4098b46107d84625e3b6cfca0eac99c47af1 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Tue, 23 May 2023 13:31:01 +0200 Subject: [PATCH 03/87] changed matsimr-deprecated --- R/output_trips.R | 21 ++++++++------------- man/matsimr-deprecated.Rd | 25 +++---------------------- 2 files changed, 11 insertions(+), 35 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 21b8905..e23dd0c 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -64,25 +64,20 @@ readTripsTable <- function(input_path = ".", n_max = Inf) { #####Deprecated#### + + + #' Plot main_mode distribution as a Pie Chart #' -#' Takes Table trips_output (from \link{readTripsTable}), -#' to plot pie chart with with values that represent -#' percentage of using transport modes from trips #' -#' Function automatically detects transport_modes from table -#' and plots pie chart. -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' These functions are provided for compatibility with older version of +#' the yourPackageName package. They may eventually be completely +#' removed. +#' +#' #' #' @rdname matsimr-deprecated #' @name matsimr-deprecated -#' @param tripsTable tibble of trips_output (from \link{readTripsTable}) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' -#' @return Pie Chart plot of transport mode distribution, values given in percents #' #' @docType package #' @export plotModalSplitPieChart plotModalSplitBarChart diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 7a20a94..51b8f3e 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -15,29 +15,10 @@ plotModalSplitPieChart( only.files = FALSE ) } -\arguments{ -\item{tripsTable}{tibble of trips_output (from \link{readTripsTable})} - -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} - -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} - -\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} -} -\value{ -Pie Chart plot of transport mode distribution, values given in percents -} \description{ -Takes Table trips_output (from \link{readTripsTable}), -to plot pie chart with with values that represent -percentage of using transport modes from trips -} -\details{ -Function automatically detects transport_modes from table -and plots pie chart. -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +These functions are provided for compatibility with older version of +the yourPackageName package. They may eventually be completely +removed. } \section{Details}{ From 56242df56f94c704662300165a1fa23e2c74bd2b Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Tue, 23 May 2023 13:34:44 +0200 Subject: [PATCH 04/87] changes in deprecated documentation --- R/output_trips.R | 8 ++++---- man/matsimr-deprecated.Rd | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index e23dd0c..5514aab 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -67,11 +67,11 @@ readTripsTable <- function(input_path = ".", n_max = Inf) { -#' Plot main_mode distribution as a Pie Chart +#' Deprecated function(s) in the matsimr package #' #' #' These functions are provided for compatibility with older version of -#' the yourPackageName package. They may eventually be completely +#' the matsimr package. They may eventually be completely #' removed. #' #' @@ -84,8 +84,8 @@ readTripsTable <- function(input_path = ".", n_max = Inf) { #' @aliases plotModalSplitPieChart plotModalSplitBarChart #' @section Details: #' \tabular{rl}{ -#' \code{plot_mainmode_piechart} \tab now a synonym for \code{\link{plotModalSplitPieChart}}\cr -#' \code{plot_mainmode_barchart} \tab now a synonym for \code{\link{plotModalSplitBarChart}}\cr +#' \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr +#' \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}}\cr #' } #' plotModalSplitPieChart <- function(tripsTable, diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 51b8f3e..37c0c2b 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -5,7 +5,7 @@ \alias{matsimr-deprecated} \alias{plotModalSplitPieChart} \alias{plotModalSplitBarChart} -\title{Plot main_mode distribution as a Pie Chart} +\title{Deprecated function(s) in the matsimr package} \usage{ plotModalSplitPieChart( tripsTable, @@ -17,14 +17,14 @@ plotModalSplitPieChart( } \description{ These functions are provided for compatibility with older version of -the yourPackageName package. They may eventually be completely +the matsimr package. They may eventually be completely removed. } \section{Details}{ \tabular{rl}{ - \code{plot_mainmode_piechart} \tab now a synonym for \code{\link{plotModalSplitPieChart}}\cr - \code{plot_mainmode_barchart} \tab now a synonym for \code{\link{plotModalSplitBarChart}}\cr + \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr + \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}}\cr } } From 60f2cc84de9f739dee7350d2f1c64656a288baf2 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 24 May 2023 13:08:41 +0200 Subject: [PATCH 05/87] test of multiple rdname functions --- R/output_trips.R | 21 +++++++++++++++++++++ man/matsimr-deprecated.Rd | 21 +++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/R/output_trips.R b/R/output_trips.R index 5514aab..5fc7456 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -175,6 +175,27 @@ plotModalSplitPieChart <- function(tripsTable, } } +#' Deprecated function(s) in the matsimr package +#' +#' +#' These functions are provided for compatibility with older version of +#' the matsimr package. They may eventually be completely +#' removed. +#' +#' Test of usage +#' +#' @rdname matsimr-deprecated +#' @name matsimr-deprecated +#' +#' @docType package +#' @export plotModalSplitBarChart +#' @aliases plotModalSplitBarChart +#' @section Details: +#' \tabular{rl}{ +#' \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr +#' \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}}\cr +#' } +#' plotModalSplitBarChart <- function(tripsTable, unite.columns = character(0), united.name = "united", diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 37c0c2b..549cba9 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -14,14 +14,35 @@ plotModalSplitPieChart( dump.output.to = matsimDumpOutputDirectory, only.files = FALSE ) + +plotModalSplitBarChart( + tripsTable, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + only.files = FALSE +) } \description{ These functions are provided for compatibility with older version of the matsimr package. They may eventually be completely removed. + +These functions are provided for compatibility with older version of +the matsimr package. They may eventually be completely +removed. +} +\details{ +Test of usage } \section{Details}{ +\tabular{rl}{ + \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr + \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}}\cr +} + + \tabular{rl}{ \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}}\cr From 9131ddba8d8532b8900a4eef729ae3c5d362d4e9 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 24 May 2023 13:12:53 +0200 Subject: [PATCH 06/87] removed redundant tags --- R/output_trips.R | 16 ++-------------- man/matsimr-deprecated.Rd | 13 ------------- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 5fc7456..5d7058e 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -80,8 +80,8 @@ readTripsTable <- function(input_path = ".", n_max = Inf) { #' @name matsimr-deprecated #' #' @docType package -#' @export plotModalSplitPieChart plotModalSplitBarChart -#' @aliases plotModalSplitPieChart plotModalSplitBarChart +#' @export plotModalSplitPieChart +#' @aliases plotModalSplitPieChart #' @section Details: #' \tabular{rl}{ #' \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr @@ -178,23 +178,11 @@ plotModalSplitPieChart <- function(tripsTable, #' Deprecated function(s) in the matsimr package #' #' -#' These functions are provided for compatibility with older version of -#' the matsimr package. They may eventually be completely -#' removed. -#' -#' Test of usage -#' #' @rdname matsimr-deprecated -#' @name matsimr-deprecated #' #' @docType package #' @export plotModalSplitBarChart #' @aliases plotModalSplitBarChart -#' @section Details: -#' \tabular{rl}{ -#' \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr -#' \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}}\cr -#' } #' plotModalSplitBarChart <- function(tripsTable, unite.columns = character(0), diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 549cba9..522f689 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -27,22 +27,9 @@ plotModalSplitBarChart( These functions are provided for compatibility with older version of the matsimr package. They may eventually be completely removed. - -These functions are provided for compatibility with older version of -the matsimr package. They may eventually be completely -removed. -} -\details{ -Test of usage } \section{Details}{ -\tabular{rl}{ - \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr - \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}}\cr -} - - \tabular{rl}{ \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}}\cr From ae2c33b80eeff22fbd46aee0d1ad8a1cc230218b Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 24 May 2023 13:55:49 +0200 Subject: [PATCH 07/87] added process travtime and plot travtime --- NAMESPACE | 2 + R/output_trips.R | 1026 +++++++++-------- man/matsimr-deprecated.Rd | 13 + man/plot_mainmode_barchart.Rd | 4 +- man/plot_mainmode_piechart.Rd | 4 +- ...d => plot_travelwaittime_mean_barchart.Rd} | 13 +- ...readTripsTable.Rd => read_output_trips.Rd} | 6 +- 7 files changed, 584 insertions(+), 484 deletions(-) rename man/{plotAverageTravelWait.Rd => plot_travelwaittime_mean_barchart.Rd} (84%) rename man/{readTripsTable.Rd => read_output_trips.Rd} (82%) diff --git a/NAMESPACE b/NAMESPACE index 17cb27d..547d9d8 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -31,6 +31,7 @@ export(plotTripDistancedByType) export(plotTripTypesPieChart) export(plot_mainmode_barchart) export(plot_mainmode_piechart) +export(plot_travelwaittime_mean_barchart) export(prepareComparisonSimwrapperDashboardFromTable) export(prepareSimwrapperDashboardFromFolder) export(prepareSimwrapperDashboardFromTable) @@ -40,6 +41,7 @@ export(readCounts) export(readLinkStats) export(readPersonsTable) export(readTripsTable) +export(read_output_trips) export(symlog_trans) export(transformToSf) import(dplyr) diff --git a/R/output_trips.R b/R/output_trips.R index 5d7058e..38dec94 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -4,63 +4,7 @@ matsimDumpOutputDirectory <- "./matsim_r_output" dashboard_file <- "/dashboard-1-trips.yaml" -#####Reading##### - - -#' Load MATSIM output_trips table into Memory -#' -#' Loads a MATSim CSV output_trips from file or archive, -#' creating a tibble with columns as in csv file -#' -#' @param input_path character string, path to matsim output directory or http link to the file. -#' @param n_max integer, maximum number of lines to read within output_trips -#' @return tibble of trips_output -#' -#' @export -readTripsTable <- function(input_path = ".", n_max = Inf) { - options(digits = 18) - trips_file <- "" - - # if input_path is a directory, find the correct file path within it - if(dir.exists(input_path)){ - files <- list.files(input_path, full.names = TRUE) - trip_file_indicies <- grep("output_trips.csv.gz$", files) - - if(length(trip_file_indicies) == 1){ - trips_file <- files[trip_file_indicies] - } else { - stop('There is supposed to be a single "output_trips.csv.gz" found in directory') - } - } else { - trips_file <- input_path - } - - trips_output_table <- read_delim(trips_file, - delim = ";", - locale = locale(decimal_mark = "."), - n_max = n_max, - col_types = cols( - start_x = col_character(), - start_y = col_character(), - end_x = col_character(), - end_y = col_character(), - end_link = col_character(), - start_link = col_character() - ) - ) - # person is mostly integer, but contains also chars(see Hamburg 110813 observation) - # doesn't reads coordinates correctly - trips_output_table <- trips_output_table %>% - mutate( - start_x = as.double(start_x), - start_y = as.double(start_y), - end_x = as.double(end_x), - end_y = as.double(end_y) - ) - attr(trips_output_table,"table_name") <- trips_file - return(trips_output_table) -} #####Deprecated#### @@ -86,6 +30,7 @@ readTripsTable <- function(input_path = ".", n_max = Inf) { #' \tabular{rl}{ #' \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr #' \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}}\cr +#' \code{readTripsTable} \tab now a synonym for \code{\link{read_output_trips}}\cr #' } #' plotModalSplitPieChart <- function(tripsTable, @@ -269,6 +214,119 @@ plotModalSplitBarChart <- function(tripsTable, } } + +#' Deprecated function(s) in the matsimr package +#' +#' +#' @rdname matsimr-deprecated +#' +#' @docType package +#' @export readTripsTable +#' @aliases readTripsTable +#' +readTripsTable <-function(input_path = ".", n_max = Inf) { + .Deprecated("read_output_trips") + return(read_output_trips(input_path,n_max)) +} + +#' Deprecated function(s) in the matsimr package +#' +#' +#' @rdname matsimr-deprecated +#' +#' @docType package +#' @export plotAverageTravelWait +#' @aliases plotAverageTravelWait +#' +plotAverageTravelWait <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, + only.files = FALSE) { + + # If some columns should be united + if (length(unite.columns) != 0) { + tripsTable$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable$main_mode)] <- united.name + } + + avg_time = tripsTable %>% group_by(main_mode)%>% + summarize(trav_time_avg = hms::hms(seconds_to_period(mean(trav_time))), + wait_time_avg = hms::hms(seconds_to_period(mean(wait_time)))) %>% + mutate(trav_time_avg = minute(trav_time_avg),wait_time_avg = minute(wait_time_avg)) + + + fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") + fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") + fig = fig %>% layout(yaxis = list(title = "Time spent (in minutes)"),barmode = "group") + + + #plotting + if(!only.files){ + + fig + return(fig) + } + +} + + +#####Reading##### + + +#' Load MATSIM output_trips table into Memory +#' +#' Loads a MATSim CSV output_trips from file or archive, +#' creating a tibble with columns as in csv file +#' +#' @param input_path character string, path to matsim output directory or http link to the file. +#' @param n_max integer, maximum number of lines to read within output_trips +#' @return tibble of trips_output +#' +#' @export +read_output_trips <- function(input_path = ".", n_max = Inf) { + options(digits = 18) + trips_file <- "" + + # if input_path is a directory, find the correct file path within it + if(dir.exists(input_path)){ + files <- list.files(input_path, full.names = TRUE) + trip_file_indicies <- grep("output_trips.csv.gz$", files) + + if(length(trip_file_indicies) == 1){ + trips_file <- files[trip_file_indicies] + } else { + stop('There is supposed to be a single "output_trips.csv.gz" found in directory') + } + } else { + trips_file <- input_path + } + + trips_output_table <- read_delim(trips_file, + delim = ";", + locale = locale(decimal_mark = "."), + n_max = n_max, + col_types = cols( + start_x = col_character(), + start_y = col_character(), + end_x = col_character(), + end_y = col_character(), + end_link = col_character(), + start_link = col_character() + ) + ) + # person is mostly integer, but contains also chars(see Hamburg 110813 observation) + # doesn't reads coordinates correctly + trips_output_table <- trips_output_table %>% + mutate( + start_x = as.double(start_x), + start_y = as.double(start_y), + end_x = as.double(end_x), + end_y = as.double(end_y) + ) + attr(trips_output_table,"table_name") <- trips_file + return(trips_output_table) + +} + + + #####Plotting##### #' Plot main_mode distribution as a Pie Chart @@ -281,7 +339,7 @@ plotModalSplitBarChart <- function(tripsTable, #' and plots pie chart. #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' -#' @param tripsTable tibble of trips_output (from \link{readTripsTable}) +#' @param trips_table tibble of trips_output (from \link{readTripsTable}) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored @@ -325,7 +383,7 @@ plot_mainmode_piechart <- function(trips_table, #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' #' -#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param trips_table tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored @@ -366,7 +424,7 @@ plot_mainmode_barchart <- function(trips_table, #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' #' -#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param trips_table tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored @@ -375,31 +433,29 @@ plot_mainmode_barchart <- function(trips_table, #' @return Bar Chart plot of average time spent on travel/wait #' #' @export -plotAverageTravelWait <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE) { +plot_travelwaittime_mean_barchart <- function(trips_table, + unite.columns = character(0), + united.name = "united", + time_format = "minute") { # If some columns should be united - if (length(unite.columns) != 0) { - tripsTable$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable$main_mode)] <- united.name - } - - avg_time = tripsTable %>% group_by(main_mode)%>% - summarize(trav_time_avg = hms::hms(seconds_to_period(mean(trav_time))), - wait_time_avg = hms::hms(seconds_to_period(mean(wait_time)))) %>% - mutate(trav_time_avg = minute(trav_time_avg),wait_time_avg = minute(wait_time_avg)) - - - fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") - fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") - fig = fig %>% layout(yaxis = list(title = "Time spent (in minutes)"),barmode = "group") + trips_table <- process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, + united.name = united.name) + #processing of result table + avg_time = process_get_travelwaittime_by_mainmode(trips_table,time_format = time_format) #plotting - if(!only.files){ + fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling", + text = round(avg_time$trav_time_avg,2)) + fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting", + text = round(avg_time$wait_time_avg,2)) + fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)"),barmode = "group")) - fig - return(fig) - } + + fig + return(fig) } @@ -1174,189 +1230,56 @@ plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FA return(plotly::ggplotly(plt)) } -#' Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature) -#' -#' Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features -#' deletes from resulting data.frame start_x, end_x, start_y, end_y. -#' And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring() -#' Or adds start_wkt and end_wkt, if geometry.type = st_point() -#' Added column/columns projected to given CRS (coordinate reference system), -#' that can be taken from network file of MATSimOutputDirectory + + +#' Plots result of filtered trips on the map (from shape) #' -#' Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" -#' to get which type of table was generated, if it is needed +#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file)) +#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +#' and filters the trips from table depending on *.inshape flags: +#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape +#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +#' result of filtering is plotted on map of shapeTable where green points are startpoints of trip and red points are endpoints of trip #' #' @param table tibble of trips_output (from readTripsTable()) #' +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' #' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' -#' @param geometry.type function of sf transformation, geometry.type can be (by default is st_multipoint()) -#' !!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or -#' !!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or -#' !!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!! +#' @param start.inshape bool, defines trips to conclude (see Description) #' -#' @return sf object (data.frame with geometries depending to geometry.type) +#' @param end.inshape bool, defines trips to conclude (see Description) +#' +#' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot +#' +#' +#' @return plot with trips filtered depending on flags *.inshape on map from shapeTable #' #' @export -transformToSf <- function(table, crs, geometry.type = st_multipoint()) { - if (class(geometry.type)[2] == "POINT") { - table1 <- table %>% - # mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep ="")) - mutate(start_wkt = paste("POINT(", start_x, " ", start_y, ")", sep = "")) - table2 <- table %>% - mutate(end_wkt = paste("POINT(", end_x, " ", end_y, ")", sep = "")) - attr(table, "geometry.type") <- "POINT" - - - table1_wkt <- st_as_sf(table1, wkt = "start_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - table2_wkt <- st_as_sf(table2, wkt = "end_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - - - result_table <- table1_wkt %>% mutate(end_wkt = table2_wkt$end_wkt) - st_geometry(result_table) <- "start_wkt" - st_crs(result_table) <- crs - st_geometry(result_table) <- "end_wkt" - st_crs(result_table) <- crs - st_geometry(result_table) <- "start_wkt" - return(result_table) - } else if (class(geometry.type)[2] == "MULTIPOINT") { - table <- table %>% - mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) - attr(table, "geometry.type") <- "MULTIPOINT" - - - result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - - st_crs(result_table) <- crs - return(result_table) - } else if (class(geometry.type)[2] == "LINESTRING") { - table <- table %>% - mutate(wkt = paste("LINESTRING(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) - attr(table, "geometry.type") <- "LINESTRING" - - - result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - - st_crs(result_table) <- crs - return(result_table) - } else { - return(NA) - } -} - -#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape -#' -#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) -#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -#' and filters the trips from table depending on *.inshape flags: -#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape -#' -#' @param tripsTable tibble of trips_output (from readTripsTable()) -#' -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) -#' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation -#' -#' @param start.inshape bool, defines trips to conclude (see Description) -#' -#' @param end.inshape bool, defines trips to conclude (see Description) -#' -#' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) -#' -#' @export -filterByRegion <- function(tripsTable, shapeTable, crs, start.inshape = TRUE, end.inshape = TRUE) { - - # shapeTable <- st_read(shapeFile) - if (st_crs(shapeTable) == NA) { - st_crs(shapeTable) <- crs - } - - sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) - shapeTable <- st_transform(shapeTable, crs = crs) - # shapeTable isn't table - shape - - union_shape <- st_union(shapeTable) # transforms the crs back to the previous in the file - union_shape <- st_transform(union_shape, crs = st_crs(shapeTable)) - - - st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry - cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile - - st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry - cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile - - # get trips that ended outside of shape - cont_end_outside <- setdiff(1:nrow(sf_table), cont2) - - # get trips that started outside of shape - cont_start_outside <- setdiff(1:nrow(sf_table), cont1) - - if (start.inshape == TRUE && end.inshape == TRUE) { - cont_union <- intersect(cont1, cont2) - } else if (start.inshape == TRUE && end.inshape == FALSE) { - cont_union <- intersect(cont1, cont_end_outside) - } else if (start.inshape == FALSE && end.inshape == TRUE) { - cont_union <- intersect(cont2, cont_start_outside) - } else { - cont_union <- intersect(cont_start_outside, cont_end_outside) # Give back trips that are neither starting and ending outside the area - } - - - return(tripsTable[cont_union, ]) -} - -#' Plots result of filtered trips on the map (from shape) -#' -#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file)) -#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -#' and filters the trips from table depending on *.inshape flags: -#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape -#' result of filtering is plotted on map of shapeTable where green points are startpoints of trip and red points are endpoints of trip -#' -#' @param table tibble of trips_output (from readTripsTable()) -#' -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) -#' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation -#' -#' @param start.inshape bool, defines trips to conclude (see Description) -#' -#' @param end.inshape bool, defines trips to conclude (see Description) -#' -#' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot -#' -#' -#' @return plot with trips filtered depending on flags *.inshape on map from shapeTable -#' -#' @export -plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRUE, end.inshape = TRUE, optimized = FALSE) { - # table = table[1:5000,] #To make plotting faster - # table_sf = transformToSf(table,crs = crs) - filtered <- filterByRegion(table, shapeTable, crs = crs, start.inshape, end.inshape) - if (nrow(filtered) == 0) { - ggplot() + - geom_sf(data = shapeTable) - warning("there is no trip filtered for this map") - } - filtered_sf <- transformToSf(filtered, crs = crs, geometry.type = st_point()) - st_geometry(filtered_sf) <- "start_wkt" - filtered_sf_start <- filtered_sf %>% select(-end_wkt) - st_geometry(filtered_sf) <- "end_wkt" - filtered_sf_end <- filtered_sf %>% select(-start_wkt) - # shape = st_read(shapePath) - if (st_crs(shapeTable) == NA) { - ct_crs(shapeTable) <- crs - } - shapeTable <- st_transform(shapeTable, crs = "+proj=longlat +datum=WGS84 +no_defs") - filtered_sf_start <- st_transform(filtered_sf_start, "+proj=longlat +datum=WGS84 +no_defs") - filtered_sf_end <- st_transform(filtered_sf_end, "+proj=longlat +datum=WGS84 +no_defs") +plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRUE, end.inshape = TRUE, optimized = FALSE) { + # table = table[1:5000,] #To make plotting faster + # table_sf = transformToSf(table,crs = crs) + filtered <- filterByRegion(table, shapeTable, crs = crs, start.inshape, end.inshape) + if (nrow(filtered) == 0) { + ggplot() + + geom_sf(data = shapeTable) + warning("there is no trip filtered for this map") + } + filtered_sf <- transformToSf(filtered, crs = crs, geometry.type = st_point()) + st_geometry(filtered_sf) <- "start_wkt" + filtered_sf_start <- filtered_sf %>% select(-end_wkt) + st_geometry(filtered_sf) <- "end_wkt" + filtered_sf_end <- filtered_sf %>% select(-start_wkt) + # shape = st_read(shapePath) + if (st_crs(shapeTable) == NA) { + ct_crs(shapeTable) <- crs + } + shapeTable <- st_transform(shapeTable, crs = "+proj=longlat +datum=WGS84 +no_defs") + filtered_sf_start <- st_transform(filtered_sf_start, "+proj=longlat +datum=WGS84 +no_defs") + filtered_sf_end <- st_transform(filtered_sf_end, "+proj=longlat +datum=WGS84 +no_defs") if (optimized) { colors <- c("Start" = "blue", "End" = "red") @@ -1936,202 +1859,67 @@ plotMapWithTripsType <- function(table, shapeTable, crs, optimized = FALSE) { return(plt) } -#' Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper -#' -#' -#' -#' @param tripsTable table of output trips(from readTripsTable) or path to trips_output file -#' -#' @param shapePath full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name) + + +#' Chooses a function to compare output_trips from the folders. +#' baseFolder contains all base outputs, policyFolder contains all policy outputs. #' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' -#' @param dump.output.to path to a folder to save csv file of ODMatrix #' -#' @param colnames if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values +#' @param baseFolder specifies data source folder with multiple base output_trips #' -#' @param simwrapper create output in a simwrapper form if set to path of the shapefile +#' @param policyFolder specifies data source folder with multiple policy output_trips #' -#' @param outer logical that represent if the table should contain outside flow of the shape, it isn't +#' @param dump.output.to that saves result of all comparisons between each base and each policy. +#' For now it creates plotModalShiftBar() for the output_trips #' -#' @return tibble of origin/destination matrix +#' @return list of tibbles, list of all base and policy output_trips as tibble #' #' @export -deriveODMatrix<- function(tripsTable,shapePath,crs,dump.output.to = matsimDumpOutputDirectory,simwrapper = FALSE,colnames = "numeric",outer = FALSE){ - defaultW <- getOption("warn") - options(warn = -1) +compareBasePolicyOutput <- function(baseFolder,policyFolder,dump.output.to = matsimDumpOutputDirectory) { - #if tripstable given as folder/file - if(sum(class(tripsTable) %in% c("tbl_df","tbl","data.frame"))<1){ - tripsTable <- readTripsTable(tripsTable) + base_trips = list(NULL) + policy_trips = list(NULL) + for(file in list.files(baseFolder,full.names = TRUE)) + { + temp = readTripsTable(file) + if(!is.null(temp)){ + attr(temp,"table_name") = strsplit(file,'/')[[1]][-1] + if(is.null(base_trips[[1]])){ + base_trips[[1]] = temp + }else{ + base_trips = append(base_trips,list(temp)) + } + } } - sfTable <- transformToSf(tripsTable,crs,geometry.type = st_point()) - - shape = st_read(shapePath) - - if (st_crs(shape) == NA) { - st_crs(shape) <- crs + for(file in list.files(policyFolder,full.names = TRUE)) + { + temp = readTripsTable(file) + if(!is.null(temp)){ + attr(temp,"table_name") = strsplit(file,'/')[[1]][-1] + if(is.null(policy_trips[[1]])){ + policy_trips[[1]] = temp + }else{ + policy_trips = append(policy_trips,list(temp)) + } + } } - shape = st_transform(shape,crs = crs) - - sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) - - sf_start = sfTable %>% select(trip_id,start_wkt) - st_geometry(sfTable) = "end_wkt" - sf_end = sfTable %>% select(trip_id,end_wkt) - - #Get all inner intersects - sf_intersect_start = st_contains(shape,sf_start) - sf_intersect_end = st_contains(shape,sf_end) - - - if(outer == TRUE){ - #Get all outer intersects - joined_shape = st_union(shape) - - start_inside = st_contains(joined_shape,sf_start) - end_inside = st_contains(joined_shape,sf_end) - - start_outside = 1:nrow(sf_start) - end_outside = 1:nrow(sf_end) - - start_outside = start_outside[! start_outside %in% start_inside[[1]]] - - end_outside = end_outside[! end_outside %in% end_inside[[1]]] + i = 0; - sf_intersect_start = append(sf_intersect_start,list(start_outside)) - sf_intersect_end = append(sf_intersect_end,list(end_outside)) + print(dump.output.to) + if (!file.exists(dump.output.to)) { + dir.create(dump.output.to) } + for(base in base_trips){ - # Create matrix out of it - result_tibble = as_tibble(data.frame(matrix(nrow=0,ncol=nrow(shape)))) - colnames(result_tibble) = 1:nrow(shape) - - for(i in 1:length(sf_intersect_start)){ - temp = c() - for(j in 1:length(sf_intersect_start)){ - start_i = sf_intersect_start[[i]] - end_j = sf_intersect_end[[j]] - - number_of_trips = length(intersect(start_i,end_j)) - - temp = append(temp,number_of_trips) - - } - result_tibble = rbind(result_tibble,temp) - } - - if(colnames!="numeric" & colnames %in% colnames(shape)){ - colnames(result_tibble) = shape[[colnames]] - if(outer == TRUE){ - rownames(result_tibble) = c(shape[[colnames]],"outer") - colnames(result_tibble)[length(colnames(result_tibble))] = "outer" - }else{ - rownames(result_tibble) = shape[[colnames]] - } - - }else{ - colnames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) - rownames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) - } - - - result_melt = melt(as.matrix(result_tibble)) - colnames(result_melt) = c("origin","destination",1) - # Generating yaml and output_files - - - - if (file.exists(dump.output.to) & simwrapper == TRUE) { - write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") - } else if(!file.exists(dump.output.to) & simwrapper == TRUE) { - dir.create(dump.output.to) - write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") - } else if (file.exists(dump.output.to) & simwrapper == FALSE) { - write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) - } else { - dir.create(dump.output.to) - write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) - } - - yaml_list <- list( - title = "OD Flow", - description = "generated by deriveODMatrix", - projection = st_crs(shape)$input, - shpFile = paste0("../",shapePath), - dbfFile = paste0("../",substr(shapePath,start = 1,stop = nchar(shapePath)-3),"dbf"), - scaleFactor = 1, - lineWidth = 50, - csvFile = "ODMatrix.csv", - idColumn = colnames(shape)[1] # at the moment idColumn of shapefile should be the first column - - ) - write_yaml(yaml_list, paste0(dump.output.to, "/viz-od-flow.yaml")) - - options(warn = defaultW) - return(result_tibble) -} - -#' Chooses a function to compare output_trips from the folders. -#' baseFolder contains all base outputs, policyFolder contains all policy outputs. -#' -#' -#' -#' @param baseFolder specifies data source folder with multiple base output_trips -#' -#' @param policyFolder specifies data source folder with multiple policy output_trips -#' -#' @param dump.output.to that saves result of all comparisons between each base and each policy. -#' For now it creates plotModalShiftBar() for the output_trips -#' -#' @return list of tibbles, list of all base and policy output_trips as tibble -#' -#' @export -compareBasePolicyOutput <- function(baseFolder,policyFolder,dump.output.to = matsimDumpOutputDirectory) { - - base_trips = list(NULL) - policy_trips = list(NULL) - for(file in list.files(baseFolder,full.names = TRUE)) - { - temp = readTripsTable(file) - if(!is.null(temp)){ - attr(temp,"table_name") = strsplit(file,'/')[[1]][-1] - if(is.null(base_trips[[1]])){ - base_trips[[1]] = temp - }else{ - base_trips = append(base_trips,list(temp)) - } - } - } - - for(file in list.files(policyFolder,full.names = TRUE)) - { - temp = readTripsTable(file) - if(!is.null(temp)){ - attr(temp,"table_name") = strsplit(file,'/')[[1]][-1] - if(is.null(policy_trips[[1]])){ - policy_trips[[1]] = temp - }else{ - policy_trips = append(policy_trips,list(temp)) - } - } - } - i = 0; - - print(dump.output.to) - if (!file.exists(dump.output.to)) { - dir.create(dump.output.to) - } - for(base in base_trips){ - - for(policy in policy_trips){ - print(paste0(i," comparison")) - name = paste0(i,"_",attr(base,"table_name"),"--",attr(policy,"table_name")) - plotModalShiftBar(base, - policy, - dump.output.to = dump.output.to, - output.name = name) + for(policy in policy_trips){ + print(paste0(i," comparison")) + name = paste0(i,"_",attr(base,"table_name"),"--",attr(policy,"table_name")) + plotModalShiftBar(base, + policy, + dump.output.to = dump.output.to, + output.name = name) i=i+1 } @@ -2208,44 +1996,7 @@ compareBasePolicyShapeOutput <- function(baseFolder,policyFolder,shapeFilePath,c -#' Reads an coordinate referenec system of MATSim output directory -#' from output_config.xml -#' -#' @param folder specifies path to find config -#' -#' -#' @return code of coordinate reference system -#' -#' @export -getCrsFromConfig <- function(folder) { - - if (grepl("output_config.xml$", folder) == TRUE) - { - config <- read_xml(folder) - - param_nodes = xml_find_all(config,"//param") - - coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] - - coord_system = xml_attr(coord_node,"value") - return(coord_system) - } - files <- list.files(folder, full.names = TRUE) - # Read from global/local directory - # output_config.xml is contained as output_trips.csv.gz - if (length(grep("output_config.xml$", files)) != 0) { - config <- read_xml(files[grep("output_config.xml$", files)]) - - param_nodes = xml_find_all(config,"//param") - - coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] - - coord_system = xml_attr(coord_node,"value") - return(coord_system) - } - return(NA) -} #####Processing##### @@ -2270,6 +2021,27 @@ process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ return(trips_table_count) } +process_get_travelwaittime_by_mainmode<-function(trips_table, + time_format = "minute"){#also could be hours/seconds + + #get 2 columns with mean travel time and mean wait time grouped by main_mode in seconds + avg_time = trips_table %>% group_by(main_mode)%>% + summarize(trav_time_avg = hms::hms(seconds_to_period(mean(trav_time))), + wait_time_avg = hms::hms(seconds_to_period(mean(wait_time)))) %>% + mutate(trav_time_avg = as.numeric(trav_time_avg),wait_time_avg = as.numeric(wait_time_avg)) + + if(time_format == "minute"){ + #convert seconds to minutes + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/60, wait_time_avg = wait_time_avg/60) + return(avg_time) + }else if(time_format == "hour"){ + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/3600, wait_time_avg = wait_time_avg/3600) + return(avg_time) + } + + return(avg_time) +} + appendDistanceCategory <- function(tripsTable){ @@ -2300,3 +2072,317 @@ appendDistanceCategory <- function(tripsTable){ tripsTable_result$dist_cat = factor(tripsTable_result$dist_cat,levels = c("0-1km","1-2km","2-5km","5-10km","10-20km","20-50km","50-100km","> 100km")) return(tripsTable_result) } + +#' Reads an coordinate referenec system of MATSim output directory +#' from output_config.xml +#' +#' @param folder specifies path to find config +#' +#' +#' @return code of coordinate reference system +#' +#' @export +getCrsFromConfig <- function(folder) { + + if (grepl("output_config.xml$", folder) == TRUE) + { + config <- read_xml(folder) + + param_nodes = xml_find_all(config,"//param") + + coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] + + coord_system = xml_attr(coord_node,"value") + return(coord_system) + } + + files <- list.files(folder, full.names = TRUE) + # Read from global/local directory + # output_config.xml is contained as output_trips.csv.gz + if (length(grep("output_config.xml$", files)) != 0) { + config <- read_xml(files[grep("output_config.xml$", files)]) + + param_nodes = xml_find_all(config,"//param") + + coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] + + coord_system = xml_attr(coord_node,"value") + return(coord_system) + } + return(NA) +} + +#' Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper +#' +#' +#' +#' @param tripsTable table of output trips(from readTripsTable) or path to trips_output file +#' +#' @param shapePath full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @param dump.output.to path to a folder to save csv file of ODMatrix +#' +#' @param colnames if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values +#' +#' @param simwrapper create output in a simwrapper form if set to path of the shapefile +#' +#' @param outer logical that represent if the table should contain outside flow of the shape, it isn't +#' +#' @return tibble of origin/destination matrix +#' +#' @export +deriveODMatrix<- function(tripsTable,shapePath,crs,dump.output.to = matsimDumpOutputDirectory,simwrapper = FALSE,colnames = "numeric",outer = FALSE){ + defaultW <- getOption("warn") + options(warn = -1) + + #if tripstable given as folder/file + if(sum(class(tripsTable) %in% c("tbl_df","tbl","data.frame"))<1){ + tripsTable <- readTripsTable(tripsTable) + } + + sfTable <- transformToSf(tripsTable,crs,geometry.type = st_point()) + + shape = st_read(shapePath) + + if (st_crs(shape) == NA) { + st_crs(shape) <- crs + } + shape = st_transform(shape,crs = crs) + + sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) + + sf_start = sfTable %>% select(trip_id,start_wkt) + st_geometry(sfTable) = "end_wkt" + sf_end = sfTable %>% select(trip_id,end_wkt) + + #Get all inner intersects + sf_intersect_start = st_contains(shape,sf_start) + sf_intersect_end = st_contains(shape,sf_end) + + + if(outer == TRUE){ + #Get all outer intersects + joined_shape = st_union(shape) + + start_inside = st_contains(joined_shape,sf_start) + end_inside = st_contains(joined_shape,sf_end) + + start_outside = 1:nrow(sf_start) + end_outside = 1:nrow(sf_end) + + start_outside = start_outside[! start_outside %in% start_inside[[1]]] + + end_outside = end_outside[! end_outside %in% end_inside[[1]]] + + sf_intersect_start = append(sf_intersect_start,list(start_outside)) + sf_intersect_end = append(sf_intersect_end,list(end_outside)) + } + + # Create matrix out of it + result_tibble = as_tibble(data.frame(matrix(nrow=0,ncol=nrow(shape)))) + colnames(result_tibble) = 1:nrow(shape) + + for(i in 1:length(sf_intersect_start)){ + temp = c() + for(j in 1:length(sf_intersect_start)){ + start_i = sf_intersect_start[[i]] + end_j = sf_intersect_end[[j]] + + number_of_trips = length(intersect(start_i,end_j)) + + temp = append(temp,number_of_trips) + + } + result_tibble = rbind(result_tibble,temp) + } + + if(colnames!="numeric" & colnames %in% colnames(shape)){ + colnames(result_tibble) = shape[[colnames]] + if(outer == TRUE){ + rownames(result_tibble) = c(shape[[colnames]],"outer") + colnames(result_tibble)[length(colnames(result_tibble))] = "outer" + }else{ + rownames(result_tibble) = shape[[colnames]] + } + + }else{ + colnames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) + rownames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) + } + + + result_melt = melt(as.matrix(result_tibble)) + colnames(result_melt) = c("origin","destination",1) + # Generating yaml and output_files + + + + if (file.exists(dump.output.to) & simwrapper == TRUE) { + write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") + } else if(!file.exists(dump.output.to) & simwrapper == TRUE) { + dir.create(dump.output.to) + write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") + } else if (file.exists(dump.output.to) & simwrapper == FALSE) { + write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) + } else { + dir.create(dump.output.to) + write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) + } + + yaml_list <- list( + title = "OD Flow", + description = "generated by deriveODMatrix", + projection = st_crs(shape)$input, + shpFile = paste0("../",shapePath), + dbfFile = paste0("../",substr(shapePath,start = 1,stop = nchar(shapePath)-3),"dbf"), + scaleFactor = 1, + lineWidth = 50, + csvFile = "ODMatrix.csv", + idColumn = colnames(shape)[1] # at the moment idColumn of shapefile should be the first column + + ) + write_yaml(yaml_list, paste0(dump.output.to, "/viz-od-flow.yaml")) + + options(warn = defaultW) + return(result_tibble) +} + +#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape +#' +#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +#' and filters the trips from table depending on *.inshape flags: +#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape +#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +#' +#' @param tripsTable tibble of trips_output (from readTripsTable()) +#' +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @param start.inshape bool, defines trips to conclude (see Description) +#' +#' @param end.inshape bool, defines trips to conclude (see Description) +#' +#' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) +#' +#' @export +filterByRegion <- function(tripsTable, shapeTable, crs, start.inshape = TRUE, end.inshape = TRUE) { + + # shapeTable <- st_read(shapeFile) + if (st_crs(shapeTable) == NA) { + st_crs(shapeTable) <- crs + } + + sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) + shapeTable <- st_transform(shapeTable, crs = crs) + # shapeTable isn't table - shape + + union_shape <- st_union(shapeTable) # transforms the crs back to the previous in the file + union_shape <- st_transform(union_shape, crs = st_crs(shapeTable)) + + + st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry + cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile + + st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry + cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile + + # get trips that ended outside of shape + cont_end_outside <- setdiff(1:nrow(sf_table), cont2) + + # get trips that started outside of shape + cont_start_outside <- setdiff(1:nrow(sf_table), cont1) + + if (start.inshape == TRUE && end.inshape == TRUE) { + cont_union <- intersect(cont1, cont2) + } else if (start.inshape == TRUE && end.inshape == FALSE) { + cont_union <- intersect(cont1, cont_end_outside) + } else if (start.inshape == FALSE && end.inshape == TRUE) { + cont_union <- intersect(cont2, cont_start_outside) + } else { + cont_union <- intersect(cont_start_outside, cont_end_outside) # Give back trips that are neither starting and ending outside the area + } + + + return(tripsTable[cont_union, ]) +} + +#' Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature) +#' +#' Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features +#' deletes from resulting data.frame start_x, end_x, start_y, end_y. +#' And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring() +#' Or adds start_wkt and end_wkt, if geometry.type = st_point() +#' Added column/columns projected to given CRS (coordinate reference system), +#' that can be taken from network file of MATSimOutputDirectory +#' +#' Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" +#' to get which type of table was generated, if it is needed +#' +#' @param table tibble of trips_output (from readTripsTable()) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @param geometry.type function of sf transformation, geometry.type can be (by default is st_multipoint()) +#' !!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or +#' !!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or +#' !!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!! +#' +#' @return sf object (data.frame with geometries depending to geometry.type) +#' +#' @export +transformToSf <- function(table, crs, geometry.type = st_multipoint()) { + if (class(geometry.type)[2] == "POINT") { + table1 <- table %>% + # mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep ="")) + mutate(start_wkt = paste("POINT(", start_x, " ", start_y, ")", sep = "")) + table2 <- table %>% + mutate(end_wkt = paste("POINT(", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "POINT" + + + table1_wkt <- st_as_sf(table1, wkt = "start_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + table2_wkt <- st_as_sf(table2, wkt = "end_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + + result_table <- table1_wkt %>% mutate(end_wkt = table2_wkt$end_wkt) + st_geometry(result_table) <- "start_wkt" + st_crs(result_table) <- crs + st_geometry(result_table) <- "end_wkt" + st_crs(result_table) <- crs + st_geometry(result_table) <- "start_wkt" + return(result_table) + } else if (class(geometry.type)[2] == "MULTIPOINT") { + table <- table %>% + mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "MULTIPOINT" + + + result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + st_crs(result_table) <- crs + return(result_table) + } else if (class(geometry.type)[2] == "LINESTRING") { + table <- table %>% + mutate(wkt = paste("LINESTRING(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "LINESTRING" + + + result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + st_crs(result_table) <- crs + return(result_table) + } else { + return(NA) + } +} + + +#####Helping functions#### diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 522f689..5f47a88 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -5,6 +5,8 @@ \alias{matsimr-deprecated} \alias{plotModalSplitPieChart} \alias{plotModalSplitBarChart} +\alias{readTripsTable} +\alias{plotAverageTravelWait} \title{Deprecated function(s) in the matsimr package} \usage{ plotModalSplitPieChart( @@ -22,6 +24,16 @@ plotModalSplitBarChart( dump.output.to = matsimDumpOutputDirectory, only.files = FALSE ) + +readTripsTable(input_path = ".", n_max = Inf) + +plotAverageTravelWait( + tripsTable, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + only.files = FALSE +) } \description{ These functions are provided for compatibility with older version of @@ -33,6 +45,7 @@ removed. \tabular{rl}{ \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}}\cr + \code{readTripsTable} \tab now a synonym for \code{\link{read_output_trips}}\cr } } diff --git a/man/plot_mainmode_barchart.Rd b/man/plot_mainmode_barchart.Rd index 0fa2687..abc7638 100644 --- a/man/plot_mainmode_barchart.Rd +++ b/man/plot_mainmode_barchart.Rd @@ -13,14 +13,14 @@ plot_mainmode_barchart( ) } \arguments{ +\item{trips_table}{tible of trips_output (from readTripsTable())} + \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} \item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} \item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} -\item{tripsTable}{tible of trips_output (from readTripsTable())} - \item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} } \value{ diff --git a/man/plot_mainmode_piechart.Rd b/man/plot_mainmode_piechart.Rd index 375969c..8974e21 100644 --- a/man/plot_mainmode_piechart.Rd +++ b/man/plot_mainmode_piechart.Rd @@ -12,14 +12,14 @@ plot_mainmode_piechart( ) } \arguments{ +\item{trips_table}{tibble of trips_output (from \link{readTripsTable})} + \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} \item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} \item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} -\item{tripsTable}{tibble of trips_output (from \link{readTripsTable})} - \item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} } \value{ diff --git a/man/plotAverageTravelWait.Rd b/man/plot_travelwaittime_mean_barchart.Rd similarity index 84% rename from man/plotAverageTravelWait.Rd rename to man/plot_travelwaittime_mean_barchart.Rd index a8b75d6..03d63d2 100644 --- a/man/plotAverageTravelWait.Rd +++ b/man/plot_travelwaittime_mean_barchart.Rd @@ -1,19 +1,18 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/output_trips.R -\name{plotAverageTravelWait} -\alias{plotAverageTravelWait} +\name{plot_travelwaittime_mean_barchart} +\alias{plot_travelwaittime_mean_barchart} \title{Bar Chart with main_mode on x-axis and average travel/wait time on y-axis} \usage{ -plotAverageTravelWait( - tripsTable, +plot_travelwaittime_mean_barchart( + trips_table, unite.columns = character(0), united.name = "united", - dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE + time_format = "minute" ) } \arguments{ -\item{tripsTable}{tible of trips_output (from readTripsTable())} +\item{trips_table}{tible of trips_output (from readTripsTable())} \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} diff --git a/man/readTripsTable.Rd b/man/read_output_trips.Rd similarity index 82% rename from man/readTripsTable.Rd rename to man/read_output_trips.Rd index 1081a70..ba00957 100644 --- a/man/readTripsTable.Rd +++ b/man/read_output_trips.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/output_trips.R -\name{readTripsTable} -\alias{readTripsTable} +\name{read_output_trips} +\alias{read_output_trips} \title{Load MATSIM output_trips table into Memory} \usage{ -readTripsTable(input_path = ".", n_max = Inf) +read_output_trips(input_path = ".", n_max = Inf) } \arguments{ \item{input_path}{character string, path to matsim output directory or http link to the file.} From 84ee3496a0dc3991208586af4ba2d6a4fb0cf2dd Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 24 May 2023 14:23:50 +0200 Subject: [PATCH 08/87] refactored compare travel wait function --- NAMESPACE | 1 + R/output_trips.R | 805 ++++++++++-------- man/matsimr-deprecated.Rd | 10 + ...lot_compare_travelwaittime_by_mainmode.Rd} | 21 +- 4 files changed, 452 insertions(+), 385 deletions(-) rename man/{compareAverageTravelWait.Rd => plot_compare_travelwaittime_by_mainmode.Rd} (87%) diff --git a/NAMESPACE b/NAMESPACE index 547d9d8..9732077 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -29,6 +29,7 @@ export(plotTripCountByDepTime) export(plotTripDistanceByMode) export(plotTripDistancedByType) export(plotTripTypesPieChart) +export(plot_compare_travelwaittime_by_mainmode) export(plot_mainmode_barchart) export(plot_mainmode_piechart) export(plot_travelwaittime_mean_barchart) diff --git a/R/output_trips.R b/R/output_trips.R index 38dec94..13228d0 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -266,220 +266,17 @@ plotAverageTravelWait <- function(tripsTable, unite.columns = character(0), unit } - -#####Reading##### - - -#' Load MATSIM output_trips table into Memory -#' -#' Loads a MATSim CSV output_trips from file or archive, -#' creating a tibble with columns as in csv file -#' -#' @param input_path character string, path to matsim output directory or http link to the file. -#' @param n_max integer, maximum number of lines to read within output_trips -#' @return tibble of trips_output -#' -#' @export -read_output_trips <- function(input_path = ".", n_max = Inf) { - options(digits = 18) - trips_file <- "" - - # if input_path is a directory, find the correct file path within it - if(dir.exists(input_path)){ - files <- list.files(input_path, full.names = TRUE) - trip_file_indicies <- grep("output_trips.csv.gz$", files) - - if(length(trip_file_indicies) == 1){ - trips_file <- files[trip_file_indicies] - } else { - stop('There is supposed to be a single "output_trips.csv.gz" found in directory') - } - } else { - trips_file <- input_path - } - - trips_output_table <- read_delim(trips_file, - delim = ";", - locale = locale(decimal_mark = "."), - n_max = n_max, - col_types = cols( - start_x = col_character(), - start_y = col_character(), - end_x = col_character(), - end_y = col_character(), - end_link = col_character(), - start_link = col_character() - ) - ) - # person is mostly integer, but contains also chars(see Hamburg 110813 observation) - # doesn't reads coordinates correctly - trips_output_table <- trips_output_table %>% - mutate( - start_x = as.double(start_x), - start_y = as.double(start_y), - end_x = as.double(end_x), - end_y = as.double(end_y) - ) - attr(trips_output_table,"table_name") <- trips_file - return(trips_output_table) - -} - - - -#####Plotting##### - -#' Plot main_mode distribution as a Pie Chart -#' -#' Takes Table trips_output (from \link{readTripsTable}), -#' to plot pie chart with with values that represent -#' percentage of using transport modes from trips -#' -#' Function automatically detects transport_modes from table -#' and plots pie chart. -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -#' -#' @param trips_table tibble of trips_output (from \link{readTripsTable}) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' -#' @return Pie Chart plot of transport mode distribution, values given in percents -#' -#' @export -plot_mainmode_piechart <- function(trips_table, - unite.columns = character(0), united.name = "united", - dump.output.to = matsimDumpOutputDirectory) { - - # If some columns should be united - trips_table = process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, - united.name = united.name) - - # tripsTableCount gives percentage representation out - trips_table_count<-process_get_mainmode_distribution(trips_table, - percentage= percentage) - - - # plotting - fig <- plot_ly(trips_table_count, labels = ~main_mode, values = ~n, type = 'pie') - fig <- fig %>% layout(title = 'Main mode distribution', - xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE), - yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE)) - - return(fig) -} - - -#' Plot main_mode distribution as a bar Chart -#' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' percentage of using transport modes from trips -#' -#' Function automatically detects transport_modes from table -#' and plots pie chart with percentage of distribution. -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -#' -#' -#' @param trips_table tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' -#' @return Bar Chart plot of transport mode distribution, values given in percents -#' -#' @export -plot_mainmode_barchart <- function(trips_table, - unite.columns = character(0), - united.name = "united", - dump.output.to = matsimDumpOutputDirectory, - percentage = FALSE) { - - # If some columns should be united - trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, - united.name = united.name) - # Get percentage - trips_table_count <- process_get_mainmode_distribution(trips_table, - percentage = percentage) - - # plotting - fig = plot_ly(data = trips_table_count,x = ~main_mode,y = ~n,type = "bar", - text=trips_table_count$n, - textposition = "auto", - name = "Main mode distribtion") - fig = fig %>% layout(yaxis = list(title = "Count"),barmode = "group") - fig - return(fig) -} - -#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis -#' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' time spent on traveling/waiting -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -#' -#' -#' @param trips_table tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' -#' @return Bar Chart plot of average time spent on travel/wait -#' -#' @export -plot_travelwaittime_mean_barchart <- function(trips_table, - unite.columns = character(0), - united.name = "united", - time_format = "minute") { - - # If some columns should be united - trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, - united.name = united.name) - - #processing of result table - avg_time = process_get_travelwaittime_by_mainmode(trips_table,time_format = time_format) - - #plotting - fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling", - text = round(avg_time$trav_time_avg,2)) - fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting", - text = round(avg_time$wait_time_avg,2)) - fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)"),barmode = "group")) - - - fig - return(fig) - -} - - -#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis -#' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' time spent on traveling/waiting -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Deprecated function(s) in the matsimr package #' #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' @rdname matsimr-deprecated #' -#' @return Bar Chart plot of average time spent on travel/wait +#' @docType package +#' @export compareAverageTravelWait +#' @aliases compareAverageTravelWait #' -#' @export compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE) { + only.files = FALSE) { # If some columns should be united if (length(unite.columns) != 0) { @@ -543,7 +340,7 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch #' #' @export plotModalDistanceDistribution <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE) { + only.files = FALSE) { # If some columns should be united @@ -634,12 +431,12 @@ plotModalDistanceDistribution <- function(tripsTable, unite.columns = character( #' #' @export compareModalDistanceDistribution <- function(tripsTable1,tripsTable2, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE) { + only.files = FALSE) { if (length(unite.columns) != 0) { tripsTable1$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable1$main_mode)] <- united.name tripsTable2$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable2$main_mode)] <- united.name - } + } modes = unique(c(unique(tripsTable1$main_mode),unique(tripsTable2$main_mode))) distribution1 <- appendDistanceCategory(tripsTable1) @@ -681,8 +478,8 @@ compareModalDistanceDistribution <- function(tripsTable1,tripsTable2, unite.colu fig = ggplotly(ggplot(result) + - geom_col(aes(x = dist_cat,fill = main_mode, y = n), position = position_dodge())+ - ggtitle("Difference in number of trips per travelling distance")) + geom_col(aes(x = dist_cat,fill = main_mode, y = n), position = position_dodge())+ + ggtitle("Difference in number of trips per travelling distance")) return(fig) @@ -792,7 +589,7 @@ plotTripCountByDepTime <- function(tripsTable, unite.columns = character(0), uni } #diff = setdiff(tableToWrite$dist_cat,newColumn$dist_cat) #for(dist in diff){ - #newColumn = rbind(newColumn,c(dist,0)) + #newColumn = rbind(newColumn,c(dist,0)) #} newColumn = newColumn %>% arrange(dep_time) %>% select(-dep_time) %>% mutate(mode = as.numeric(mode)) colnames(newColumn)[1] = mode @@ -831,7 +628,7 @@ plotTripCountByDepTime <- function(tripsTable, unite.columns = character(0), uni #' #' @export plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE) { + only.files = FALSE) { # If some columns should be united @@ -869,8 +666,8 @@ plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), unite fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~start_activity_type) fig = fig %>% layout(yaxis = list(title = "Number of activities ending [n]"), - xaxis = list(title = "Time [h]"), - barmode = "group") + xaxis = list(title = "Time [h]"), + barmode = "group") #files @@ -879,8 +676,8 @@ plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), unite #} else { # dir.create(dump.output.to) # htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/countTripsByDep.html")) -# -# } + # + # } # Generating yaml and output_files @@ -910,7 +707,7 @@ plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), unite #' #' @export plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE) { + only.files = FALSE) { # If some columns should be united @@ -949,18 +746,18 @@ plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character fig = plot_ly(tripsTable,x = ~arr_time,y = ~n,type = "scatter",mode = "line",linetype = ~end_activity_type) fig = fig %>% layout(yaxis = list(title = "Number of trips ending per trip purpose / Count of activities starting"), - xaxis = list(title = "Time [h]"), - barmode = "group") + xaxis = list(title = "Time [h]"), + barmode = "group") - # #files - # if (file.exists(dump.output.to)) { - # htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/countEndActByArr.html")) - # } else { - # dir.create(dump.output.to) - # htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/countEndActByArr.html")) -# - # } + # #files + # if (file.exists(dump.output.to)) { + # htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/countEndActByArr.html")) + # } else { + # dir.create(dump.output.to) + # htmlwidgets::saveWidget(fig,paste0(dump.output.to, "/countEndActByArr.html")) + # + # } # Generating yaml and output_files if (! file.exists(dump.output.to)) { @@ -1030,7 +827,7 @@ plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character #' #' @export plotDepartureTimesPerTripPurpose <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE) { + only.files = FALSE) { # If some columns should be united @@ -1069,11 +866,11 @@ plotDepartureTimesPerTripPurpose <- function(tripsTable, unite.columns = charact fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~end_activity_type) fig = fig %>% layout(yaxis = list(title = "Number of trips starting per trip purpose"), - xaxis = list(title = "Time [h]"), - barmode = "group") + xaxis = list(title = "Time [h]"), + barmode = "group") - # #files + # #files if(!only.files){ fig @@ -1147,17 +944,17 @@ plotTripDistancedByType <- function(tripsTable,shapeTable,crs,dump.output.to = m plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FALSE, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory) { StatStratum <- ggalluvial::StatStratum joined <- as_tibble(inner_join(tripsTable1, tripsTable2 %>% - select(trip_id, main_mode), by = "trip_id") %>% - dplyr::rename(base_mode = main_mode.x, policy_mode = main_mode.y)) + select(trip_id, main_mode), by = "trip_id") %>% + dplyr::rename(base_mode = main_mode.x, policy_mode = main_mode.y)) if (show.onlyChanges == TRUE) { - joined <- joined %>% + joined <- joined %>% filter(base_mode != policy_mode) } joined <- joined %>% - group_by(base_mode, policy_mode) %>% - count() + group_by(base_mode, policy_mode) %>% + count() # If the unite.commercials flag is set to TRUE, then join all commercials under 1 name commercial if (length(unite.columns) != 0) { @@ -1209,7 +1006,7 @@ plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FA #' @return plots Bar Chart of transport mode changes with additional files for simwrapper #' #' @export - plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, +plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, output.name = "modalShiftBarChart") { # If the unite.columns is specified, then #print(dump.output.to) @@ -1339,32 +1136,32 @@ plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRU ) %>% addPolygons(data = shapeTable, opacity = 0.1, color = "green") %>% addCircleMarkers(filtered_sf_start, - lng = st_coordinates(filtered_sf_start$start_wkt)[, 1], - lat = st_coordinates(filtered_sf_start$start_wkt)[, 2], radius = 3, color = "blue", - label = paste( - "Person_id:", - filtered_sf_start$person, "
", - "Trip_id:", - filtered_sf_start$trip_id, "
", - "main_mode:", filtered_sf_start$main_mode, "
", - "type:", "start", "
", - "Start activity:", - filtered_sf_start$start_activity_type, "
" - ) %>% lapply(htmltools::HTML) + lng = st_coordinates(filtered_sf_start$start_wkt)[, 1], + lat = st_coordinates(filtered_sf_start$start_wkt)[, 2], radius = 3, color = "blue", + label = paste( + "Person_id:", + filtered_sf_start$person, "
", + "Trip_id:", + filtered_sf_start$trip_id, "
", + "main_mode:", filtered_sf_start$main_mode, "
", + "type:", "start", "
", + "Start activity:", + filtered_sf_start$start_activity_type, "
" + ) %>% lapply(htmltools::HTML) ) %>% addCircleMarkers(filtered_sf_end, - lng = st_coordinates(filtered_sf_end$end_wkt)[, 1], - lat = st_coordinates(filtered_sf_end$end_wkt)[, 2], radius = 0.15, color = "red", - label = paste( - "Person_id:", - filtered_sf_end$person, "
", - "Trip_id:", - filtered_sf_end$trip_id, "
", - "main_mode:", filtered_sf_end$main_mode, "
", - "type:", "end", "
", - "End activity:", - filtered_sf_end$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) + lng = st_coordinates(filtered_sf_end$end_wkt)[, 1], + lat = st_coordinates(filtered_sf_end$end_wkt)[, 2], radius = 0.15, color = "red", + label = paste( + "Person_id:", + filtered_sf_end$person, "
", + "Trip_id:", + filtered_sf_end$trip_id, "
", + "main_mode:", filtered_sf_end$main_mode, "
", + "type:", "end", "
", + "End activity:", + filtered_sf_end$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) ) %>% addLegend( colors = c("blue", "red"), @@ -1554,18 +1351,18 @@ plotTripTypesPieChart <- function(table, shapeTable, crs) { ) return(ggplot(result, aes(x = "", y = n, fill = fct_inorder(type))) + - geom_col(width = 1, col = 1) + - geom_bar(stat = "identity", width = 1) + - coord_polar("y") + - # geom_text(aes(label = round(n,digits = 1)), - # position=position_stack(vjust = 0.5), - # show.legend = FALSE,size = 4)+ - geom_label_repel( - data = positions, - aes(y = pos, label = paste0(round(n, digits = 1), "%")), - size = 4.5, nudge_x = 1, show.legend = FALSE - ) + - ggtitle("Distribution")) + geom_col(width = 1, col = 1) + + geom_bar(stat = "identity", width = 1) + + coord_polar("y") + + # geom_text(aes(label = round(n,digits = 1)), + # position=position_stack(vjust = 0.5), + # show.legend = FALSE,size = 4)+ + geom_label_repel( + data = positions, + aes(y = pos, label = paste0(round(n, digits = 1), "%")), + size = 4.5, nudge_x = 1, show.legend = FALSE + ) + + ggtitle("Distribution")) } #' Creates BarChart of changing trip types(originating,transit etc) between 2 tables @@ -1722,116 +1519,116 @@ plotMapWithTripsType <- function(table, shapeTable, crs, optimized = FALSE) { ) %>% addPolygons(data = shapeTable, opacity = 0.1, color = "green") %>% addCircleMarkers(filtered_sf_inside, - lng = st_coordinates(filtered_sf_inside$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_inside$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 3, color = "blue", - label = paste( - "Person_id:", - filtered_sf_inside$person, "
", - "Trip_id:", - filtered_sf_inside$trip_id, "
", - "main_mode:", filtered_sf_inside$main_mode, "
", - "type:", "start", "
", - "Start activity:", - filtered_sf_inside$start_activity_type, "
" - ) %>% lapply(htmltools::HTML) + lng = st_coordinates(filtered_sf_inside$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_inside$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 3, color = "blue", + label = paste( + "Person_id:", + filtered_sf_inside$person, "
", + "Trip_id:", + filtered_sf_inside$trip_id, "
", + "main_mode:", filtered_sf_inside$main_mode, "
", + "type:", "start", "
", + "Start activity:", + filtered_sf_inside$start_activity_type, "
" + ) %>% lapply(htmltools::HTML) ) %>% addCircleMarkers(filtered_sf_inside, - lng = st_coordinates(filtered_sf_inside$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_inside$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 3, color = "blue", - label = paste( - "Person_id:", - filtered_sf_inside$person, "
", - "Trip_id:", - filtered_sf_inside$trip_id, "
", - "main_mode:", filtered_sf_inside$main_mode, "
", - "type:", "end", "
", - "End activity:", - filtered_sf_inside$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) + lng = st_coordinates(filtered_sf_inside$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_inside$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 3, color = "blue", + label = paste( + "Person_id:", + filtered_sf_inside$person, "
", + "Trip_id:", + filtered_sf_inside$trip_id, "
", + "main_mode:", filtered_sf_inside$main_mode, "
", + "type:", "end", "
", + "End activity:", + filtered_sf_inside$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) ) %>% addCircleMarkers(filtered_sf_origin, - lng = st_coordinates(filtered_sf_origin$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_origin$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 2, color = "red", - label = paste( - "Person_id:", - filtered_sf_origin$person, "
", - "Trip_id:", - filtered_sf_origin$trip_id, "
", - "main_mode:", filtered_sf_origin$main_mode, "
", - "type:", "start", "
", - "Start activity:", - filtered_sf_origin$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) + lng = st_coordinates(filtered_sf_origin$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_origin$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 2, color = "red", + label = paste( + "Person_id:", + filtered_sf_origin$person, "
", + "Trip_id:", + filtered_sf_origin$trip_id, "
", + "main_mode:", filtered_sf_origin$main_mode, "
", + "type:", "start", "
", + "Start activity:", + filtered_sf_origin$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) ) %>% addCircleMarkers(filtered_sf_origin, - lng = st_coordinates(filtered_sf_origin$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_origin$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 2, color = "red", - label = paste( - "Person_id:", - filtered_sf_origin$person, "
", - "Trip_id:", - filtered_sf_origin$trip_id, "
", - "main_mode:", filtered_sf_origin$main_mode, "
", - "type:", "end", "
", - "End activity:", - filtered_sf_origin$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) - ) %>% + lng = st_coordinates(filtered_sf_origin$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_origin$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 2, color = "red", + label = paste( + "Person_id:", + filtered_sf_origin$person, "
", + "Trip_id:", + filtered_sf_origin$trip_id, "
", + "main_mode:", filtered_sf_origin$main_mode, "
", + "type:", "end", "
", + "End activity:", + filtered_sf_origin$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% addCircleMarkers(filtered_sf_destination, - lng = st_coordinates(filtered_sf_destination$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_destination$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 1, color = "orange", - label = paste( - "Person_id:", - filtered_sf_destination$person, "
", - "Trip_id:", - filtered_sf_destination$trip_id, "
", - "main_mode:", filtered_sf_destination$main_mode, "
", - "type:", "start", "
", - "Start activity:", - filtered_sf_destination$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) + lng = st_coordinates(filtered_sf_destination$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_destination$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 1, color = "orange", + label = paste( + "Person_id:", + filtered_sf_destination$person, "
", + "Trip_id:", + filtered_sf_destination$trip_id, "
", + "main_mode:", filtered_sf_destination$main_mode, "
", + "type:", "start", "
", + "Start activity:", + filtered_sf_destination$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) ) %>% addCircleMarkers(filtered_sf_destination, - lng = st_coordinates(filtered_sf_destination$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_destination$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 1, color = "orange", - label = paste( - "Person_id:", - filtered_sf_destination$person, "
", - "Trip_id:", - filtered_sf_destination$trip_id, "
", - "main_mode:", filtered_sf_destination$main_mode, "
", - "type:", "end", "
", - "End activity:", - filtered_sf_destination$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) + lng = st_coordinates(filtered_sf_destination$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_destination$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 1, color = "orange", + label = paste( + "Person_id:", + filtered_sf_destination$person, "
", + "Trip_id:", + filtered_sf_destination$trip_id, "
", + "main_mode:", filtered_sf_destination$main_mode, "
", + "type:", "end", "
", + "End activity:", + filtered_sf_destination$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) ) %>% addCircleMarkers(filtered_sf_transit, - lng = st_coordinates(filtered_sf_transit$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_transit$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 0.15, color = "black", - label = paste( - "Person_id:", - filtered_sf_transit$person, "
", - "Trip_id:", - filtered_sf_transit$trip_id, "
", - "main_mode:", filtered_sf_transit$main_mode, "
", - "type:", "start", "
", - "Start activity:", - filtered_sf_transit$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) + lng = st_coordinates(filtered_sf_transit$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_transit$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 0.15, color = "black", + label = paste( + "Person_id:", + filtered_sf_transit$person, "
", + "Trip_id:", + filtered_sf_transit$trip_id, "
", + "main_mode:", filtered_sf_transit$main_mode, "
", + "type:", "start", "
", + "Start activity:", + filtered_sf_transit$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) ) %>% addCircleMarkers(filtered_sf_transit, - lng = st_coordinates(filtered_sf_transit$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_transit$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 0.15, color = "black", - label = paste( - "Person_id:", - filtered_sf_transit$person, "
", - "Trip_id:", - filtered_sf_transit$trip_id, "
", - "main_mode:", filtered_sf_transit$main_mode, "
", - "type:", "end", "
", - "End activity:", - filtered_sf_transit$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) + lng = st_coordinates(filtered_sf_transit$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_transit$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 0.15, color = "black", + label = paste( + "Person_id:", + filtered_sf_transit$person, "
", + "Trip_id:", + filtered_sf_transit$trip_id, "
", + "main_mode:", filtered_sf_transit$main_mode, "
", + "type:", "end", "
", + "End activity:", + filtered_sf_transit$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) ) %>% addLegend( colors = c("blue", "red", "orange", "black"), @@ -1993,7 +1790,267 @@ compareBasePolicyShapeOutput <- function(baseFolder,policyFolder,shapeFilePath,c } invisible(list(base = base_trips,policy = policy_trips)) } +#####Reading##### + + +#' Load MATSIM output_trips table into Memory +#' +#' Loads a MATSim CSV output_trips from file or archive, +#' creating a tibble with columns as in csv file +#' +#' @param input_path character string, path to matsim output directory or http link to the file. +#' @param n_max integer, maximum number of lines to read within output_trips +#' @return tibble of trips_output +#' +#' @export +read_output_trips <- function(input_path = ".", n_max = Inf) { + options(digits = 18) + trips_file <- "" + + # if input_path is a directory, find the correct file path within it + if(dir.exists(input_path)){ + files <- list.files(input_path, full.names = TRUE) + trip_file_indicies <- grep("output_trips.csv.gz$", files) + + if(length(trip_file_indicies) == 1){ + trips_file <- files[trip_file_indicies] + } else { + stop('There is supposed to be a single "output_trips.csv.gz" found in directory') + } + } else { + trips_file <- input_path + } + + trips_output_table <- read_delim(trips_file, + delim = ";", + locale = locale(decimal_mark = "."), + n_max = n_max, + col_types = cols( + start_x = col_character(), + start_y = col_character(), + end_x = col_character(), + end_y = col_character(), + end_link = col_character(), + start_link = col_character() + ) + ) + # person is mostly integer, but contains also chars(see Hamburg 110813 observation) + # doesn't reads coordinates correctly + trips_output_table <- trips_output_table %>% + mutate( + start_x = as.double(start_x), + start_y = as.double(start_y), + end_x = as.double(end_x), + end_y = as.double(end_y) + ) + attr(trips_output_table,"table_name") <- trips_file + return(trips_output_table) + +} + + + +#####Plotting##### + +#' Plot main_mode distribution as a Pie Chart +#' +#' Takes Table trips_output (from \link{readTripsTable}), +#' to plot pie chart with with values that represent +#' percentage of using transport modes from trips +#' +#' Function automatically detects transport_modes from table +#' and plots pie chart. +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' @param trips_table tibble of trips_output (from \link{readTripsTable}) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' +#' @return Pie Chart plot of transport mode distribution, values given in percents +#' +#' @export +plot_mainmode_piechart <- function(trips_table, + unite.columns = character(0), united.name = "united", + dump.output.to = matsimDumpOutputDirectory) { + + # If some columns should be united + trips_table = process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, + united.name = united.name) + + # tripsTableCount gives percentage representation out + trips_table_count<-process_get_mainmode_distribution(trips_table, + percentage= percentage) + + + # plotting + fig <- plot_ly(trips_table_count, labels = ~main_mode, values = ~n, type = 'pie') + fig <- fig %>% layout(title = 'Main mode distribution', + xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE), + yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE)) + + return(fig) +} + + +#' Plot main_mode distribution as a bar Chart +#' +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' percentage of using transport modes from trips +#' +#' Function automatically detects transport_modes from table +#' and plots pie chart with percentage of distribution. +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' @param trips_table tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' +#' @return Bar Chart plot of transport mode distribution, values given in percents +#' +#' @export +plot_mainmode_barchart <- function(trips_table, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + percentage = FALSE) { + + # If some columns should be united + trips_table <- process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, + united.name = united.name) + # Get percentage + trips_table_count <- process_get_mainmode_distribution(trips_table, + percentage = percentage) + + # plotting + fig = plot_ly(data = trips_table_count,x = ~main_mode,y = ~n,type = "bar", + text=trips_table_count$n, + textposition = "auto", + name = "Main mode distribtion") + fig = fig %>% layout(yaxis = list(title = "Count"),barmode = "group") + fig + return(fig) +} + +#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis +#' +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' time spent on traveling/waiting +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' @param trips_table tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' +#' @return Bar Chart plot of average time spent on travel/wait +#' +#' @export +plot_travelwaittime_mean_barchart <- function(trips_table, + unite.columns = character(0), + united.name = "united", + time_format = "minute") { + + # If some columns should be united + trips_table <- process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, + united.name = united.name) + + #processing of result table + avg_time = process_get_travelwaittime_by_mainmode(trips_table,time_format = time_format) + #plotting + fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling", + text = round(avg_time$trav_time_avg,2)) + fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting", + text = round(avg_time$wait_time_avg,2)) + fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)"),barmode = "group")) + + + fig + return(fig) + +} + + + + +#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis +#' +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' time spent on traveling/waiting +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' @param tripsTable1 tible of trips_output (from readTripsTable()) +#' @param tripsTable2 tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' +#' @return Bar Chart plot of average time spent on travel/wait +#' +#' @export +plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, + unite.columns = character(0), + united.name = "united", + time_format = "minute") { + + #TODO: + # . Document and add title to show what means positive/negative value + # . think about comparing processing functions they can appear in future often + + + # If some columns should be united + trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, + unite.columns = unite.columns, + united.name = united.name) + + trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, + unite.columns = unite.columns, + united.name = united.name) + + #processing + avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) + + + + avg_time2 = process_get_travelwaittime_by_mainmode(trips_table2,time_format = time_format) + + + avg_time = full_join(avg_time1, avg_time2, by = "main_mode") %>% + replace_na(list(trav_time_avg.x = 0,wait_time_avg.x = 0,trav_time_avg.y = 0,wait_time_avg.y = 0)) + + + + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg.x - trav_time_avg.y, + wait_time_avg =wait_time_avg.x - wait_time_avg.y )%>% + select(-wait_time_avg.x,-wait_time_avg.y, -trav_time_avg.x,-trav_time_avg.y) + + + + #plotting + fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") + fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") + fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)")),barmode = "group") + + + fig + return(fig) + +} diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 5f47a88..819a97d 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -7,6 +7,7 @@ \alias{plotModalSplitBarChart} \alias{readTripsTable} \alias{plotAverageTravelWait} +\alias{compareAverageTravelWait} \title{Deprecated function(s) in the matsimr package} \usage{ plotModalSplitPieChart( @@ -34,6 +35,15 @@ plotAverageTravelWait( dump.output.to = matsimDumpOutputDirectory, only.files = FALSE ) + +compareAverageTravelWait( + tripsTable1, + tripsTable2, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + only.files = FALSE +) } \description{ These functions are provided for compatibility with older version of diff --git a/man/compareAverageTravelWait.Rd b/man/plot_compare_travelwaittime_by_mainmode.Rd similarity index 87% rename from man/compareAverageTravelWait.Rd rename to man/plot_compare_travelwaittime_by_mainmode.Rd index ca316ec..481626f 100644 --- a/man/compareAverageTravelWait.Rd +++ b/man/plot_compare_travelwaittime_by_mainmode.Rd @@ -1,27 +1,26 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/output_trips.R -\name{compareAverageTravelWait} -\alias{compareAverageTravelWait} +\name{plot_compare_travelwaittime_by_mainmode} +\alias{plot_compare_travelwaittime_by_mainmode} \title{Bar Chart with main_mode on x-axis and average travel/wait time on y-axis} \usage{ -compareAverageTravelWait( - tripsTable1, - tripsTable2, +plot_compare_travelwaittime_by_mainmode( + trips_table1, + trips_table2, unite.columns = character(0), united.name = "united", - dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE + time_format = "minute" ) } \arguments{ -\item{tripsTable1}{tible of trips_output (from readTripsTable())} - -\item{tripsTable2}{tible of trips_output (from readTripsTable())} - \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} \item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +\item{tripsTable1}{tible of trips_output (from readTripsTable())} + +\item{tripsTable2}{tible of trips_output (from readTripsTable())} + \item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} \item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} From bc6d4006dcff424f6394f31b98249882d60561f3 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 24 May 2023 14:40:55 +0200 Subject: [PATCH 09/87] splited append distance category --- NAMESPACE | 1 + R/output_trips.R | 53 +++++++++++++++++++++++++++++++++++++-- man/matsimr-deprecated.Rd | 3 +++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 9732077..e44f071 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -38,6 +38,7 @@ export(prepareSimwrapperDashboardFromFolder) export(prepareSimwrapperDashboardFromTable) export(processDtvEstimationQuality) export(processLinkStatsDtvDistribution) +export(process_append_distcat) export(readCounts) export(readLinkStats) export(readPersonsTable) diff --git a/R/output_trips.R b/R/output_trips.R index 13228d0..f696d89 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -1790,6 +1790,51 @@ compareBasePolicyShapeOutput <- function(baseFolder,policyFolder,shapeFilePath,c } invisible(list(base = base_trips,policy = policy_trips)) } + + +#' Deprecated function(s) in the matsimr package +#' +#' +#' @rdname matsimr-deprecated +#' +#' @docType package +#' @export compareAverageTravelWait +#' @aliases compareAverageTravelWait +#' +appendDistanceCategory <- function(tripsTable){ + + distances_array = sort(distances_array) + modes = levels(factor(tripsTable$main_mode)) + + #This is a very bad way to do that, but I see no other way to get it done + #Also filtering table into a new doesn't creates new objects in memory, so it works fast + #Upd: it creates copy of dataframe on each mutate :/ + + + tripsTable_05km = tripsTable %>% filter(traveled_distance<=1000) %>% mutate(dist_cat = "0-1km") + tripsTable_2km = tripsTable %>% filter(traveled_distance>1000 & traveled_distance<=2000) %>% mutate(dist_cat = "1-2km") + tripsTable_5km = tripsTable %>% filter(traveled_distance>2000 & traveled_distance<=5000) %>% mutate(dist_cat = "2-5km") + tripsTable_10km = tripsTable %>% filter(traveled_distance>5000 & traveled_distance<=10*1000) %>% mutate(dist_cat = "5-10km") + tripsTable_20km = tripsTable %>% filter(traveled_distance>10*1000 & traveled_distance<=20*1000) %>% mutate(dist_cat = "10-20km") + tripsTable_50km = tripsTable %>% filter(traveled_distance>20*1000 & traveled_distance<=50*1000) %>% mutate(dist_cat = "20-50km") + tripsTable_100km = tripsTable %>% filter(traveled_distance>50*1000 & traveled_distance<=100*1000) %>% mutate(dist_cat = "50-100km") + tripsTable_100pluskm = tripsTable %>% filter(traveled_distance>100*1000) %>% mutate(dist_cat = "> 100km") + + tripsTable_result = rbind(tripsTable_05km, + #tripsTable_1km, + tripsTable_2km, + tripsTable_5km, + tripsTable_10km, + tripsTable_20km, + tripsTable_50km, + tripsTable_100km, + tripsTable_100pluskm) + + tripsTable_result$dist_cat = factor(tripsTable_result$dist_cat,levels = c("0-1km","1-2km","2-5km","5-10km","10-20km","20-50km","50-100km","> 100km")) + return(tripsTable_result) +} + + #####Reading##### @@ -2100,14 +2145,18 @@ process_get_travelwaittime_by_mainmode<-function(trips_table, } +#' @export +process_append_distcat <- function(tripsTable,distances_array = c(1000,2000,5000,10000,20000,50000,100000)){ -appendDistanceCategory <- function(tripsTable){ + distances_array = sort(distances_array) modes = levels(factor(tripsTable$main_mode)) #This is a very bad way to do that, but I see no other way to get it done #Also filtering table into a new doesn't creates new objects in memory, so it works fast + #Upd: it creates copy of dataframe on each mutate :/ + + tripsTable_05km = tripsTable %>% filter(traveled_distance<=1000) %>% mutate(dist_cat = "0-1km") - #tripsTable_1km = tripsTable %>% filter(traveled_distance>500 & traveled_distance<=1000 ) %>% mutate(dist_cat = "0.5-1km") tripsTable_2km = tripsTable %>% filter(traveled_distance>1000 & traveled_distance<=2000) %>% mutate(dist_cat = "1-2km") tripsTable_5km = tripsTable %>% filter(traveled_distance>2000 & traveled_distance<=5000) %>% mutate(dist_cat = "2-5km") tripsTable_10km = tripsTable %>% filter(traveled_distance>5000 & traveled_distance<=10*1000) %>% mutate(dist_cat = "5-10km") diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 819a97d..1c90d25 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -8,6 +8,7 @@ \alias{readTripsTable} \alias{plotAverageTravelWait} \alias{compareAverageTravelWait} +\alias{appendDistanceCategory} \title{Deprecated function(s) in the matsimr package} \usage{ plotModalSplitPieChart( @@ -44,6 +45,8 @@ compareAverageTravelWait( dump.output.to = matsimDumpOutputDirectory, only.files = FALSE ) + +appendDistanceCategory(tripsTable) } \description{ These functions are provided for compatibility with older version of From 4f586e79a8b0bbd4507e28aa462c0f1a70292183 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Tue, 30 May 2023 12:05:56 +0200 Subject: [PATCH 10/87] last_update --- R/output_trips.R | 3 +++ 1 file changed, 3 insertions(+) diff --git a/R/output_trips.R b/R/output_trips.R index f696d89..89499e7 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2155,6 +2155,9 @@ process_append_distcat <- function(tripsTable,distances_array = c(1000,2000,5000 #Also filtering table into a new doesn't creates new objects in memory, so it works fast #Upd: it creates copy of dataframe on each mutate :/ + for(i in length(distances_array)){ + + } tripsTable_05km = tripsTable %>% filter(traveled_distance<=1000) %>% mutate(dist_cat = "0-1km") tripsTable_2km = tripsTable %>% filter(traveled_distance>1000 & traveled_distance<=2000) %>% mutate(dist_cat = "1-2km") From afcb24269041293c924f284663a57cdb30a5e932 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Tue, 30 May 2023 15:04:35 +0200 Subject: [PATCH 11/87] added distance by mainmode barchart --- NAMESPACE | 2 +- R/output_trips.R | 79 +++++++++++++++-------- man/plot_distance_by_mainmode_barchart.Rd | 30 +++++++++ 3 files changed, 83 insertions(+), 28 deletions(-) create mode 100644 man/plot_distance_by_mainmode_barchart.Rd diff --git a/NAMESPACE b/NAMESPACE index e44f071..089de4e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -30,6 +30,7 @@ export(plotTripDistanceByMode) export(plotTripDistancedByType) export(plotTripTypesPieChart) export(plot_compare_travelwaittime_by_mainmode) +export(plot_distance_by_mainmode_barchart) export(plot_mainmode_barchart) export(plot_mainmode_piechart) export(plot_travelwaittime_mean_barchart) @@ -38,7 +39,6 @@ export(prepareSimwrapperDashboardFromFolder) export(prepareSimwrapperDashboardFromTable) export(processDtvEstimationQuality) export(processLinkStatsDtvDistribution) -export(process_append_distcat) export(readCounts) export(readLinkStats) export(readPersonsTable) diff --git a/R/output_trips.R b/R/output_trips.R index 89499e7..c9ea8ee 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2097,7 +2097,45 @@ plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, } +#' Bar Chart with distance travelled on x-axis and number of trips on y-axis +#' +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' number of trips ~ distance travelled +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' @param trips_table tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @return Bar Chart plot of count of trips among distance travelled +#' +#' @export +plot_distance_by_mainmode_barchart <- function(trips_table, + unite.columns = character(0), + united.name = "united", + dist_column = "dist_cat", + distances_array = c(1000,2000,5000,10000,20000,50000,100000)) { + + + # If some columns should be united + trips_table <- process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, + united.name = united.name) + + trips_table <- process_append_distancecategory(trips_table =trips_table, + distances_array = distances_array) + + + plt = ggplot(trips_table) + + geom_bar(aes(x = dist_cat,fill = main_mode),position = position_dodge())+ + ggtitle("Number of trips per travelling distance") + fig = plotly::ggplotly(plt) + + fig + return(fig) +} #####Processing##### @@ -2145,41 +2183,28 @@ process_get_travelwaittime_by_mainmode<-function(trips_table, } -#' @export -process_append_distcat <- function(tripsTable,distances_array = c(1000,2000,5000,10000,20000,50000,100000)){ - distances_array = sort(distances_array) - modes = levels(factor(tripsTable$main_mode)) +process_append_distancecategory <- function(trips_table,distances_array = c(1000,2000,5000,10000,20000,50000,100000)){ + + distances_array = sort(c(distances_array,c(0,Inf))) + modes = levels(factor(trips_table$main_mode)) - #This is a very bad way to do that, but I see no other way to get it done #Also filtering table into a new doesn't creates new objects in memory, so it works fast #Upd: it creates copy of dataframe on each mutate :/ - for(i in length(distances_array)){ + result_table <- c(NULL) + str_factors<-c(NULL) + for(i in 1:(length(distances_array)-1)){ + part_table <- trips_table %>% + filter(traveled_distance>=distances_array[i] & traveled_distance% + mutate(dist_cat = paste0(distances_array[i],"-",distances_array[i+1])) + str_factors<- c(str_factors,paste0(distances_array[i],"-",distances_array[i+1])) + result_table <- rbind(result_table,part_table) } - tripsTable_05km = tripsTable %>% filter(traveled_distance<=1000) %>% mutate(dist_cat = "0-1km") - tripsTable_2km = tripsTable %>% filter(traveled_distance>1000 & traveled_distance<=2000) %>% mutate(dist_cat = "1-2km") - tripsTable_5km = tripsTable %>% filter(traveled_distance>2000 & traveled_distance<=5000) %>% mutate(dist_cat = "2-5km") - tripsTable_10km = tripsTable %>% filter(traveled_distance>5000 & traveled_distance<=10*1000) %>% mutate(dist_cat = "5-10km") - tripsTable_20km = tripsTable %>% filter(traveled_distance>10*1000 & traveled_distance<=20*1000) %>% mutate(dist_cat = "10-20km") - tripsTable_50km = tripsTable %>% filter(traveled_distance>20*1000 & traveled_distance<=50*1000) %>% mutate(dist_cat = "20-50km") - tripsTable_100km = tripsTable %>% filter(traveled_distance>50*1000 & traveled_distance<=100*1000) %>% mutate(dist_cat = "50-100km") - tripsTable_100pluskm = tripsTable %>% filter(traveled_distance>100*1000) %>% mutate(dist_cat = "> 100km") - - tripsTable_result = rbind(tripsTable_05km, - #tripsTable_1km, - tripsTable_2km, - tripsTable_5km, - tripsTable_10km, - tripsTable_20km, - tripsTable_50km, - tripsTable_100km, - tripsTable_100pluskm) - - tripsTable_result$dist_cat = factor(tripsTable_result$dist_cat,levels = c("0-1km","1-2km","2-5km","5-10km","10-20km","20-50km","50-100km","> 100km")) - return(tripsTable_result) + result_table$dist_cat = factor(result_table$dist_cat,levels = str_factors) + return(result_table) } #' Reads an coordinate referenec system of MATSim output directory diff --git a/man/plot_distance_by_mainmode_barchart.Rd b/man/plot_distance_by_mainmode_barchart.Rd new file mode 100644 index 0000000..48771de --- /dev/null +++ b/man/plot_distance_by_mainmode_barchart.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{plot_distance_by_mainmode_barchart} +\alias{plot_distance_by_mainmode_barchart} +\title{Bar Chart with distance travelled on x-axis and number of trips on y-axis} +\usage{ +plot_distance_by_mainmode_barchart( + trips_table, + unite.columns = character(0), + united.name = "united", + dist_column = "dist_cat", + distances_array = c(1000, 2000, 5000, 10000, 20000, 50000, 1e+05) +) +} +\arguments{ +\item{trips_table}{tible of trips_output (from readTripsTable())} + +\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} + +\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +} +\value{ +Bar Chart plot of count of trips among distance travelled +} +\description{ +Takes Table trips_output (from readTripsTable()), +to plot bar chart with with values that represent +number of trips ~ distance travelled +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +} From 4fc392751acf1a7c84b1e6949ac8ce68116b3018 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Tue, 30 May 2023 16:21:55 +0200 Subject: [PATCH 12/87] added modal distance distribution --- NAMESPACE | 2 + R/output_trips.R | 131 ++++++++++++++++-- ...ot_compare_distcat_by_mainmode_barchart.Rd | 37 +++++ ...plot_compare_travelwaittime_by_mainmode.Rd | 4 - man/plot_distance_by_mainmode_barchart.Rd | 10 +- man/plot_distcat_by_mainmode_barchart.Rd | 30 ++++ man/plot_mainmode_barchart.Rd | 4 - man/plot_mainmode_piechart.Rd | 4 - man/plot_travelwaittime_mean_barchart.Rd | 4 - 9 files changed, 191 insertions(+), 35 deletions(-) create mode 100644 man/plot_compare_distcat_by_mainmode_barchart.Rd create mode 100644 man/plot_distcat_by_mainmode_barchart.Rd diff --git a/NAMESPACE b/NAMESPACE index 089de4e..e393a82 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -29,8 +29,10 @@ export(plotTripCountByDepTime) export(plotTripDistanceByMode) export(plotTripDistancedByType) export(plotTripTypesPieChart) +export(plot_compare_distcat_by_mainmode_barchart) export(plot_compare_travelwaittime_by_mainmode) export(plot_distance_by_mainmode_barchart) +export(plot_distcat_by_mainmode_barchart) export(plot_mainmode_barchart) export(plot_mainmode_piechart) export(plot_travelwaittime_mean_barchart) diff --git a/R/output_trips.R b/R/output_trips.R index c9ea8ee..742768f 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -503,7 +503,9 @@ compareModalDistanceDistribution <- function(tripsTable1,tripsTable2, unite.colu #' @return Bar Chart plot of distance traveled per mode #' #' @export -plotTripDistanceByMode <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, +plotTripDistanceByMode <- function(tripsTable, + unite.columns = character(0), united.name = "united", + dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { @@ -1910,8 +1912,6 @@ read_output_trips <- function(input_path = ".", n_max = Inf) { #' @param trips_table tibble of trips_output (from \link{readTripsTable}) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' #' @return Pie Chart plot of transport mode distribution, values given in percents #' @@ -1925,6 +1925,7 @@ plot_mainmode_piechart <- function(trips_table, unite.columns = unite.columns, united.name = united.name) + # processing # tripsTableCount gives percentage representation out trips_table_count<-process_get_mainmode_distribution(trips_table, percentage= percentage) @@ -1954,8 +1955,6 @@ plot_mainmode_piechart <- function(trips_table, #' @param trips_table tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' #' @return Bar Chart plot of transport mode distribution, values given in percents #' @@ -1970,7 +1969,7 @@ plot_mainmode_barchart <- function(trips_table, trips_table <- process_rename_mainmodes(trips_table = trips_table, unite.columns = unite.columns, united.name = united.name) - # Get percentage + # processing trips_table_count <- process_get_mainmode_distribution(trips_table, percentage = percentage) @@ -1995,8 +1994,6 @@ plot_mainmode_barchart <- function(trips_table, #' @param trips_table tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' #' @return Bar Chart plot of average time spent on travel/wait #' @@ -2042,8 +2039,6 @@ plot_travelwaittime_mean_barchart <- function(trips_table, #' @param tripsTable2 tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' #' @return Bar Chart plot of average time spent on travel/wait #' @@ -2111,7 +2106,7 @@ plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, #' @return Bar Chart plot of count of trips among distance travelled #' #' @export -plot_distance_by_mainmode_barchart <- function(trips_table, +plot_distcat_by_mainmode_barchart <- function(trips_table, unite.columns = character(0), united.name = "united", dist_column = "dist_cat", @@ -2123,10 +2118,12 @@ plot_distance_by_mainmode_barchart <- function(trips_table, unite.columns = unite.columns, united.name = united.name) - trips_table <- process_append_distancecategory(trips_table =trips_table, + #processing + trips_table <- process_append_distcat(trips_table =trips_table, distances_array = distances_array) + #plotting plt = ggplot(trips_table) + geom_bar(aes(x = dist_cat,fill = main_mode),position = position_dodge())+ ggtitle("Number of trips per travelling distance") @@ -2137,6 +2134,105 @@ plot_distance_by_mainmode_barchart <- function(trips_table, } +#' Bar Chart with distance travelled on x-axis and number of trips on y-axis +#' +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' average distance traveled ~ main mode used +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' @param trips_table tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart#' +#' @return Bar Chart plot of distance traveled per mode +#' +#' @export +plot_distance_by_mainmode_barchart <- function(trips_table, + unite.columns = character(0), united.name = "united") { + + + # If some columns should be united + trips_table <- process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, + united.name = united.name) + + #processing + trips_table <- process_get_travdistance_distribution(trips_table = trips_table) + + #plotting + text_for_y <- round(trips_table$avg_dist,digits = 2) + fig <- plot_ly(data = trips_table,x = ~main_mode,y = ~avg_dist, + type = 'bar', + text = text_for_y, + textposition = "auto", + name = "AVG Distance traveled by a person over a day") + fig <- fig %>% layout(yaxis = list(title = "Distance (in meters)"),barmode = "group") + + fig + return(fig) +} + +#' Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis +#' +#' Takes 2 Tables trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' @param tripsTable1 tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 +#' @param tripsTable2 tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' @return Bar Chart plot of count of trips among distance travelled +#' +#' @export +plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, + unite.columns = character(0), united.name = "united", + dist_column = "dist_cat", + distances_array = c(1000,2000,5000,10000,20000,50000,100000)) { + + trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, + unite.columns = unite.columns, + united.name = united.name) + + trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, + unite.columns = unite.columns, + united.name = united.name) + + modes = unique(c(unique(trips_table1$main_mode),unique(trips_table2$main_mode))) + + distribution1 <- process_append_distcat(trips_table1,distances_array = distances_array) + distribution2 <- process_append_distcat(trips_table2,distances_array = distances_array) + + + #Get category count difference??? + table_with_сounts1 = distribution1 %>% count(main_mode,dist_cat) + table_with_сounts2 = distribution2 %>% count(main_mode,dist_cat) + + joined <- full_join(table_with_сounts1, table_with_сounts2, by = c("main_mode", "dist_cat")) + + result <- joined %>% + replace_na( list(n.x = 0, n.y = 0) ) %>% + mutate(n = n.y - n.x) %>% + select(main_mode, dist_cat, n) + + + result$dist_cat = factor(result$dist_cat,levels = distances_array) + + + fig = ggplotly(ggplot(result) + + geom_col(aes(x = dist_cat,fill = main_mode, y = n), position = position_dodge())+ + ggtitle("Difference in number of trips per travelling distance")) + + + return(fig) + +} + #####Processing##### @@ -2161,6 +2257,15 @@ process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ return(trips_table_count) } +process_get_travdistance_distribution<-function(trips_table){ + + trips_table = trips_table %>% + group_by(main_mode) %>% + summarize(avg_dist = mean(traveled_distance)) + + return(trips_table) +} + process_get_travelwaittime_by_mainmode<-function(trips_table, time_format = "minute"){#also could be hours/seconds @@ -2184,7 +2289,7 @@ process_get_travelwaittime_by_mainmode<-function(trips_table, -process_append_distancecategory <- function(trips_table,distances_array = c(1000,2000,5000,10000,20000,50000,100000)){ +process_append_distcat <- function(trips_table,distances_array = c(1000,2000,5000,10000,20000,50000,100000)){ distances_array = sort(c(distances_array,c(0,Inf))) modes = levels(factor(trips_table$main_mode)) diff --git a/man/plot_compare_distcat_by_mainmode_barchart.Rd b/man/plot_compare_distcat_by_mainmode_barchart.Rd new file mode 100644 index 0000000..056ed61 --- /dev/null +++ b/man/plot_compare_distcat_by_mainmode_barchart.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{plot_compare_distcat_by_mainmode_barchart} +\alias{plot_compare_distcat_by_mainmode_barchart} +\title{Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis} +\usage{ +plot_compare_distcat_by_mainmode_barchart( + trips_table1, + trips_table2, + unite.columns = character(0), + united.name = "united", + dist_column = "dist_cat", + distances_array = c(1000, 2000, 5000, 10000, 20000, 50000, 1e+05) +) +} +\arguments{ +\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} + +\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} + +\item{tripsTable1}{tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1} + +\item{tripsTable2}{tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted} + +\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} + +\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} +} +\value{ +Bar Chart plot of count of trips among distance travelled +} +\description{ +Takes 2 Tables trips_output (from readTripsTable()), +to plot bar chart with with values that represent +difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +} diff --git a/man/plot_compare_travelwaittime_by_mainmode.Rd b/man/plot_compare_travelwaittime_by_mainmode.Rd index 481626f..546c8d1 100644 --- a/man/plot_compare_travelwaittime_by_mainmode.Rd +++ b/man/plot_compare_travelwaittime_by_mainmode.Rd @@ -20,10 +20,6 @@ plot_compare_travelwaittime_by_mainmode( \item{tripsTable1}{tible of trips_output (from readTripsTable())} \item{tripsTable2}{tible of trips_output (from readTripsTable())} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} - -\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} } \value{ Bar Chart plot of average time spent on travel/wait diff --git a/man/plot_distance_by_mainmode_barchart.Rd b/man/plot_distance_by_mainmode_barchart.Rd index 48771de..adbb2df 100644 --- a/man/plot_distance_by_mainmode_barchart.Rd +++ b/man/plot_distance_by_mainmode_barchart.Rd @@ -7,9 +7,7 @@ plot_distance_by_mainmode_barchart( trips_table, unite.columns = character(0), - united.name = "united", - dist_column = "dist_cat", - distances_array = c(1000, 2000, 5000, 10000, 20000, 50000, 1e+05) + united.name = "united" ) } \arguments{ @@ -17,14 +15,14 @@ plot_distance_by_mainmode_barchart( \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart#'} } \value{ -Bar Chart plot of count of trips among distance travelled +Bar Chart plot of distance traveled per mode } \description{ Takes Table trips_output (from readTripsTable()), to plot bar chart with with values that represent -number of trips ~ distance travelled +average distance traveled ~ main mode used Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') } diff --git a/man/plot_distcat_by_mainmode_barchart.Rd b/man/plot_distcat_by_mainmode_barchart.Rd new file mode 100644 index 0000000..2d1a03e --- /dev/null +++ b/man/plot_distcat_by_mainmode_barchart.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{plot_distcat_by_mainmode_barchart} +\alias{plot_distcat_by_mainmode_barchart} +\title{Bar Chart with distance travelled on x-axis and number of trips on y-axis} +\usage{ +plot_distcat_by_mainmode_barchart( + trips_table, + unite.columns = character(0), + united.name = "united", + dist_column = "dist_cat", + distances_array = c(1000, 2000, 5000, 10000, 20000, 50000, 1e+05) +) +} +\arguments{ +\item{trips_table}{tible of trips_output (from readTripsTable())} + +\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} + +\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +} +\value{ +Bar Chart plot of count of trips among distance travelled +} +\description{ +Takes Table trips_output (from readTripsTable()), +to plot bar chart with with values that represent +number of trips ~ distance travelled +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +} diff --git a/man/plot_mainmode_barchart.Rd b/man/plot_mainmode_barchart.Rd index abc7638..9a5a223 100644 --- a/man/plot_mainmode_barchart.Rd +++ b/man/plot_mainmode_barchart.Rd @@ -18,10 +18,6 @@ plot_mainmode_barchart( \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} \item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} - -\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} } \value{ Bar Chart plot of transport mode distribution, values given in percents diff --git a/man/plot_mainmode_piechart.Rd b/man/plot_mainmode_piechart.Rd index 8974e21..82c8a67 100644 --- a/man/plot_mainmode_piechart.Rd +++ b/man/plot_mainmode_piechart.Rd @@ -17,10 +17,6 @@ plot_mainmode_piechart( \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} \item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} - -\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} } \value{ Pie Chart plot of transport mode distribution, values given in percents diff --git a/man/plot_travelwaittime_mean_barchart.Rd b/man/plot_travelwaittime_mean_barchart.Rd index 03d63d2..175b743 100644 --- a/man/plot_travelwaittime_mean_barchart.Rd +++ b/man/plot_travelwaittime_mean_barchart.Rd @@ -17,10 +17,6 @@ plot_travelwaittime_mean_barchart( \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} \item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} - -\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} } \value{ Bar Chart plot of average time spent on travel/wait From 8090ecf917ed7870251b7b653fed09f49cd6ef55 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 31 May 2023 11:28:51 +0200 Subject: [PATCH 13/87] rdname test --- NAMESPACE | 2 + R/output_trips.R | 86 +++++++++++++++++++ man/matsimr-deprecated.Rd | 28 ++++++ man/plot_compare_mainmode_barchart.Rd | 37 ++++++++ ...ot_trips_count_by_deptime_and_mainmode.Rd} | 26 +++--- 5 files changed, 163 insertions(+), 16 deletions(-) create mode 100644 man/plot_compare_mainmode_barchart.Rd rename man/{plotModalDistanceDistribution.Rd => plot_trips_count_by_deptime_and_mainmode.Rd} (52%) diff --git a/NAMESPACE b/NAMESPACE index e393a82..db17582 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -30,12 +30,14 @@ export(plotTripDistanceByMode) export(plotTripDistancedByType) export(plotTripTypesPieChart) export(plot_compare_distcat_by_mainmode_barchart) +export(plot_compare_mainmode_barchart) export(plot_compare_travelwaittime_by_mainmode) export(plot_distance_by_mainmode_barchart) export(plot_distcat_by_mainmode_barchart) export(plot_mainmode_barchart) export(plot_mainmode_piechart) export(plot_travelwaittime_mean_barchart) +export(plot_trips_count_by_deptime_and_mainmode) export(prepareComparisonSimwrapperDashboardFromTable) export(prepareSimwrapperDashboardFromFolder) export(prepareSimwrapperDashboardFromTable) diff --git a/R/output_trips.R b/R/output_trips.R index 742768f..bfe2311 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -331,6 +331,8 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' #' +#' @rdname matsimr-deprecated +#' #' @param tripsTable tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart @@ -2234,6 +2236,90 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, } +#' Line plot with departure time x-axis and number of trips on y-axis +#' +#' Takes Table trips_output (from readTripsTable()), +#' to make line plot with with values that represent +#' count of trips for a specific departure time by main_mode +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @return Line Chart plot of trips count by departure mode per mode +#' +#' @export +plot_trips_count_by_deptime_and_mainmode <- function(trips_table, + unite.columns = character(0), + united.name = "united") { + + + # If some columns should be united + trips_table <- process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, + united.name = united.name) + + + #processing + tripsTable = tripsTable %>% + mutate(dep_time = hour(dep_time)) %>% + count(dep_time,main_mode) + + #plotting + fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) + fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") + + fig + return(fig) +} + +#' Plot bar chart diagram of transport mode changes +#' +#' Takes two trips_table (from readTripsTable), and collects +#' changes between transport mode distribution of these tables +#' to make bar chart diagram with dodging positioning from this data +#' +#' Function calculates number of each transport mode used in +#' first and second table, and draws plot that represent how +#' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) +#' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") +#' Using parameter show.onlyChanges +#' +#' @param tripsTable1 tible of trips_output (from readTripsTable()) +#' @param tripsTable2 tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name if columns were united, you can specify name for the resulting column in plot +#' +#' @return plots Bar Chart of transport mode changes with additional files for simwrapper +#' +#' @export +plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, + unite.columns = character(0), + united.name = "united") { + # If the unite.columns is specified, then + #print(dump.output.to) + trips_table1 <- process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, + united.name = united.name) + + trips_table2 <- process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, + united.name = united.name) + + trips_table1 = trips_table1 %>% mutate(type = "base") + trips_table2 = trips_table2 %>% mutate(type = "policy") + + total_trips = rbind(trips_table1,trips_table2) + + plt = ggplot(total_trips, aes(x =main_mode,fill = factor(type)))+ + geom_bar(position = position_dodge())+ + coord_flip() + plotly::ggplotly(plt) + + return(plotly::ggplotly(plt)) +} + #####Processing##### process_rename_mainmodes<-function(trips_table, diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 1c90d25..83d8daf 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -8,6 +8,7 @@ \alias{readTripsTable} \alias{plotAverageTravelWait} \alias{compareAverageTravelWait} +\alias{plotModalDistanceDistribution} \alias{appendDistanceCategory} \title{Deprecated function(s) in the matsimr package} \usage{ @@ -46,12 +47,39 @@ compareAverageTravelWait( only.files = FALSE ) +plotModalDistanceDistribution( + tripsTable, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + only.files = FALSE +) + appendDistanceCategory(tripsTable) } +\arguments{ +\item{tripsTable}{tible of trips_output (from readTripsTable())} + +\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} + +\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} + +\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} + +\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} +} +\value{ +Bar Chart plot of count of trips among distance travelled +} \description{ These functions are provided for compatibility with older version of the matsimr package. They may eventually be completely removed. + +Takes Table trips_output (from readTripsTable()), +to plot bar chart with with values that represent +number of trips ~ distance travelled +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') } \section{Details}{ diff --git a/man/plot_compare_mainmode_barchart.Rd b/man/plot_compare_mainmode_barchart.Rd new file mode 100644 index 0000000..ecc40df --- /dev/null +++ b/man/plot_compare_mainmode_barchart.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{plot_compare_mainmode_barchart} +\alias{plot_compare_mainmode_barchart} +\title{Plot bar chart diagram of transport mode changes} +\usage{ +plot_compare_mainmode_barchart( + trips_table1, + trips_table2, + unite.columns = character(0), + united.name = "united" +) +} +\arguments{ +\item{unite.columns}{vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} + +\item{united.name}{if columns were united, you can specify name for the resulting column in plot} + +\item{tripsTable1}{tible of trips_output (from readTripsTable())} + +\item{tripsTable2}{tible of trips_output (from readTripsTable())} +} +\value{ +plots Bar Chart of transport mode changes with additional files for simwrapper +} +\description{ +Takes two trips_table (from readTripsTable), and collects +changes between transport mode distribution of these tables +to make bar chart diagram with dodging positioning from this data +} +\details{ +Function calculates number of each transport mode used in +first and second table, and draws plot that represent how +distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) +Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") +Using parameter show.onlyChanges +} diff --git a/man/plotModalDistanceDistribution.Rd b/man/plot_trips_count_by_deptime_and_mainmode.Rd similarity index 52% rename from man/plotModalDistanceDistribution.Rd rename to man/plot_trips_count_by_deptime_and_mainmode.Rd index e29ced2..d9b4bb3 100644 --- a/man/plotModalDistanceDistribution.Rd +++ b/man/plot_trips_count_by_deptime_and_mainmode.Rd @@ -1,34 +1,28 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/output_trips.R -\name{plotModalDistanceDistribution} -\alias{plotModalDistanceDistribution} -\title{Bar Chart with distance travelled on x-axis and number of trips on y-axis} +\name{plot_trips_count_by_deptime_and_mainmode} +\alias{plot_trips_count_by_deptime_and_mainmode} +\title{Line plot with departure time x-axis and number of trips on y-axis} \usage{ -plotModalDistanceDistribution( - tripsTable, +plot_trips_count_by_deptime_and_mainmode( + trips_table, unite.columns = character(0), - united.name = "united", - dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE + united.name = "united" ) } \arguments{ -\item{tripsTable}{tible of trips_output (from readTripsTable())} - \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} \item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} - -\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} +\item{tripsTable}{tible of trips_output (from readTripsTable())} } \value{ -Bar Chart plot of count of trips among distance travelled +Line Chart plot of trips count by departure mode per mode } \description{ Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -number of trips ~ distance travelled +to make line plot with with values that represent +count of trips for a specific departure time by main_mode Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') } From 635985a049f18d12c90de2071bee062f5c97120f Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 31 May 2023 11:34:51 +0200 Subject: [PATCH 14/87] rdname readtripstable --- R/output_trips.R | 13 ++++++++----- man/matsimr-deprecated.Rd | 9 +++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index bfe2311..c950e78 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -215,15 +215,18 @@ plotModalSplitBarChart <- function(tripsTable, } -#' Deprecated function(s) in the matsimr package +#' Load MATSIM output_trips table into Memory #' +#' Loads a MATSim CSV output_trips from file or archive, +#' creating a tibble with columns as in csv file #' -#' @rdname matsimr-deprecated +#'@rdname matsimr-deprecated #' -#' @docType package -#' @export readTripsTable -#' @aliases readTripsTable +#' @param input_path character string, path to matsim output directory or http link to the file. +#' @param n_max integer, maximum number of lines to read within output_trips +#' @return tibble of trips_output #' +#' @export readTripsTable <-function(input_path = ".", n_max = Inf) { .Deprecated("read_output_trips") return(read_output_trips(input_path,n_max)) diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 83d8daf..8975ca3 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -67,8 +67,14 @@ appendDistanceCategory(tripsTable) \item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} \item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} + +\item{input_path}{character string, path to matsim output directory or http link to the file.} + +\item{n_max}{integer, maximum number of lines to read within output_trips} } \value{ +tibble of trips_output + Bar Chart plot of count of trips among distance travelled } \description{ @@ -76,6 +82,9 @@ These functions are provided for compatibility with older version of the matsimr package. They may eventually be completely removed. +Loads a MATSim CSV output_trips from file or archive, +creating a tibble with columns as in csv file + Takes Table trips_output (from readTripsTable()), to plot bar chart with with values that represent number of trips ~ distance travelled From d04ad3f63d575ef673a2dd1d4f14d02053cf08ef Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 31 May 2023 11:38:13 +0200 Subject: [PATCH 15/87] name test --- R/output_trips.R | 3 +++ 1 file changed, 3 insertions(+) diff --git a/R/output_trips.R b/R/output_trips.R index c950e78..ec7435d 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -221,6 +221,7 @@ plotModalSplitBarChart <- function(tripsTable, #' creating a tibble with columns as in csv file #' #'@rdname matsimr-deprecated +#' @name readTripsTable #' #' @param input_path character string, path to matsim output directory or http link to the file. #' @param n_max integer, maximum number of lines to read within output_trips @@ -336,6 +337,8 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch #' #' @rdname matsimr-deprecated #' +#' @name plotModalDistanceDistribution +#' #' @param tripsTable tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart From 7048f43ee24381fa65104bd350efa265a498d92f Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 31 May 2023 13:24:23 +0200 Subject: [PATCH 16/87] removed rdname --- NAMESPACE | 2 +- R/output_trips.R | 10 +++++++--- man/matsimr-deprecated.Rd | 12 ----------- ...ount_by_deptime_and_mainmode_linechart.Rd} | 6 +++--- man/readTripsTable.Rd | 20 +++++++++++++++++++ 5 files changed, 31 insertions(+), 19 deletions(-) rename man/{plot_trips_count_by_deptime_and_mainmode.Rd => plot_trips_count_by_deptime_and_mainmode_linechart.Rd} (86%) create mode 100644 man/readTripsTable.Rd diff --git a/NAMESPACE b/NAMESPACE index db17582..baaae97 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -37,7 +37,7 @@ export(plot_distcat_by_mainmode_barchart) export(plot_mainmode_barchart) export(plot_mainmode_piechart) export(plot_travelwaittime_mean_barchart) -export(plot_trips_count_by_deptime_and_mainmode) +export(plot_trips_count_by_deptime_and_mainmode_linechart) export(prepareComparisonSimwrapperDashboardFromTable) export(prepareSimwrapperDashboardFromFolder) export(prepareSimwrapperDashboardFromTable) diff --git a/R/output_trips.R b/R/output_trips.R index ec7435d..6dabe7c 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -215,12 +215,11 @@ plotModalSplitBarChart <- function(tripsTable, } -#' Load MATSIM output_trips table into Memory +#' **Deprecated. (see matsimr-deprecated)** Load MATSIM output_trips table into Memory #' #' Loads a MATSim CSV output_trips from file or archive, #' creating a tibble with columns as in csv file #' -#'@rdname matsimr-deprecated #' @name readTripsTable #' #' @param input_path character string, path to matsim output directory or http link to the file. @@ -2168,6 +2167,11 @@ plot_distance_by_mainmode_barchart <- function(trips_table, #processing trips_table <- process_get_travdistance_distribution(trips_table = trips_table) + + #if(only.process){ + # return(trips_table) + #} + #plotting text_for_y <- round(trips_table$avg_dist,digits = 2) fig <- plot_ly(data = trips_table,x = ~main_mode,y = ~avg_dist, @@ -2256,7 +2260,7 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, #' @return Line Chart plot of trips count by departure mode per mode #' #' @export -plot_trips_count_by_deptime_and_mainmode <- function(trips_table, +plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, unite.columns = character(0), united.name = "united") { diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 8975ca3..e785c35 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -5,7 +5,6 @@ \alias{matsimr-deprecated} \alias{plotModalSplitPieChart} \alias{plotModalSplitBarChart} -\alias{readTripsTable} \alias{plotAverageTravelWait} \alias{compareAverageTravelWait} \alias{plotModalDistanceDistribution} @@ -28,8 +27,6 @@ plotModalSplitBarChart( only.files = FALSE ) -readTripsTable(input_path = ".", n_max = Inf) - plotAverageTravelWait( tripsTable, unite.columns = character(0), @@ -67,14 +64,8 @@ appendDistanceCategory(tripsTable) \item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} \item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} - -\item{input_path}{character string, path to matsim output directory or http link to the file.} - -\item{n_max}{integer, maximum number of lines to read within output_trips} } \value{ -tibble of trips_output - Bar Chart plot of count of trips among distance travelled } \description{ @@ -82,9 +73,6 @@ These functions are provided for compatibility with older version of the matsimr package. They may eventually be completely removed. -Loads a MATSim CSV output_trips from file or archive, -creating a tibble with columns as in csv file - Takes Table trips_output (from readTripsTable()), to plot bar chart with with values that represent number of trips ~ distance travelled diff --git a/man/plot_trips_count_by_deptime_and_mainmode.Rd b/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd similarity index 86% rename from man/plot_trips_count_by_deptime_and_mainmode.Rd rename to man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd index d9b4bb3..6622b1b 100644 --- a/man/plot_trips_count_by_deptime_and_mainmode.Rd +++ b/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/output_trips.R -\name{plot_trips_count_by_deptime_and_mainmode} -\alias{plot_trips_count_by_deptime_and_mainmode} +\name{plot_trips_count_by_deptime_and_mainmode_linechart} +\alias{plot_trips_count_by_deptime_and_mainmode_linechart} \title{Line plot with departure time x-axis and number of trips on y-axis} \usage{ -plot_trips_count_by_deptime_and_mainmode( +plot_trips_count_by_deptime_and_mainmode_linechart( trips_table, unite.columns = character(0), united.name = "united" diff --git a/man/readTripsTable.Rd b/man/readTripsTable.Rd new file mode 100644 index 0000000..176d197 --- /dev/null +++ b/man/readTripsTable.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{readTripsTable} +\alias{readTripsTable} +\title{**Deprecated. (see matsimr-deprecated)** Load MATSIM output_trips table into Memory} +\usage{ +readTripsTable(input_path = ".", n_max = Inf) +} +\arguments{ +\item{input_path}{character string, path to matsim output directory or http link to the file.} + +\item{n_max}{integer, maximum number of lines to read within output_trips} +} +\value{ +tibble of trips_output +} +\description{ +Loads a MATSim CSV output_trips from file or archive, +creating a tibble with columns as in csv file +} From 3b7e4e464a92adc389125589ac71741d20c9b109 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 31 May 2023 16:23:52 +0200 Subject: [PATCH 17/87] plot_compare_mainmode_sankey with plotly --- NAMESPACE | 1 + R/output_trips.R | 95 ++++++++++++++++++++++++++++- man/plot_compare_mainmode_sankey.Rd | 40 ++++++++++++ 3 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 man/plot_compare_mainmode_sankey.Rd diff --git a/NAMESPACE b/NAMESPACE index baaae97..80079ac 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -31,6 +31,7 @@ export(plotTripDistancedByType) export(plotTripTypesPieChart) export(plot_compare_distcat_by_mainmode_barchart) export(plot_compare_mainmode_barchart) +export(plot_compare_mainmode_sankey) export(plot_compare_travelwaittime_by_mainmode) export(plot_distance_by_mainmode_barchart) export(plot_distcat_by_mainmode_barchart) diff --git a/R/output_trips.R b/R/output_trips.R index 6dabe7c..5b03c44 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -965,6 +965,7 @@ plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FA group_by(base_mode, policy_mode) %>% count() + return(joined) # If the unite.commercials flag is set to TRUE, then join all commercials under 1 name commercial if (length(unite.columns) != 0) { joined$base_mode[grep(paste0(unite.columns, collapse = "|"), joined$base_mode)] <- united.name @@ -1812,7 +1813,6 @@ compareBasePolicyShapeOutput <- function(baseFolder,policyFolder,shapeFilePath,c #' appendDistanceCategory <- function(tripsTable){ - distances_array = sort(distances_array) modes = levels(factor(tripsTable$main_mode)) #This is a very bad way to do that, but I see no other way to get it done @@ -2330,6 +2330,99 @@ plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, return(plotly::ggplotly(plt)) } +#' Plot alluvial/sankey diagram of transport mode changes +#' +#' Takes two trips_table (from readTripsTable), and collects +#' changes between transport mode distribution of these tables +#' to make alluvial diagram from this data +#' +#' Function calculates number of each transport mode used in +#' first and second table, and draws plot that represent how +#' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) +#' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") +#' Using parameter show.onlyChanges +#' +#' @param tripsTable1 tible of trips_output (from readTripsTable()) +#' @param tripsTable2 tible of trips_output (from readTripsTable()) +#' @param show.onlyChanges boolean, if it is set to TRUE => sankey diagram only contains changes on axes +#' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name if columns were united, you can specify name for the resulting column in plot +#' +#' @return Alluvial diagram that represents changes in transport mode distribution of trip tables +#' +#' @export +plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, + show.onlyChanges = FALSE, + unite.columns = character(0), + united.name = "united") { + + #rename + trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, + unite.columns = unite.columns, + united.name = united.name) + + trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, + unite.columns = unite.columns, + united.name = united.name) + #processing + joined <- as_tibble(inner_join(trips_table1, trips_table2 %>% + select(trip_id, main_mode), by = "trip_id") %>% + dplyr::rename(base_mode = main_mode.x, policy_mode = main_mode.y)) + + #if onlychanges, then we should exclude base_mode=policy_mode + if (show.onlyChanges == TRUE) { + joined <- joined %>% + filter(base_mode != policy_mode) + } + + joined <- joined %>% + group_by(base_mode, policy_mode) %>% + count() + + modes = unique(c(joined$base_mode,joined$policy_mode)) + + joined$base_mode <- as.numeric(factor(joined$base_mode,levels = modes)) + joined$policy_mode <- as.numeric(factor(joined$policy_mode,levels = modes)) + + + #plotting + mypal <- colorRampPalette( c( "blue", "red" ) )( 7 ) + + + fig <- plot_ly( + type = "sankey", + orientation = "h", + + node = list( + label = c(modes,modes), + color = c(mypal,mypal), + pad = 15, + thickness = 20, + line = list( + color = "black", + width = 0.5 + ) + ), + + link = list( + source = joined$base_mode-1, + target = joined$policy_mode+6, + value = joined$n + ) + ) + fig <- fig %>% layout( + title = "Basic Sankey Diagram", + font = list( + size = 10 + ) + ) + + fig + return(fig) +} + + + #####Processing##### process_rename_mainmodes<-function(trips_table, diff --git a/man/plot_compare_mainmode_sankey.Rd b/man/plot_compare_mainmode_sankey.Rd new file mode 100644 index 0000000..6288d92 --- /dev/null +++ b/man/plot_compare_mainmode_sankey.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{plot_compare_mainmode_sankey} +\alias{plot_compare_mainmode_sankey} +\title{Plot alluvial/sankey diagram of transport mode changes} +\usage{ +plot_compare_mainmode_sankey( + trips_table1, + trips_table2, + show.onlyChanges = FALSE, + unite.columns = character(0), + united.name = "united" +) +} +\arguments{ +\item{show.onlyChanges}{boolean, if it is set to TRUE => sankey diagram only contains changes on axes} + +\item{unite.columns}{vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} + +\item{united.name}{if columns were united, you can specify name for the resulting column in plot} + +\item{tripsTable1}{tible of trips_output (from readTripsTable())} + +\item{tripsTable2}{tible of trips_output (from readTripsTable())} +} +\value{ +Alluvial diagram that represents changes in transport mode distribution of trip tables +} +\description{ +Takes two trips_table (from readTripsTable), and collects +changes between transport mode distribution of these tables +to make alluvial diagram from this data +} +\details{ +Function calculates number of each transport mode used in +first and second table, and draws plot that represent how +distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) +Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") +Using parameter show.onlyChanges +} From df66d2c6db7a24a08f633f2ad98a10f23ee0bd3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Thu, 1 Jun 2023 13:53:43 +0200 Subject: [PATCH 18/87] working on documentation --- R/counts.R | 47 ++++++++++++++++++++++++++++------------------- R/output_trips.R | 3 ++- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/R/counts.R b/R/counts.R index 0d3b0a4..4f5962d 100644 --- a/R/counts.R +++ b/R/counts.R @@ -8,14 +8,14 @@ #' #'@title Load a MATSim Counts file into memory #' -#'@description Loads a MATSim Counts XML-File as tibble into memory -#' +#'@description Loads a MATSim Counts XML-File as tibble into memory#' #' #'@param file File to load. Must be an .xml file #' -#'@return tibble containing with MATSim Link id as "loc_id" as key +#'@return tibble with MATSim link id ("loc_id") as key #' #'@export +#' readCounts <- function(file){ message = paste("Read counts file from", file) @@ -51,11 +51,14 @@ readCounts <- function(file){ result } -#' Load linkstats as tibble into memory +# XXXX - why tsv file when it's supposed to be comma separated? is this a standard MATSim output? +# XXXX - what are time bins? qsim mode? + +#' Load a MATSim linkstats file into memory #' -#' Reads Linkstats as .tsv created from LinkStats.class -#' as dataframe into memory. -#' Counts can be provided in any time bins. +#' Loads a linkstats tsv file created from the LinkStats class +#' as a dataframe into memory. +#' Counts can be provided in any time bin. #' Counts can be provided for any qsim mode. The argument networkModes is used to #' select and filter the columns. #' @@ -77,7 +80,7 @@ readLinkStats <- function(runId, file, sampleSize = 0.25){ return(NA) } - message <- paste("Read in link stats from run", runId, ". Loading data from", file ) + message <- paste("Read link stats from run", runId, ". Loading data from", file ) print(message) linkstats <- readr::read_csv(file = file) @@ -107,30 +110,36 @@ readLinkStats <- function(runId, file, sampleSize = 0.25){ } -#' Load Counts, a limited number of Linkstats and Network links as joined tibble into memory +#XXXX why is linkstats a list? in the other function we create a tibble, no? +#XXXX can this be done without linkstats or is that a different function? +#XXXX in error message it says network needs to be a list, in description a vector? + + +#' Join counts and linkstats to the network, creating a tibble into memory +#' //Load Counts, a limited number of Linkstats and Network links as joined tibble into memory #' -#'Function to join counts, network links and several matsim link stats. Data can be aggregated -#'and filtered by time or network mode. +#'Function to join counts, linkstats and network links. Data can be aggregated +#'and filtered by time or mode. #' #' #'@param counts Tibble with counts data #' #'@param network Tibble with network nodes and links #' -#'@param linkStats List with link stats tibbles -#' -#'@param networkModes a vector with network modes, which are needed for analysis +#'@param linkStats List with linkstats tibbles #' -#'@param aggr_to Determinates if data should be aggregated to hour values or DTV, can either be "day" or "hour" +#'@param networkModes a vector with network modes that will be analyzed, default is "car". #' -#'@param earliest Lower limit to filter link stats by time, default is 0 +#'@param aggr_to Determines if data should be aggregated into hourly bins or as daily traffic volume, can either be "day" or "hour" #' -#'@param latest Upper limit to filter link stats by time, default is 86400 (midnight) +#'@param earliest Lower limit to filter link stats by time, default is 0. #' -#'@return Long-format tibble with MATSim link id as key ("loc_id"), traffic volume from MATSim runs and link type +#'@param latest Upper limit to filter link stats by time, default is 86400 (midnight). #' +#'@return Long-format tibble with MATSim link id as key ("loc_id"), traffic volumes from MATSim runs and link type #' #'@export + mergeCountsAndLinks <- function(counts, network, linkStats, networkModes = c("car"), aggr_to = c("day", "hour"), earliest = 0, latest = 86400){ if(!is.list(linkStats)){ @@ -242,7 +251,7 @@ mergeCountsAndLinks <- function(counts, network, linkStats, networkModes = c("ca join.long } -#' Categorize DTV and calculate DTV distribution +#' Group daily traffic volume (DTV) #' #' Takes a tibble from mergeCountsAndLinks. DTV is categorized into bins. Finally #' data is aggregated to calculate DTV distribution in each link type category, diff --git a/R/output_trips.R b/R/output_trips.R index 89499e7..bb7ed18 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -44,7 +44,7 @@ plotModalSplitPieChart <- function(tripsTable, tripsTable$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable$main_mode)] <- united.name } - # tripsTableCount gives percentage representation out + # calculates the mode share and saves it as a tibble tripsTableCount <- tripsTable %>% count(main_mode) %>% mutate(n = n / sum(n) * 100) @@ -70,6 +70,7 @@ plotModalSplitPieChart <- function(tripsTable, ggtitle("Distribution of transport type") + theme_void() plt + if (file.exists(dump.output.to)) { ggsave(paste0(dump.output.to, "/modalSplitPieChart.png"),width = 6,height = 10, plt) } else { From cbe709c001ac1e71b581af8cc5306989470482b6 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Fri, 2 Jun 2023 13:45:40 +0200 Subject: [PATCH 19/87] added deprecated warnings and new structure for function subcategorie --- NAMESPACE | 3 +- R/output_trips.R | 626 ++++++++++++------ man/deriveODMatrix.Rd | 14 + ...re_travelwaittime_by_mainmode_barchart.Rd} | 6 +- man/plot_distance_by_mainmode_barchart.Rd | 3 +- man/process_filter_by_shape.Rd | 38 ++ 6 files changed, 496 insertions(+), 194 deletions(-) rename man/{plot_compare_travelwaittime_by_mainmode.Rd => plot_compare_travelwaittime_by_mainmode_barchart.Rd} (87%) create mode 100644 man/process_filter_by_shape.Rd diff --git a/NAMESPACE b/NAMESPACE index 80079ac..40e0584 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -32,7 +32,7 @@ export(plotTripTypesPieChart) export(plot_compare_distcat_by_mainmode_barchart) export(plot_compare_mainmode_barchart) export(plot_compare_mainmode_sankey) -export(plot_compare_travelwaittime_by_mainmode) +export(plot_compare_travelwaittime_by_mainmode_barchart) export(plot_distance_by_mainmode_barchart) export(plot_distcat_by_mainmode_barchart) export(plot_mainmode_barchart) @@ -44,6 +44,7 @@ export(prepareSimwrapperDashboardFromFolder) export(prepareSimwrapperDashboardFromTable) export(processDtvEstimationQuality) export(processLinkStatsDtvDistribution) +export(process_filter_by_shape) export(readCounts) export(readLinkStats) export(readPersonsTable) diff --git a/R/output_trips.R b/R/output_trips.R index 5b03c44..15918be 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -244,6 +244,7 @@ readTripsTable <-function(input_path = ".", n_max = Inf) { plotAverageTravelWait <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { + .Deprecated("plot_travelwaittime_mean_barchart") # If some columns should be united if (length(unite.columns) != 0) { tripsTable$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable$main_mode)] <- united.name @@ -281,6 +282,7 @@ plotAverageTravelWait <- function(tripsTable, unite.columns = character(0), unit compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { + .Deprecated("plot_compare_travelwaittime_by_mainmode_barchart") # If some columns should be united if (length(unite.columns) != 0) { tripsTable1$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable1$main_mode)] <- united.name @@ -349,6 +351,7 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch plotModalDistanceDistribution <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { + .Deprecated("plot_distcat_by_mainmode_barchart") # If some columns should be united if (length(unite.columns) != 0) { @@ -439,6 +442,9 @@ plotModalDistanceDistribution <- function(tripsTable, unite.columns = character( #' @export compareModalDistanceDistribution <- function(tripsTable1,tripsTable2, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { + + .Deprecated("plot_compare_distcat_by_mainmode_barchart") + if (length(unite.columns) != 0) { tripsTable1$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable1$main_mode)] <- united.name tripsTable2$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable2$main_mode)] <- united.name @@ -515,6 +521,7 @@ plotTripDistanceByMode <- function(tripsTable, dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { + .Deprecated("plot_distance_by_mainmode_barchart") # If some columns should be united if (length(unite.columns) != 0) { @@ -566,6 +573,7 @@ plotTripDistanceByMode <- function(tripsTable, plotTripCountByDepTime <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { + .Deprecated("plot_trips_count_by_deptime_and_mainmode_linechart") # If some columns should be united if (length(unite.columns) != 0) { @@ -951,6 +959,8 @@ plotTripDistancedByType <- function(tripsTable,shapeTable,crs,dump.output.to = m #' #' @export plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FALSE, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory) { + + .Deprecated("plot_compare_mainmode_sankey") StatStratum <- ggalluvial::StatStratum joined <- as_tibble(inner_join(tripsTable1, tripsTable2 %>% select(trip_id, main_mode), by = "trip_id") %>% @@ -1018,6 +1028,8 @@ plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FA #' @export plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, output.name = "modalShiftBarChart") { + + .Deprecated("plot_compare_mainmode_barchart") # If the unite.columns is specified, then #print(dump.output.to) if (length(unite.columns) != 0) { @@ -1074,6 +1086,7 @@ plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRU ggplot() + geom_sf(data = shapeTable) warning("there is no trip filtered for this map") + return(NaN) } filtered_sf <- transformToSf(filtered, crs = crs, geometry.type = st_point()) st_geometry(filtered_sf) <- "start_wkt" @@ -1752,6 +1765,7 @@ compareBasePolicyOutput <- function(baseFolder,policyFolder,dump.output.to = mat #' @export compareBasePolicyShapeOutput <- function(baseFolder,policyFolder,shapeFilePath,crs,dump.output.to = matsimDumpOutputDirectory) { + base_trips = list(NULL) policy_trips = list(NULL) shape = st_read(shapeFilePath) @@ -1813,6 +1827,7 @@ compareBasePolicyShapeOutput <- function(baseFolder,policyFolder,shapeFilePath,c #' appendDistanceCategory <- function(tripsTable){ + .Deprecated("process_append_distcat") modes = levels(factor(tripsTable$main_mode)) #This is a very bad way to do that, but I see no other way to get it done @@ -1843,6 +1858,218 @@ appendDistanceCategory <- function(tripsTable){ return(tripsTable_result) } +#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape +#' +#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +#' and filters the trips from table depending on *.inshape flags: +#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape +#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +#' +#' @param tripsTable tibble of trips_output (from readTripsTable()) +#' +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @param start.inshape bool, defines trips to conclude (see Description) +#' +#' @param end.inshape bool, defines trips to conclude (see Description) +#' +#' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) +#' +#' @export +filterByRegion <- function(tripsTable, + shapeTable, + crs, + start.inshape = TRUE, end.inshape = TRUE) { + .Deprecated("process_filter_by_shape") + # shapeTable <- st_read(shapeFile) + if (st_crs(shapeTable) == NA) { + st_crs(shapeTable) <- crs + } + + sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) + shapeTable <- st_transform(shapeTable, crs = crs) + # shapeTable isn't table - shape + + union_shape <- st_union(shapeTable) # transforms the crs back to the previous in the file + union_shape <- st_transform(union_shape, crs = st_crs(shapeTable)) + + + st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry + cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile + + st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry + cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile + + # get trips that ended outside of shape + cont_end_outside <- setdiff(1:nrow(sf_table), cont2) + + # get trips that started outside of shape + cont_start_outside <- setdiff(1:nrow(sf_table), cont1) + + if (start.inshape == TRUE && end.inshape == TRUE) { + cont_union <- intersect(cont1, cont2) + } else if (start.inshape == TRUE && end.inshape == FALSE) { + cont_union <- intersect(cont1, cont_end_outside) + } else if (start.inshape == FALSE && end.inshape == TRUE) { + cont_union <- intersect(cont2, cont_start_outside) + } else { + cont_union <- intersect(cont_start_outside, cont_end_outside) # Give back trips that are neither starting and ending outside the area + } + + + return(tripsTable[cont_union, ]) +} + + +#' Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper +#' +#' +#' +#' @param tripsTable table of output trips(from readTripsTable) or path to trips_output file +#' +#' @param shapePath full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @param dump.output.to path to a folder to save csv file of ODMatrix +#' +#' @param colnames if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values +#' +#' @param simwrapper create output in a simwrapper form if set to path of the shapefile +#' +#' @param outer logical that represent if the table should contain outside flow of the shape, it isn't +#' +#' @return tibble of origin/destination matrix +#' +#' @export +deriveODMatrix<- function(tripsTable, + shapePath, + crs, + dump.output.to = matsimDumpOutputDirectory, + simwrapper = FALSE, + colnames = "numeric", + outer = FALSE){ + .Deprecated("process_get_OD_matrix") + defaultW <- getOption("warn") + options(warn = -1) + + #if tripstable given as folder/file + if(sum(class(tripsTable) %in% c("tbl_df","tbl","data.frame"))<1){ + tripsTable <- readTripsTable(tripsTable) + } + + sfTable <- transformToSf(tripsTable,crs,geometry.type = st_point()) + + shape = st_read(shapePath) + + if (st_crs(shape) == NA) { + st_crs(shape) <- crs + } + shape = st_transform(shape,crs = crs) + + sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) + + sf_start = sfTable %>% select(trip_id,start_wkt) + st_geometry(sfTable) = "end_wkt" + sf_end = sfTable %>% select(trip_id,end_wkt) + + #Get all inner intersects + sf_intersect_start = st_contains(shape,sf_start) + sf_intersect_end = st_contains(shape,sf_end) + + + if(outer == TRUE){ + #Get all outer intersects + joined_shape = st_union(shape) + + start_inside = st_contains(joined_shape,sf_start) + end_inside = st_contains(joined_shape,sf_end) + + start_outside = 1:nrow(sf_start) + end_outside = 1:nrow(sf_end) + + start_outside = start_outside[! start_outside %in% start_inside[[1]]] + + end_outside = end_outside[! end_outside %in% end_inside[[1]]] + + sf_intersect_start = append(sf_intersect_start,list(start_outside)) + sf_intersect_end = append(sf_intersect_end,list(end_outside)) + } + + # Create matrix out of it + result_tibble = as_tibble(data.frame(matrix(nrow=0,ncol=nrow(shape)))) + colnames(result_tibble) = 1:nrow(shape) + + for(i in 1:length(sf_intersect_start)){ + temp = c() + for(j in 1:length(sf_intersect_start)){ + start_i = sf_intersect_start[[i]] + end_j = sf_intersect_end[[j]] + + number_of_trips = length(intersect(start_i,end_j)) + + temp = append(temp,number_of_trips) + + } + result_tibble = rbind(result_tibble,temp) + } + + if(colnames!="numeric" & colnames %in% colnames(shape)){ + colnames(result_tibble) = shape[[colnames]] + if(outer == TRUE){ + rownames(result_tibble) = c(shape[[colnames]],"outer") + colnames(result_tibble)[length(colnames(result_tibble))] = "outer" + }else{ + rownames(result_tibble) = shape[[colnames]] + } + + }else{ + colnames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) + rownames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) + } + + + result_melt = melt(as.matrix(result_tibble)) + colnames(result_melt) = c("origin","destination",1) + # Generating yaml and output_files + + + + if (file.exists(dump.output.to) & simwrapper == TRUE) { + write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") + } else if(!file.exists(dump.output.to) & simwrapper == TRUE) { + dir.create(dump.output.to) + write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") + } else if (file.exists(dump.output.to) & simwrapper == FALSE) { + write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) + } else { + dir.create(dump.output.to) + write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) + } + + yaml_list <- list( + title = "OD Flow", + description = "generated by deriveODMatrix", + projection = st_crs(shape)$input, + shpFile = paste0("../",shapePath), + dbfFile = paste0("../",substr(shapePath,start = 1,stop = nchar(shapePath)-3),"dbf"), + scaleFactor = 1, + lineWidth = 50, + csvFile = "ODMatrix.csv", + idColumn = colnames(shape)[1] # at the moment idColumn of shapefile should be the first column + + ) + write_yaml(yaml_list, paste0(dump.output.to, "/viz-od-flow.yaml")) + + options(warn = defaultW) + return(result_tibble) +} #####Reading##### @@ -2034,129 +2261,112 @@ plot_travelwaittime_mean_barchart <- function(trips_table, -#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis + + +#' Bar Chart with distance travelled on x-axis and number of trips on y-axis #' #' Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent -#' time spent on traveling/waiting +#' number of trips ~ distance travelled #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) +#' @param trips_table tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' -#' @return Bar Chart plot of average time spent on travel/wait +#' @return Bar Chart plot of count of trips among distance travelled #' #' @export -plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, - unite.columns = character(0), - united.name = "united", - time_format = "minute") { - - #TODO: - # . Document and add title to show what means positive/negative value - # . think about comparing processing functions they can appear in future often +plot_distcat_by_mainmode_barchart <- function(trips_table, + unite.columns = character(0), + united.name = "united", + dist_column = "dist_cat", + distances_array = c(1000,2000,5000,10000,20000,50000,100000)) { # If some columns should be united - trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.columns = unite.columns, - united.name = united.name) - - trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.columns = unite.columns, - united.name = united.name) + trips_table <- process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, + united.name = united.name) #processing - avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) - - - - avg_time2 = process_get_travelwaittime_by_mainmode(trips_table2,time_format = time_format) + trips_table <- process_append_distcat(trips_table =trips_table, + distances_array = distances_array) - avg_time = full_join(avg_time1, avg_time2, by = "main_mode") %>% - replace_na(list(trav_time_avg.x = 0,wait_time_avg.x = 0,trav_time_avg.y = 0,wait_time_avg.y = 0)) + #plotting + plt = ggplot(trips_table) + + geom_bar(aes(x = dist_cat,fill = main_mode),position = position_dodge())+ + ggtitle("Number of trips per travelling distance") + fig = plotly::ggplotly(plt) + fig + return(fig) - - avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg.x - trav_time_avg.y, - wait_time_avg =wait_time_avg.x - wait_time_avg.y )%>% - select(-wait_time_avg.x,-wait_time_avg.y, -trav_time_avg.x,-trav_time_avg.y) - - - - #plotting - fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") - fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") - fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)")),barmode = "group") - - - fig - return(fig) - -} +} #' Bar Chart with distance travelled on x-axis and number of trips on y-axis #' #' Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent -#' number of trips ~ distance travelled +#' average distance traveled ~ main mode used #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' #' #' @param trips_table tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @return Bar Chart plot of count of trips among distance travelled +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart#' +#' @return Bar Chart plot of distance traveled per mode #' #' @export -plot_distcat_by_mainmode_barchart <- function(trips_table, - unite.columns = character(0), - united.name = "united", - dist_column = "dist_cat", - distances_array = c(1000,2000,5000,10000,20000,50000,100000)) { +plot_distance_by_mainmode_barchart <- function(trips_table, + unite.columns = character(0), united.name = "united", + euclidean = FALSE) { # If some columns should be united trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, - united.name = united.name) + unite.columns = unite.columns, + united.name = united.name) #processing - trips_table <- process_append_distcat(trips_table =trips_table, - distances_array = distances_array) + trips_table <- process_get_travdistance_distribution(trips_table = trips_table,euclidean = euclidean) + #if(only.process){ + # return(trips_table) + #} + #plotting - plt = ggplot(trips_table) + - geom_bar(aes(x = dist_cat,fill = main_mode),position = position_dodge())+ - ggtitle("Number of trips per travelling distance") - fig = plotly::ggplotly(plt) + text_for_y <- round(trips_table$avg_dist,digits = 2) + fig <- plot_ly(data = trips_table,x = ~main_mode,y = ~avg_dist, + type = 'bar', + text = text_for_y, + textposition = "auto", + name = paste0("AVG " ,if_else(euclidean,"eucliden ","traveled ") ,"distance by mode over a day")) + fig <- fig %>% layout(yaxis = list(title = "Distance (in meters)"),barmode = "group") fig return(fig) - } -#' Bar Chart with distance travelled on x-axis and number of trips on y-axis +#' Line plot with departure time x-axis and number of trips on y-axis #' #' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' average distance traveled ~ main mode used +#' to make line plot with with values that represent +#' count of trips for a specific departure time by main_mode #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' #' -#' @param trips_table tible of trips_output (from readTripsTable()) +#' @param tripsTable tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart#' -#' @return Bar Chart plot of distance traveled per mode +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @return Line Chart plot of trips count by departure mode per mode #' #' @export -plot_distance_by_mainmode_barchart <- function(trips_table, - unite.columns = character(0), united.name = "united") { +plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, + unite.columns = character(0), + united.name = "united") { # If some columns should be united @@ -2164,27 +2374,22 @@ plot_distance_by_mainmode_barchart <- function(trips_table, unite.columns = unite.columns, united.name = united.name) - #processing - trips_table <- process_get_travdistance_distribution(trips_table = trips_table) - - #if(only.process){ - # return(trips_table) - #} + #processing + tripsTable = tripsTable %>% + mutate(dep_time = hour(dep_time)) %>% + count(dep_time,main_mode) #plotting - text_for_y <- round(trips_table$avg_dist,digits = 2) - fig <- plot_ly(data = trips_table,x = ~main_mode,y = ~avg_dist, - type = 'bar', - text = text_for_y, - textposition = "auto", - name = "AVG Distance traveled by a person over a day") - fig <- fig %>% layout(yaxis = list(title = "Distance (in meters)"),barmode = "group") + fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) + fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") fig return(fig) } +###### Compare ###### + #' Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis #' #' Takes 2 Tables trips_output (from readTripsTable()), @@ -2246,43 +2451,7 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, } -#' Line plot with departure time x-axis and number of trips on y-axis -#' -#' Takes Table trips_output (from readTripsTable()), -#' to make line plot with with values that represent -#' count of trips for a specific departure time by main_mode -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -#' -#' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @return Line Chart plot of trips count by departure mode per mode -#' -#' @export -plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, - unite.columns = character(0), - united.name = "united") { - - - # If some columns should be united - trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, - united.name = united.name) - - - #processing - tripsTable = tripsTable %>% - mutate(dep_time = hour(dep_time)) %>% - count(dep_time,main_mode) - - #plotting - fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) - fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") - fig - return(fig) -} #' Plot bar chart diagram of transport mode changes #' @@ -2386,7 +2555,7 @@ plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, #plotting - mypal <- colorRampPalette( c( "blue", "red" ) )( 7 ) + palette <- colorRampPalette( c( "blue", "red" ) )( 7 ) fig <- plot_ly( @@ -2395,7 +2564,7 @@ plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, node = list( label = c(modes,modes), - color = c(mypal,mypal), + color = c(palette,palette), pad = 15, thickness = 20, line = list( @@ -2421,8 +2590,73 @@ plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, return(fig) } +#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis +#' +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' time spent on traveling/waiting +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' @param tripsTable1 tible of trips_output (from readTripsTable()) +#' @param tripsTable2 tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' +#' @return Bar Chart plot of average time spent on travel/wait +#' +#' @export +plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_table2, + unite.columns = character(0), + united.name = "united", + time_format = "minute") { + + #TODO: + # . Document and add title to show what means positive/negative value + # . think about comparing processing functions they can appear in future often + + + # If some columns should be united + trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, + unite.columns = unite.columns, + united.name = united.name) + + trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, + unite.columns = unite.columns, + united.name = united.name) + + #processing + avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) + + + + avg_time2 = process_get_travelwaittime_by_mainmode(trips_table2,time_format = time_format) + + + avg_time = full_join(avg_time1, avg_time2, by = "main_mode") %>% + replace_na(list(trav_time_avg.x = 0,wait_time_avg.x = 0,trav_time_avg.y = 0,wait_time_avg.y = 0)) + + + + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg.x - trav_time_avg.y, + wait_time_avg =wait_time_avg.x - wait_time_avg.y )%>% + select(-wait_time_avg.x,-wait_time_avg.y, -trav_time_avg.x,-trav_time_avg.y) + + #plotting + fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") + fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") + fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)")),barmode = "group") + + + fig + return(fig) + +} + +###### Mapping ###### + #####Processing##### process_rename_mainmodes<-function(trips_table, @@ -2446,16 +2680,16 @@ process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ return(trips_table_count) } -process_get_travdistance_distribution<-function(trips_table){ +process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ trips_table = trips_table %>% group_by(main_mode) %>% - summarize(avg_dist = mean(traveled_distance)) + summarize(avg_dist = if_else(euclidian,mean(euclidean_distance),mean(traveled_distance))) return(trips_table) } -process_get_travelwaittime_by_mainmode<-function(trips_table, +process_get_travelwaittime_by_mainmode_barchart<-function(trips_table, time_format = "minute"){#also could be hours/seconds #get 2 columns with mean travel time and mean wait time grouped by main_mode in seconds @@ -2501,6 +2735,75 @@ process_append_distcat <- function(trips_table,distances_array = c(1000,2000,500 return(result_table) } +######Spatial###### +#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape +#' +#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +#' and filters the trips from table depending on *.inshape flags: +#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape +#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +#' +#' @param trips_table tibble of trips_output (from readTripsTable()) +#' +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @param start.inshape bool, defines trips to conclude (see Description) +#' +#' @param end.inshape bool, defines trips to conclude (see Description) +#' +#' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) +#' +#' @export +process_filter_by_shape <- function(trips_table, + shape_table, + crs, + start.inshape = TRUE, end.inshape = TRUE) { + + # shape_table <- st_read(shapeFile) + if (st_crs(shape_table) == NA) { + st_crs(shape_table) <- crs + } + + sf_table <- transformToSf(trips_table, crs = crs, geometry.type = st_point()) + shape_table <- st_transform(shape_table, crs = crs) + # shape_table isn't table - shape + + union_shape <- st_union(shape_table) # transforms the crs back to the previous in the file + union_shape <- st_transform(union_shape, crs = st_crs(shape_table)) + + + st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry + cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile + + st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry + cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile + + # get trips that ended outside of shape + cont_end_outside <- setdiff(1:nrow(sf_table), cont2) + + # get trips that started outside of shape + cont_start_outside <- setdiff(1:nrow(sf_table), cont1) + + if (start.inshape == TRUE && end.inshape == TRUE) { + cont_union <- intersect(cont1, cont2) + } else if (start.inshape == TRUE && end.inshape == FALSE) { + cont_union <- intersect(cont1, cont_end_outside) + } else if (start.inshape == FALSE && end.inshape == TRUE) { + cont_union <- intersect(cont2, cont_start_outside) + } else { + cont_union <- intersect(cont_start_outside, cont_end_outside) # Give back trips that are neither starting and ending outside the area + } + + + return(trips_table[cont_union, ]) +} + #' Reads an coordinate referenec system of MATSim output directory #' from output_config.xml #' @@ -2561,7 +2864,13 @@ getCrsFromConfig <- function(folder) { #' @return tibble of origin/destination matrix #' #' @export -deriveODMatrix<- function(tripsTable,shapePath,crs,dump.output.to = matsimDumpOutputDirectory,simwrapper = FALSE,colnames = "numeric",outer = FALSE){ +deriveODMatrix<- function(tripsTable, + shapePath, + crs, + dump.output.to = matsimDumpOutputDirectory, + simwrapper = FALSE, + colnames = "numeric", + outer = FALSE){ defaultW <- getOption("warn") options(warn = -1) @@ -2677,70 +2986,7 @@ deriveODMatrix<- function(tripsTable,shapePath,crs,dump.output.to = matsimDumpOu return(result_tibble) } -#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape -#' -#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) -#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -#' and filters the trips from table depending on *.inshape flags: -#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape -#' -#' @param tripsTable tibble of trips_output (from readTripsTable()) -#' -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) -#' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation -#' -#' @param start.inshape bool, defines trips to conclude (see Description) -#' -#' @param end.inshape bool, defines trips to conclude (see Description) -#' -#' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) -#' -#' @export -filterByRegion <- function(tripsTable, shapeTable, crs, start.inshape = TRUE, end.inshape = TRUE) { - - # shapeTable <- st_read(shapeFile) - if (st_crs(shapeTable) == NA) { - st_crs(shapeTable) <- crs - } - - sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) - shapeTable <- st_transform(shapeTable, crs = crs) - # shapeTable isn't table - shape - union_shape <- st_union(shapeTable) # transforms the crs back to the previous in the file - union_shape <- st_transform(union_shape, crs = st_crs(shapeTable)) - - - st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry - cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile - - st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry - cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile - - # get trips that ended outside of shape - cont_end_outside <- setdiff(1:nrow(sf_table), cont2) - - # get trips that started outside of shape - cont_start_outside <- setdiff(1:nrow(sf_table), cont1) - - if (start.inshape == TRUE && end.inshape == TRUE) { - cont_union <- intersect(cont1, cont2) - } else if (start.inshape == TRUE && end.inshape == FALSE) { - cont_union <- intersect(cont1, cont_end_outside) - } else if (start.inshape == FALSE && end.inshape == TRUE) { - cont_union <- intersect(cont2, cont_start_outside) - } else { - cont_union <- intersect(cont_start_outside, cont_end_outside) # Give back trips that are neither starting and ending outside the area - } - - - return(tripsTable[cont_union, ]) -} #' Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature) #' @@ -2766,7 +3012,9 @@ filterByRegion <- function(tripsTable, shapeTable, crs, start.inshape = TRUE, en #' @return sf object (data.frame with geometries depending to geometry.type) #' #' @export -transformToSf <- function(table, crs, geometry.type = st_multipoint()) { +transformToSf <- function(table, + crs, + geometry.type = st_multipoint()) { if (class(geometry.type)[2] == "POINT") { table1 <- table %>% # mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep ="")) diff --git a/man/deriveODMatrix.Rd b/man/deriveODMatrix.Rd index ef9f9fe..2cb075f 100644 --- a/man/deriveODMatrix.Rd +++ b/man/deriveODMatrix.Rd @@ -4,6 +4,16 @@ \alias{deriveODMatrix} \title{Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper} \usage{ +deriveODMatrix( + tripsTable, + shapePath, + crs, + dump.output.to = matsimDumpOutputDirectory, + simwrapper = FALSE, + colnames = "numeric", + outer = FALSE +) + deriveODMatrix( tripsTable, shapePath, @@ -30,8 +40,12 @@ deriveODMatrix( \item{outer}{logical that represent if the table should contain outside flow of the shape, it isn't} } \value{ +tibble of origin/destination matrix + tibble of origin/destination matrix } \description{ +Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper + Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper } diff --git a/man/plot_compare_travelwaittime_by_mainmode.Rd b/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd similarity index 87% rename from man/plot_compare_travelwaittime_by_mainmode.Rd rename to man/plot_compare_travelwaittime_by_mainmode_barchart.Rd index 546c8d1..351f164 100644 --- a/man/plot_compare_travelwaittime_by_mainmode.Rd +++ b/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/output_trips.R -\name{plot_compare_travelwaittime_by_mainmode} -\alias{plot_compare_travelwaittime_by_mainmode} +\name{plot_compare_travelwaittime_by_mainmode_barchart} +\alias{plot_compare_travelwaittime_by_mainmode_barchart} \title{Bar Chart with main_mode on x-axis and average travel/wait time on y-axis} \usage{ -plot_compare_travelwaittime_by_mainmode( +plot_compare_travelwaittime_by_mainmode_barchart( trips_table1, trips_table2, unite.columns = character(0), diff --git a/man/plot_distance_by_mainmode_barchart.Rd b/man/plot_distance_by_mainmode_barchart.Rd index adbb2df..dc264f5 100644 --- a/man/plot_distance_by_mainmode_barchart.Rd +++ b/man/plot_distance_by_mainmode_barchart.Rd @@ -7,7 +7,8 @@ plot_distance_by_mainmode_barchart( trips_table, unite.columns = character(0), - united.name = "united" + united.name = "united", + euclidean = FALSE ) } \arguments{ diff --git a/man/process_filter_by_shape.Rd b/man/process_filter_by_shape.Rd new file mode 100644 index 0000000..9f3a93f --- /dev/null +++ b/man/process_filter_by_shape.Rd @@ -0,0 +1,38 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_filter_by_shape} +\alias{process_filter_by_shape} +\title{Filtering of trips_table(from readTripsTable) depending on how they located in given shape} +\usage{ +process_filter_by_shape( + trips_table, + shape_table, + crs, + start.inshape = TRUE, + end.inshape = TRUE +) +} +\arguments{ +\item{trips_table}{tibble of trips_output (from readTripsTable())} + +\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} + +\item{start.inshape}{bool, defines trips to conclude (see Description)} + +\item{end.inshape}{bool, defines trips to conclude (see Description)} + +\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +} +\value{ +tibble, with filtered trips depending on shapeTable and special flags (see Description) +} +\description{ +Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +and filters the trips from table depending on *.inshape flags: +if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape +if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +} From 1763ede1d8b6700b9c45e86d0ba0b35407fd8e31 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Fri, 2 Jun 2023 13:56:52 +0200 Subject: [PATCH 20/87] read_network, od_matrix, read_config --- NAMESPACE | 3 + R/network.R | 138 ++++++++++++++++++++++++++++++++++- R/output_trips.R | 19 ++++- man/deriveODMatrix.Rd | 14 ---- man/process_get_od_matrix.Rd | 37 ++++++++++ man/read_config.Rd | 20 +++++ man/read_network.Rd | 24 ++++++ 7 files changed, 239 insertions(+), 16 deletions(-) create mode 100644 man/process_get_od_matrix.Rd create mode 100644 man/read_config.Rd create mode 100644 man/read_network.Rd diff --git a/NAMESPACE b/NAMESPACE index 40e0584..f48fc15 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -45,10 +45,13 @@ export(prepareSimwrapperDashboardFromTable) export(processDtvEstimationQuality) export(processLinkStatsDtvDistribution) export(process_filter_by_shape) +export(process_get_od_matrix) export(readCounts) export(readLinkStats) export(readPersonsTable) export(readTripsTable) +export(read_config) +export(read_network) export(read_output_trips) export(symlog_trans) export(transformToSf) diff --git a/R/network.R b/R/network.R index f5dce53..f2313de 100644 --- a/R/network.R +++ b/R/network.R @@ -53,7 +53,7 @@ utils::globalVariables(c("name")) #' @return "nodes" and "links" tibbles in a list object. #' #' @export -loadNetwork <- function(filename) { +read_network <- function(filename) { cat(filename, ": ") network <- read_xml(filename) @@ -171,3 +171,139 @@ loadNetwork <- function(filename) { list("nodes" = nodes, "links" = links, "attributes" = networkAttributes) } + + +#' Load MATSim network into memory +#' +#' Loads a MATSim XML network file, creating a nodes tibble and a links tibble. +#' Any node and link attribute records in the network are stored as +#' additional columns in the respective node and link tibbles. +#' +#' The links table is automatically joined with the nodes table so that +#' node x/y coordinates (and any other node attributes) are available on the +#' links table without additional processing. +#' +#' @param filename File to load. Can be XML or gzipped XML +#' +#' @return "nodes" and "links" tibbles in a list object. +#' +#' @export +loadNetwork <- function(filename) { + .Deprecated("read_network") + cat(filename, ": ") + network <- read_xml(filename) + + cat("Nodes..") + node_elements <- network %>% xml_find_all("./nodes/node") + nodes <- tibble( + id = node_elements %>% xml_attr("id"), + x = node_elements %>% xml_attr("x") %>% parse_double(), + y = node_elements %>% xml_attr("y") %>% parse_double(), + ) + + attributes <- node_elements %>% xml_find_all("./attributes/attribute") + # skip if there are no node attributes + if (length(attributes)) { + attrIds <- tibble(id = unlist(map(attributes, function(row) xml_attr(xml_parent(xml_parent(row)), "id")))) + + nodeAttributes <- tibble( + id = attrIds$id, + name = attributes %>% xml_attr("name"), + class = attributes %>% xml_attr("class"), + value = attributes %>% xml_text(), + ) + + # which columns should be converted to numeric? + types <- nodeAttributes %>% + select(name, class) %>% + distinct() + convert <- filter(types, class == "java.lang.Double")$name + + # convert to a format we can join to the links + nodeAttributes <- (nodeAttributes + %>% select(-class) + %>% pivot_wider(names_from = "name", values_from = "value") + %>% mutate_at(vars(one_of(convert)), as.double) + ) + nodes <- nodes %>% left_join(nodeAttributes, by = "id") + } + + cat("Links..") + link_elements <- network %>% xml_find_all("./links/link") + links <- tibble( + id = link_elements %>% xml_attr("id"), + from = link_elements %>% xml_attr("from"), + to = link_elements %>% xml_attr("to"), + length = link_elements %>% xml_attr("length") %>% parse_double(), + freespeed = link_elements %>% xml_attr("freespeed") %>% parse_double(), + capacity = link_elements %>% xml_attr("capacity") %>% parse_double(), + permlanes = link_elements %>% xml_attr("permlanes") %>% parse_double(), + modes = link_elements %>% xml_attr("modes"), + origid = link_elements %>% xml_attr("origid") + ) + + # merge node coordinates + links <- (links + %>% left_join(nodes, by = c("from" = "id")) + %>% left_join(nodes, by = c("to" = "id"), suffix = c(".from", ".to")) + ) + + # attributes don't have IDs on them! JFC, MATSim! + cat("Attributes..") + + attributes <- link_elements %>% xml_find_all("./attributes/attribute") + # skip if there are no link-attributes + if (length(attributes)) { + attrIds <- tibble(id = unlist(map(attributes, function(row) xml_attr(xml_parent(xml_parent(row)), "id")))) + + linkAttributes <- tibble( + id = attrIds$id, + name = attributes %>% xml_attr("name"), + class = attributes %>% xml_attr("class"), + value = attributes %>% xml_text(), + ) + + # which columns should be converted to numeric? + types <- linkAttributes %>% + select(name, class) %>% + distinct() + convert <- filter(types, class == "java.lang.Double")$name + + # convert to a format we can join to the links + linkAttributes <- (linkAttributes + %>% select(-class) + %>% pivot_wider(names_from = "name", values_from = "value") + %>% mutate_at(vars(one_of(convert)), as.double) + ) + + links <- links %>% left_join(linkAttributes, by = "id", suffix = c(".link", ".attr")) + } + + # Top-level network attributes + networkAttributes <- NULL + + allNetworkAttributes <- network %>% xml_find_all("./attributes/attribute") + if (length(allNetworkAttributes)) { + networkAttributes <- tibble( + name = allNetworkAttributes %>% xml_attr("name"), + class = allNetworkAttributes %>% xml_attr("class"), + value = allNetworkAttributes %>% xml_text(), + ) + # which columns should be converted to numeric? + types <- networkAttributes %>% + select(name, class) %>% + distinct() + convert <- filter(types, class == "java.lang.Double")$name + + # convert to a format we can join to the links + networkAttributes <- (networkAttributes + %>% select(-class) + %>% pivot_wider(names_from = "name", values_from = "value") + %>% mutate_at(vars(one_of(convert)), as.double) + ) + } + + cat("Done!\n") + + list("nodes" = nodes, "links" = links, "attributes" = networkAttributes) +} diff --git a/R/output_trips.R b/R/output_trips.R index 15918be..619e4c5 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2129,8 +2129,24 @@ read_output_trips <- function(input_path = ".", n_max = Inf) { } +#' Load MATSIM config file into Memory +#' +#' Loads a MATSim xml config from file or archive, +#' creating a list with parameters as in xml file +#' +#' @param input_path character string, path to matsim output directory or http link to the file. +#' @param n_max integer, maximum number of lines to read within output_trips +#' @return tibble of trips_output +#' +#' @export +read_config <- function(input_path = ".", n_max = Inf) { + + return(trips_output_table) + +} + #####Plotting##### #' Plot main_mode distribution as a Pie Chart @@ -2864,13 +2880,14 @@ getCrsFromConfig <- function(folder) { #' @return tibble of origin/destination matrix #' #' @export -deriveODMatrix<- function(tripsTable, +process_get_od_matrix<- function(tripsTable, shapePath, crs, dump.output.to = matsimDumpOutputDirectory, simwrapper = FALSE, colnames = "numeric", outer = FALSE){ + defaultW <- getOption("warn") options(warn = -1) diff --git a/man/deriveODMatrix.Rd b/man/deriveODMatrix.Rd index 2cb075f..ef9f9fe 100644 --- a/man/deriveODMatrix.Rd +++ b/man/deriveODMatrix.Rd @@ -4,16 +4,6 @@ \alias{deriveODMatrix} \title{Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper} \usage{ -deriveODMatrix( - tripsTable, - shapePath, - crs, - dump.output.to = matsimDumpOutputDirectory, - simwrapper = FALSE, - colnames = "numeric", - outer = FALSE -) - deriveODMatrix( tripsTable, shapePath, @@ -40,12 +30,8 @@ deriveODMatrix( \item{outer}{logical that represent if the table should contain outside flow of the shape, it isn't} } \value{ -tibble of origin/destination matrix - tibble of origin/destination matrix } \description{ -Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper - Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper } diff --git a/man/process_get_od_matrix.Rd b/man/process_get_od_matrix.Rd new file mode 100644 index 0000000..988818a --- /dev/null +++ b/man/process_get_od_matrix.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_get_od_matrix} +\alias{process_get_od_matrix} +\title{Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper} +\usage{ +process_get_od_matrix( + tripsTable, + shapePath, + crs, + dump.output.to = matsimDumpOutputDirectory, + simwrapper = FALSE, + colnames = "numeric", + outer = FALSE +) +} +\arguments{ +\item{tripsTable}{table of output trips(from readTripsTable) or path to trips_output file} + +\item{shapePath}{full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name)} + +\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} + +\item{dump.output.to}{path to a folder to save csv file of ODMatrix} + +\item{simwrapper}{create output in a simwrapper form if set to path of the shapefile} + +\item{colnames}{if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values} + +\item{outer}{logical that represent if the table should contain outside flow of the shape, it isn't} +} +\value{ +tibble of origin/destination matrix +} +\description{ +Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper +} diff --git a/man/read_config.Rd b/man/read_config.Rd new file mode 100644 index 0000000..4833ee0 --- /dev/null +++ b/man/read_config.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{read_config} +\alias{read_config} +\title{Load MATSIM config file into Memory} +\usage{ +read_config(input_path = ".", n_max = Inf) +} +\arguments{ +\item{input_path}{character string, path to matsim output directory or http link to the file.} + +\item{n_max}{integer, maximum number of lines to read within output_trips} +} +\value{ +tibble of trips_output +} +\description{ +Loads a MATSim xml config from file or archive, +creating a list with parameters as in xml file +} diff --git a/man/read_network.Rd b/man/read_network.Rd new file mode 100644 index 0000000..2602e44 --- /dev/null +++ b/man/read_network.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/network.R +\name{read_network} +\alias{read_network} +\title{Load MATSim network into memory} +\usage{ +read_network(filename) +} +\arguments{ +\item{filename}{File to load. Can be XML or gzipped XML} +} +\value{ +"nodes" and "links" tibbles in a list object. +} +\description{ +Loads a MATSim XML network file, creating a nodes tibble and a links tibble. +Any node and link attribute records in the network are stored as +additional columns in the respective node and link tibbles. +} +\details{ +The links table is automatically joined with the nodes table so that +node x/y coordinates (and any other node attributes) are available on the +links table without additional processing. +} From b4c50a65dbd3a28e5601aacf36d1d3cc02fea649 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Fri, 2 Jun 2023 14:51:22 +0200 Subject: [PATCH 21/87] first implementation read_config --- NAMESPACE | 1 + R/config.R | 40 +++++++++++++++++ R/output_trips.R | 71 ++++++++++++++++++++---------- man/process_get_crs_from_config.Rd | 19 ++++++++ man/read_config.Rd | 2 +- 5 files changed, 109 insertions(+), 24 deletions(-) create mode 100644 R/config.R create mode 100644 man/process_get_crs_from_config.Rd diff --git a/NAMESPACE b/NAMESPACE index f48fc15..9d846bf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -45,6 +45,7 @@ export(prepareSimwrapperDashboardFromTable) export(processDtvEstimationQuality) export(processLinkStatsDtvDistribution) export(process_filter_by_shape) +export(process_get_crs_from_config) export(process_get_od_matrix) export(readCounts) export(readLinkStats) diff --git a/R/config.R b/R/config.R new file mode 100644 index 0000000..081a03a --- /dev/null +++ b/R/config.R @@ -0,0 +1,40 @@ +#' Load MATSIM config file into Memory +#' +#' Loads a MATSim xml config from file or archive, +#' creating a list with parameters as in xml file +#' +#' @param input_path character string, path to matsim output directory or http link to the file. +#' @param n_max integer, maximum number of lines to read within output_trips +#' @return tibble of trips_output +#' +#' @export +read_config <- function(input_path = ".", n_max = Inf) { + + result_tibble <- tibble(module = character(), + param = character(), + value = character()) + + config_xml = read_xml(input_path) + + module_nodeset = xml_children(config_xml) + + for(i in 1:length(module_nodeset)){ + module_name = xml_attr(module_nodeset[[i]],"name") + print(module_name) + param_nodeset = xml_children(module_nodeset[[i]]) + for(j in 1:length(param_nodeset)){ + param_name = xml_attr(param_nodeset[[j]],"name") + value_name = xml_attr(param_nodeset[[j]],"value") + #print(param_name,value_name) + temp_tibble = tibble(module = module_name, + param = param_name, + value = value_name + ) + result_tibble = rbind(result_tibble,temp_tibble) + } + + } + + return(result_tibble) + +} diff --git a/R/output_trips.R b/R/output_trips.R index 619e4c5..f2516d4 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2071,6 +2071,46 @@ deriveODMatrix<- function(tripsTable, return(result_tibble) } + +#' Reads an coordinate referenec system of MATSim output directory +#' from output_config.xml +#' +#' @param folder specifies path to find config +#' +#' +#' @return code of coordinate reference system +#' +#' @export +getCrsFromConfig <- function(folder) { + + if (grepl("output_config.xml$", folder) == TRUE) + { + config <- read_xml(folder) + + param_nodes = xml_find_all(config,"//param") + + coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] + + coord_system = xml_attr(coord_node,"value") + return(coord_system) + } + + files <- list.files(folder, full.names = TRUE) + # Read from global/local directory + # output_config.xml is contained as output_trips.csv.gz + if (length(grep("output_config.xml$", files)) != 0) { + config <- read_xml(files[grep("output_config.xml$", files)]) + + param_nodes = xml_find_all(config,"//param") + + coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] + + coord_system = xml_attr(coord_node,"value") + return(coord_system) + } + return(NA) +} + #####Reading##### @@ -2129,23 +2169,7 @@ read_output_trips <- function(input_path = ".", n_max = Inf) { } -#' Load MATSIM config file into Memory -#' -#' Loads a MATSim xml config from file or archive, -#' creating a list with parameters as in xml file -#' -#' @param input_path character string, path to matsim output directory or http link to the file. -#' @param n_max integer, maximum number of lines to read within output_trips -#' @return tibble of trips_output -#' -#' @export -read_config <- function(input_path = ".", n_max = Inf) { - - - return(trips_output_table) - -} #####Plotting##### @@ -2414,8 +2438,8 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 -#' @param tripsTable2 tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted +#' @param trips_table1 tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 +#' @param trips_table2 tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored @@ -2442,7 +2466,8 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, distribution2 <- process_append_distcat(trips_table2,distances_array = distances_array) - #Get category count difference??? + #Get category count difference + table_with_сounts1 = distribution1 %>% count(main_mode,dist_cat) table_with_сounts2 = distribution2 %>% count(main_mode,dist_cat) @@ -2823,15 +2848,15 @@ process_filter_by_shape <- function(trips_table, #' Reads an coordinate referenec system of MATSim output directory #' from output_config.xml #' -#' @param folder specifies path to find config +#' @param config_path specifies path to find config #' #' #' @return code of coordinate reference system #' #' @export -getCrsFromConfig <- function(folder) { +process_get_crs_from_config <- function(config_path) { - if (grepl("output_config.xml$", folder) == TRUE) + if (grepl("output_config.xml$", config_path) == TRUE) { config <- read_xml(folder) @@ -2843,7 +2868,7 @@ getCrsFromConfig <- function(folder) { return(coord_system) } - files <- list.files(folder, full.names = TRUE) + files <- list.files(config_path, full.names = TRUE) # Read from global/local directory # output_config.xml is contained as output_trips.csv.gz if (length(grep("output_config.xml$", files)) != 0) { diff --git a/man/process_get_crs_from_config.Rd b/man/process_get_crs_from_config.Rd new file mode 100644 index 0000000..10cdb61 --- /dev/null +++ b/man/process_get_crs_from_config.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_get_crs_from_config} +\alias{process_get_crs_from_config} +\title{Reads an coordinate referenec system of MATSim output directory +from output_config.xml} +\usage{ +process_get_crs_from_config(config_path) +} +\arguments{ +\item{config_path}{specifies path to find config} +} +\value{ +code of coordinate reference system +} +\description{ +Reads an coordinate referenec system of MATSim output directory +from output_config.xml +} diff --git a/man/read_config.Rd b/man/read_config.Rd index 4833ee0..fce5fbb 100644 --- a/man/read_config.Rd +++ b/man/read_config.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R +% Please edit documentation in R/config.R \name{read_config} \alias{read_config} \title{Load MATSIM config file into Memory} From b283c85e3189b82c81b69ef775505575718092d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Fri, 2 Jun 2023 17:55:57 +0200 Subject: [PATCH 22/87] editing documentation --- R/counts.R | 2 +- R/output_trips.R | 286 +++++++++++++++++++++++------------------------ 2 files changed, 144 insertions(+), 144 deletions(-) diff --git a/R/counts.R b/R/counts.R index 4f5962d..f386707 100644 --- a/R/counts.R +++ b/R/counts.R @@ -52,7 +52,7 @@ readCounts <- function(file){ } # XXXX - why tsv file when it's supposed to be comma separated? is this a standard MATSim output? -# XXXX - what are time bins? qsim mode? +# XXXX - what are time bins? qsim mode? are they supposed to be parameters? how are they provided? #' Load a MATSim linkstats file into memory #' diff --git a/R/output_trips.R b/R/output_trips.R index 9f52d8e..ca01bac 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -1854,7 +1854,7 @@ appendDistanceCategory <- function(tripsTable){ #' creating a tibble with columns as in csv file #' #' @param input_path character string, path to matsim output directory or http link to the file. -#' @param n_max integer, maximum number of lines to read within output_trips +#' @param n_max optional, integer, maximum number of lines to read, standard value is Inf #' @return tibble of trips_output #' #' @export @@ -1890,7 +1890,7 @@ read_output_trips <- function(input_path = ".", n_max = Inf) { ) ) # person is mostly integer, but contains also chars(see Hamburg 110813 observation) - # doesn't reads coordinates correctly + # doesn't read coordinates correctly trips_output_table <- trips_output_table %>% mutate( start_x = as.double(start_x), @@ -1907,34 +1907,34 @@ read_output_trips <- function(input_path = ".", n_max = Inf) { #####Plotting##### -#' Plot main_mode distribution as a Pie Chart +#' Plot the distribution of modes in main_modes as a pie chart #' -#' Takes Table trips_output (from \link{readTripsTable}), -#' to plot pie chart with with values that represent -#' percentage of using transport modes from trips +#' Uses the dataframe trips_output (from \link{readTripsTable}), +#' to plot a pie chart of the modal split using the column main_mode #' -#' Function automatically detects transport_modes from table -#' and plots pie chart. -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Function automatically detects transport_modes from table and plots a pie chart. +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' @param trips_table tibble of trips_output (from \link{readTripsTable}) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' -#' @return Pie Chart plot of transport mode distribution, values given in percents +#' @return pie chart plot of transport mode distribution, values given in percent #' #' @export plot_mainmode_piechart <- function(trips_table, - unite.columns = character(0), united.name = "united", + unite.modes = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory) { - # If some columns should be united + # renaming/uniting of modes trips_table = process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) # processing - # tripsTableCount gives percentage representation out + # calculates the mode share and saves it as a tibble trips_table_count<-process_get_mainmode_distribution(trips_table, percentage= percentage) @@ -1949,35 +1949,37 @@ plot_mainmode_piechart <- function(trips_table, } -#' Plot main_mode distribution as a bar Chart +#' Plot the distribution of modes in main_modes as a bar chart #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' percentage of using transport modes from trips +#' Takes the dataframe trips_output (from \link{readTripsTable()}) +#' to plot a bar chart of the modal split using the column main_mode. #' -#' Function automatically detects transport_modes from table -#' and plots pie chart with percentage of distribution. -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' The modal shares are given in percentages. #' +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' -#' @param trips_table tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' +#' @param trips_table tibble of trips_output (from \link{readTripsTable()}) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' #' @return Bar Chart plot of transport mode distribution, values given in percents #' #' @export plot_mainmode_barchart <- function(trips_table, - unite.columns = character(0), + unite.modes = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, percentage = FALSE) { - # If some columns should be united + # renaming/uniting of modes trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) # processing + # calculates the mode share and saves it as a tibble trips_table_count <- process_get_mainmode_distribution(trips_table, percentage = percentage) @@ -1993,30 +1995,31 @@ plot_mainmode_barchart <- function(trips_table, #' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' time spent on traveling/waiting -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes the data frame trips_output (from \links{readTripsTable()}), +#' to plot a bar chart of travel and wait times. +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param trips_table tibble of trips_output (from \links{readTripsTable()}) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' #' @return Bar Chart plot of average time spent on travel/wait #' #' @export plot_travelwaittime_mean_barchart <- function(trips_table, - unite.columns = character(0), + unite.modes = character(0), united.name = "united", time_format = "minute") { - # If some columns should be united + # renaming/uniting of modes trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) - #processing of result table + #processing avg_time = process_get_travelwaittime_by_mainmode(trips_table,time_format = time_format) #plotting @@ -2035,24 +2038,26 @@ plot_travelwaittime_mean_barchart <- function(trips_table, -#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis +#' Bar Chart comparing two runs with main_mode on x-axis and average travel/wait time on y-axis #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' time spent on traveling/waiting -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes two data frames (from \link{readTripsTable()}), +#' to plot a comparison bar chart of travel and wait times. #' +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' -#' @return Bar Chart plot of average time spent on travel/wait +#' @param tripsTable1 tibble of trips_output (from readTripsTable()) +#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode +#' +#' @return Bar chart plot comparing average time spent on travel/wait of two runs #' #' @export plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, - unite.columns = character(0), + unite.modes = character(0), united.name = "united", time_format = "minute") { @@ -2061,13 +2066,13 @@ plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, # . think about comparing processing functions they can appear in future often - # If some columns should be united + # renaming/uniting of modes trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) #processing @@ -2100,30 +2105,31 @@ plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, } -#' Bar Chart with distance travelled on x-axis and number of trips on y-axis +#' Bar Chart with distance traveled on x-axis and number of trips on y-axis #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' number of trips ~ distance travelled -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes the data frame trips_output (from \link{readTripsTable()}) and categorizes the traveled distances into pre-defined bins +#' to plot a histogram of the traveled distances. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param trips_table tibble of trips_output (from readTripsTable()) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' @return Bar Chart plot of count of trips among distance travelled #' #' @export plot_distcat_by_mainmode_barchart <- function(trips_table, - unite.columns = character(0), + unite.modes = character(0), united.name = "united", dist_column = "dist_cat", distances_array = c(1000,2000,5000,10000,20000,50000,100000)) { - # If some columns should be united + # renaming/uniting of modes trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) #processing @@ -2142,27 +2148,28 @@ plot_distcat_by_mainmode_barchart <- function(trips_table, } -#' Bar Chart with distance travelled on x-axis and number of trips on y-axis +#' Bar chart with average distance traveled for each mode on x-axis and number of trips on y-axis #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' average distance traveled ~ main mode used -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes the data frame trips_output (from \link{readTripsTable()}), +#' to plot a bar chart of the average distance traveled for each main mode, +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart#' +#' @param trips_table tibble of trips_output (from readTripsTable()) +#'@param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' @return Bar Chart plot of distance traveled per mode #' #' @export plot_distance_by_mainmode_barchart <- function(trips_table, - unite.columns = character(0), united.name = "united") { + unite.modes = character(0), united.name = "united") { - # If some columns should be united + # renaming/uniting of modes trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) #processing @@ -2186,34 +2193,33 @@ plot_distance_by_mainmode_barchart <- function(trips_table, return(fig) } -#' Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis +#' Bar chart comparing distance traveled on x-axis and number of trips on y-axis for two different runs #' -#' Takes 2 Tables trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes two data frames (from \link{readTripsTable()}), categorizes the traveled distances into pre-defined bins +#' and plots the difference in number of trips for each bin. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 -#' @param tripsTable2 tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' @param tripsTable1 tibble of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 +#' @param tripsTable2 tibble of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' @return Bar Chart plot of count of trips among distance travelled #' #' @export plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, - unite.columns = character(0), united.name = "united", + unite.modes = character(0), united.name = "united", dist_column = "dist_cat", distances_array = c(1000,2000,5000,10000,20000,50000,100000)) { trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) modes = unique(c(unique(trips_table1$main_mode),unique(trips_table2$main_mode))) @@ -2247,28 +2253,29 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, } -#' Line plot with departure time x-axis and number of trips on y-axis +#' Line plot with departure time on x-axis and number of trips on y-axis #' -#' Takes Table trips_output (from readTripsTable()), -#' to make line plot with with values that represent -#' count of trips for a specific departure time by main_mode -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes data frame trips_output (from \link{readTripsTable()}), +#' to create a line plot of the number of trips for a specific departure time by main_mode +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @return Line Chart plot of trips count by departure mode per mode +#' @param tripsTable tibble of trips_output (from readTripsTable()) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode +#' @return Line plot of trips count by departure time per mode #' #' @export plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, - unite.columns = character(0), + unite.modes = character(0), united.name = "united") { - # If some columns should be united + # renaming/uniting of modes trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) @@ -2285,37 +2292,34 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, return(fig) } -#' Plot bar chart diagram of transport mode changes +#' Plot bar chart of changes in modal split #' -#' Takes two trips_table (from readTripsTable), and collects -#' changes between transport mode distribution of these tables -#' to make bar chart diagram with dodging positioning from this data +#' Takes two data frames (from \link{readTripsTable()}), calculates the +#' changes in mode shares and plots them as a bar chart +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' -#' Function calculates number of each transport mode used in -#' first and second table, and draws plot that represent how -#' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) -#' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") -#' Using parameter show.onlyChanges #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name if columns were united, you can specify name for the resulting column in plot #' -#' @return plots Bar Chart of transport mode changes with additional files for simwrapper +#' @param tripsTable1 tibble of trips_output (from readTripsTable()) +#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#'@param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode +#' +#' @return plots bar chart of changes in modal split #' #' @export plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, - unite.columns = character(0), + unite.modes = character(0), united.name = "united") { - # If the unite.columns is specified, then - #print(dump.output.to) + # renaming/uniting of modes trips_table1 <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) trips_table2 <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) trips_table1 = trips_table1 %>% mutate(type = "base") @@ -2333,37 +2337,33 @@ plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, #' Plot alluvial/sankey diagram of transport mode changes #' -#' Takes two trips_table (from readTripsTable), and collects -#' changes between transport mode distribution of these tables -#' to make alluvial diagram from this data -#' -#' Function calculates number of each transport mode used in -#' first and second table, and draws plot that represent how -#' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) -#' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") -#' Using parameter show.onlyChanges +#' Takes two data frames (from \link{readTripsTable()}) and compares the mode choice for each agent and summarizes the results, showing the modal shift. +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' The parameter show.onlyChanges allows the visualization of only the mode shift (excluding the trips that do not change mode). Standard value is FALSE. #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param show.onlyChanges boolean, if it is set to TRUE => sankey diagram only contains changes on axes -#' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name if columns were united, you can specify name for the resulting column in plot +#' @param tripsTable1 tibble of trips_output (from readTripsTable()) +#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#' @param show.onlyChanges boolean, if it is set to TRUE the sankey diagram only shows the mode shift +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' -#' @return Alluvial diagram that represents changes in transport mode distribution of trip tables +#' @return Alluvial diagram that represents changes in transport mode distribution #' #' @export plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, show.onlyChanges = FALSE, - unite.columns = character(0), + unite.modes = character(0), united.name = "united") { - #rename + # renaming/uniting of modes trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) #processing joined <- as_tibble(inner_join(trips_table1, trips_table2 %>% @@ -2427,10 +2427,10 @@ plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, #####Processing##### process_rename_mainmodes<-function(trips_table, - unite.columns = character(0), united.name = "united"){ + unite.modes = character(0), united.name = "united"){ - if (length(unite.columns) != 0) { - trips_table$main_mode[grep(paste0(unite.columns, collapse = "|") + if (length(unite.modes) != 0) { + trips_table$main_mode[grep(paste0(unite.modes, collapse = "|") , trips_table$main_mode)] <- united.name } return(trips_table) From 8beb220d53be5508504eca9664f2964243934b56 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Tue, 6 Jun 2023 09:46:40 +0200 Subject: [PATCH 23/87] added names for functions in matsimr-deprecated --- R/output_trips.R | 15 ++++++++++++-- man/matsimr-deprecated.Rd | 20 +++++++++++++++++++ ...ot_compare_distcat_by_mainmode_barchart.Rd | 8 ++++---- man/readTripsTable.Rd | 20 ------------------- 4 files changed, 37 insertions(+), 26 deletions(-) delete mode 100644 man/readTripsTable.Rd diff --git a/R/output_trips.R b/R/output_trips.R index f2516d4..d704735 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -217,14 +217,15 @@ plotModalSplitBarChart <- function(tripsTable, #' **Deprecated. (see matsimr-deprecated)** Load MATSIM output_trips table into Memory #' -#' Loads a MATSim CSV output_trips from file or archive, +#' **readTripsTable** - Loads a MATSim CSV output_trips from file or archive, #' creating a tibble with columns as in csv file #' +#' @rdname matsimr-deprecated #' @name readTripsTable #' #' @param input_path character string, path to matsim output directory or http link to the file. #' @param n_max integer, maximum number of lines to read within output_trips -#' @return tibble of trips_output +#' @return **readTripsTable** - tibble of trips_output #' #' @export readTripsTable <-function(input_path = ".", n_max = Inf) { @@ -235,8 +236,18 @@ readTripsTable <-function(input_path = ".", n_max = Inf) { #' Deprecated function(s) in the matsimr package #' #' +#' **plotAverageTravelWait** - Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' time spent on traveling/waiting +#' Using parameters unite.columns, specific columns could be given, +#' to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' #' @rdname matsimr-deprecated #' +#' +#' @return **plotAverageTravelWait** - Bar Chart plot of average time spent on travel/wait #' @docType package #' @export plotAverageTravelWait #' @aliases plotAverageTravelWait diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index e785c35..42e29ca 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -5,6 +5,7 @@ \alias{matsimr-deprecated} \alias{plotModalSplitPieChart} \alias{plotModalSplitBarChart} +\alias{readTripsTable} \alias{plotAverageTravelWait} \alias{compareAverageTravelWait} \alias{plotModalDistanceDistribution} @@ -27,6 +28,8 @@ plotModalSplitBarChart( only.files = FALSE ) +readTripsTable(input_path = ".", n_max = Inf) + plotAverageTravelWait( tripsTable, unite.columns = character(0), @@ -64,8 +67,16 @@ appendDistanceCategory(tripsTable) \item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} \item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} + +\item{input_path}{character string, path to matsim output directory or http link to the file.} + +\item{n_max}{integer, maximum number of lines to read within output_trips} } \value{ +**readTripsTable** - tibble of trips_output + +**plotAverageTravelWait** - Bar Chart plot of average time spent on travel/wait + Bar Chart plot of count of trips among distance travelled } \description{ @@ -73,6 +84,15 @@ These functions are provided for compatibility with older version of the matsimr package. They may eventually be completely removed. +**readTripsTable** - Loads a MATSim CSV output_trips from file or archive, +creating a tibble with columns as in csv file + +**plotAverageTravelWait** - Takes Table trips_output (from readTripsTable()), +to plot bar chart with with values that represent +time spent on traveling/waiting +Using parameters unite.columns, specific columns could be given, +to unite them in 1 mode with the name united.name(by default 'united') + Takes Table trips_output (from readTripsTable()), to plot bar chart with with values that represent number of trips ~ distance travelled diff --git a/man/plot_compare_distcat_by_mainmode_barchart.Rd b/man/plot_compare_distcat_by_mainmode_barchart.Rd index 056ed61..09b9d31 100644 --- a/man/plot_compare_distcat_by_mainmode_barchart.Rd +++ b/man/plot_compare_distcat_by_mainmode_barchart.Rd @@ -14,13 +14,13 @@ plot_compare_distcat_by_mainmode_barchart( ) } \arguments{ -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{trips_table1}{tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1} -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +\item{trips_table2}{tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted} -\item{tripsTable1}{tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1} +\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} -\item{tripsTable2}{tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted} +\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} \item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} diff --git a/man/readTripsTable.Rd b/man/readTripsTable.Rd deleted file mode 100644 index 176d197..0000000 --- a/man/readTripsTable.Rd +++ /dev/null @@ -1,20 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{readTripsTable} -\alias{readTripsTable} -\title{**Deprecated. (see matsimr-deprecated)** Load MATSIM output_trips table into Memory} -\usage{ -readTripsTable(input_path = ".", n_max = Inf) -} -\arguments{ -\item{input_path}{character string, path to matsim output directory or http link to the file.} - -\item{n_max}{integer, maximum number of lines to read within output_trips} -} -\value{ -tibble of trips_output -} -\description{ -Loads a MATSim CSV output_trips from file or archive, -creating a tibble with columns as in csv file -} From 29558259c4f702fea4dce7fdcb3d89e6e0180656 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Tue, 6 Jun 2023 09:49:36 +0200 Subject: [PATCH 24/87] added plotmodaldistancedistribution doc --- R/output_trips.R | 4 ++-- man/matsimr-deprecated.Rd | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index d704735..05dbc98 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -341,7 +341,7 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch #' Bar Chart with distance travelled on x-axis and number of trips on y-axis #' -#' Takes Table trips_output (from readTripsTable()), +#' **plotModalDistanceDistribution** - Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' number of trips ~ distance travelled #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') @@ -356,7 +356,7 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' @return Bar Chart plot of count of trips among distance travelled +#' @return **plotModalDistanceDistribution** Bar Chart plot of count of trips among distance travelled #' #' @export plotModalDistanceDistribution <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 42e29ca..b4e7731 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -77,7 +77,7 @@ appendDistanceCategory(tripsTable) **plotAverageTravelWait** - Bar Chart plot of average time spent on travel/wait -Bar Chart plot of count of trips among distance travelled +**plotModalDistanceDistribution** Bar Chart plot of count of trips among distance travelled } \description{ These functions are provided for compatibility with older version of @@ -93,7 +93,7 @@ time spent on traveling/waiting Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -Takes Table trips_output (from readTripsTable()), +**plotModalDistanceDistribution** - Takes Table trips_output (from readTripsTable()), to plot bar chart with with values that represent number of trips ~ distance travelled Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') From a8f203ef0f4440ddadb7706e995e3d913c6139c7 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Tue, 6 Jun 2023 09:52:33 +0200 Subject: [PATCH 25/87] name with bold text --- R/output_trips.R | 12 ++++++------ man/matsimr-deprecated.Rd | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 05dbc98..7147bec 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -217,7 +217,7 @@ plotModalSplitBarChart <- function(tripsTable, #' **Deprecated. (see matsimr-deprecated)** Load MATSIM output_trips table into Memory #' -#' **readTripsTable** - Loads a MATSim CSV output_trips from file or archive, +#' \strong{readTripsTable} - Loads a MATSim CSV output_trips from file or archive, #' creating a tibble with columns as in csv file #' #' @rdname matsimr-deprecated @@ -225,7 +225,7 @@ plotModalSplitBarChart <- function(tripsTable, #' #' @param input_path character string, path to matsim output directory or http link to the file. #' @param n_max integer, maximum number of lines to read within output_trips -#' @return **readTripsTable** - tibble of trips_output +#' @return \strong{readTripsTable} - tibble of trips_output #' #' @export readTripsTable <-function(input_path = ".", n_max = Inf) { @@ -236,7 +236,7 @@ readTripsTable <-function(input_path = ".", n_max = Inf) { #' Deprecated function(s) in the matsimr package #' #' -#' **plotAverageTravelWait** - Takes Table trips_output (from readTripsTable()), +#' \strong{plotAverageTravelWait} - Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' time spent on traveling/waiting #' Using parameters unite.columns, specific columns could be given, @@ -247,7 +247,7 @@ readTripsTable <-function(input_path = ".", n_max = Inf) { #' @rdname matsimr-deprecated #' #' -#' @return **plotAverageTravelWait** - Bar Chart plot of average time spent on travel/wait +#' @return \strong{plotAverageTravelWait} - Bar Chart plot of average time spent on travel/wait #' @docType package #' @export plotAverageTravelWait #' @aliases plotAverageTravelWait @@ -341,7 +341,7 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch #' Bar Chart with distance travelled on x-axis and number of trips on y-axis #' -#' **plotModalDistanceDistribution** - Takes Table trips_output (from readTripsTable()), +#' \strong{plotModalDistanceDistribution} - Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' number of trips ~ distance travelled #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') @@ -356,7 +356,7 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' @return **plotModalDistanceDistribution** Bar Chart plot of count of trips among distance travelled +#' @return \strong{plotModalDistanceDistribution} Bar Chart plot of count of trips among distance travelled #' #' @export plotModalDistanceDistribution <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index b4e7731..080261c 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -73,27 +73,27 @@ appendDistanceCategory(tripsTable) \item{n_max}{integer, maximum number of lines to read within output_trips} } \value{ -**readTripsTable** - tibble of trips_output +\strong{readTripsTable} - tibble of trips_output -**plotAverageTravelWait** - Bar Chart plot of average time spent on travel/wait +\strong{plotAverageTravelWait} - Bar Chart plot of average time spent on travel/wait -**plotModalDistanceDistribution** Bar Chart plot of count of trips among distance travelled +\strong{plotModalDistanceDistribution} Bar Chart plot of count of trips among distance travelled } \description{ These functions are provided for compatibility with older version of the matsimr package. They may eventually be completely removed. -**readTripsTable** - Loads a MATSim CSV output_trips from file or archive, +\strong{readTripsTable} - Loads a MATSim CSV output_trips from file or archive, creating a tibble with columns as in csv file -**plotAverageTravelWait** - Takes Table trips_output (from readTripsTable()), +\strong{plotAverageTravelWait} - Takes Table trips_output (from readTripsTable()), to plot bar chart with with values that represent time spent on traveling/waiting Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -**plotModalDistanceDistribution** - Takes Table trips_output (from readTripsTable()), +\strong{plotModalDistanceDistribution} - Takes Table trips_output (from readTripsTable()), to plot bar chart with with values that represent number of trips ~ distance travelled Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') From 067f2e912d5ccb25ffcb219827de650aaec9e2ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Tue, 6 Jun 2023 11:20:06 +0200 Subject: [PATCH 26/87] WIP documentation --- NAMESPACE | 7 +- R/config.R | 40 ++ R/network.R | 138 ++++- R/output_trips.R | 521 +++++++++++++++--- ...re_travelwaittime_by_mainmode_barchart.Rd} | 6 +- man/plot_distance_by_mainmode_barchart.Rd | 3 +- man/process_filter_by_shape.Rd | 38 ++ man/process_get_crs_from_config.Rd | 19 + man/process_get_od_matrix.Rd | 37 ++ man/read_config.Rd | 20 + man/read_network.Rd | 24 + 11 files changed, 760 insertions(+), 93 deletions(-) create mode 100644 R/config.R rename man/{plot_compare_travelwaittime_by_mainmode.Rd => plot_compare_travelwaittime_by_mainmode_barchart.Rd} (87%) create mode 100644 man/process_filter_by_shape.Rd create mode 100644 man/process_get_crs_from_config.Rd create mode 100644 man/process_get_od_matrix.Rd create mode 100644 man/read_config.Rd create mode 100644 man/read_network.Rd diff --git a/NAMESPACE b/NAMESPACE index 80079ac..9d846bf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -32,7 +32,7 @@ export(plotTripTypesPieChart) export(plot_compare_distcat_by_mainmode_barchart) export(plot_compare_mainmode_barchart) export(plot_compare_mainmode_sankey) -export(plot_compare_travelwaittime_by_mainmode) +export(plot_compare_travelwaittime_by_mainmode_barchart) export(plot_distance_by_mainmode_barchart) export(plot_distcat_by_mainmode_barchart) export(plot_mainmode_barchart) @@ -44,10 +44,15 @@ export(prepareSimwrapperDashboardFromFolder) export(prepareSimwrapperDashboardFromTable) export(processDtvEstimationQuality) export(processLinkStatsDtvDistribution) +export(process_filter_by_shape) +export(process_get_crs_from_config) +export(process_get_od_matrix) export(readCounts) export(readLinkStats) export(readPersonsTable) export(readTripsTable) +export(read_config) +export(read_network) export(read_output_trips) export(symlog_trans) export(transformToSf) diff --git a/R/config.R b/R/config.R new file mode 100644 index 0000000..081a03a --- /dev/null +++ b/R/config.R @@ -0,0 +1,40 @@ +#' Load MATSIM config file into Memory +#' +#' Loads a MATSim xml config from file or archive, +#' creating a list with parameters as in xml file +#' +#' @param input_path character string, path to matsim output directory or http link to the file. +#' @param n_max integer, maximum number of lines to read within output_trips +#' @return tibble of trips_output +#' +#' @export +read_config <- function(input_path = ".", n_max = Inf) { + + result_tibble <- tibble(module = character(), + param = character(), + value = character()) + + config_xml = read_xml(input_path) + + module_nodeset = xml_children(config_xml) + + for(i in 1:length(module_nodeset)){ + module_name = xml_attr(module_nodeset[[i]],"name") + print(module_name) + param_nodeset = xml_children(module_nodeset[[i]]) + for(j in 1:length(param_nodeset)){ + param_name = xml_attr(param_nodeset[[j]],"name") + value_name = xml_attr(param_nodeset[[j]],"value") + #print(param_name,value_name) + temp_tibble = tibble(module = module_name, + param = param_name, + value = value_name + ) + result_tibble = rbind(result_tibble,temp_tibble) + } + + } + + return(result_tibble) + +} diff --git a/R/network.R b/R/network.R index f5dce53..f2313de 100644 --- a/R/network.R +++ b/R/network.R @@ -53,7 +53,7 @@ utils::globalVariables(c("name")) #' @return "nodes" and "links" tibbles in a list object. #' #' @export -loadNetwork <- function(filename) { +read_network <- function(filename) { cat(filename, ": ") network <- read_xml(filename) @@ -171,3 +171,139 @@ loadNetwork <- function(filename) { list("nodes" = nodes, "links" = links, "attributes" = networkAttributes) } + + +#' Load MATSim network into memory +#' +#' Loads a MATSim XML network file, creating a nodes tibble and a links tibble. +#' Any node and link attribute records in the network are stored as +#' additional columns in the respective node and link tibbles. +#' +#' The links table is automatically joined with the nodes table so that +#' node x/y coordinates (and any other node attributes) are available on the +#' links table without additional processing. +#' +#' @param filename File to load. Can be XML or gzipped XML +#' +#' @return "nodes" and "links" tibbles in a list object. +#' +#' @export +loadNetwork <- function(filename) { + .Deprecated("read_network") + cat(filename, ": ") + network <- read_xml(filename) + + cat("Nodes..") + node_elements <- network %>% xml_find_all("./nodes/node") + nodes <- tibble( + id = node_elements %>% xml_attr("id"), + x = node_elements %>% xml_attr("x") %>% parse_double(), + y = node_elements %>% xml_attr("y") %>% parse_double(), + ) + + attributes <- node_elements %>% xml_find_all("./attributes/attribute") + # skip if there are no node attributes + if (length(attributes)) { + attrIds <- tibble(id = unlist(map(attributes, function(row) xml_attr(xml_parent(xml_parent(row)), "id")))) + + nodeAttributes <- tibble( + id = attrIds$id, + name = attributes %>% xml_attr("name"), + class = attributes %>% xml_attr("class"), + value = attributes %>% xml_text(), + ) + + # which columns should be converted to numeric? + types <- nodeAttributes %>% + select(name, class) %>% + distinct() + convert <- filter(types, class == "java.lang.Double")$name + + # convert to a format we can join to the links + nodeAttributes <- (nodeAttributes + %>% select(-class) + %>% pivot_wider(names_from = "name", values_from = "value") + %>% mutate_at(vars(one_of(convert)), as.double) + ) + nodes <- nodes %>% left_join(nodeAttributes, by = "id") + } + + cat("Links..") + link_elements <- network %>% xml_find_all("./links/link") + links <- tibble( + id = link_elements %>% xml_attr("id"), + from = link_elements %>% xml_attr("from"), + to = link_elements %>% xml_attr("to"), + length = link_elements %>% xml_attr("length") %>% parse_double(), + freespeed = link_elements %>% xml_attr("freespeed") %>% parse_double(), + capacity = link_elements %>% xml_attr("capacity") %>% parse_double(), + permlanes = link_elements %>% xml_attr("permlanes") %>% parse_double(), + modes = link_elements %>% xml_attr("modes"), + origid = link_elements %>% xml_attr("origid") + ) + + # merge node coordinates + links <- (links + %>% left_join(nodes, by = c("from" = "id")) + %>% left_join(nodes, by = c("to" = "id"), suffix = c(".from", ".to")) + ) + + # attributes don't have IDs on them! JFC, MATSim! + cat("Attributes..") + + attributes <- link_elements %>% xml_find_all("./attributes/attribute") + # skip if there are no link-attributes + if (length(attributes)) { + attrIds <- tibble(id = unlist(map(attributes, function(row) xml_attr(xml_parent(xml_parent(row)), "id")))) + + linkAttributes <- tibble( + id = attrIds$id, + name = attributes %>% xml_attr("name"), + class = attributes %>% xml_attr("class"), + value = attributes %>% xml_text(), + ) + + # which columns should be converted to numeric? + types <- linkAttributes %>% + select(name, class) %>% + distinct() + convert <- filter(types, class == "java.lang.Double")$name + + # convert to a format we can join to the links + linkAttributes <- (linkAttributes + %>% select(-class) + %>% pivot_wider(names_from = "name", values_from = "value") + %>% mutate_at(vars(one_of(convert)), as.double) + ) + + links <- links %>% left_join(linkAttributes, by = "id", suffix = c(".link", ".attr")) + } + + # Top-level network attributes + networkAttributes <- NULL + + allNetworkAttributes <- network %>% xml_find_all("./attributes/attribute") + if (length(allNetworkAttributes)) { + networkAttributes <- tibble( + name = allNetworkAttributes %>% xml_attr("name"), + class = allNetworkAttributes %>% xml_attr("class"), + value = allNetworkAttributes %>% xml_text(), + ) + # which columns should be converted to numeric? + types <- networkAttributes %>% + select(name, class) %>% + distinct() + convert <- filter(types, class == "java.lang.Double")$name + + # convert to a format we can join to the links + networkAttributes <- (networkAttributes + %>% select(-class) + %>% pivot_wider(names_from = "name", values_from = "value") + %>% mutate_at(vars(one_of(convert)), as.double) + ) + } + + cat("Done!\n") + + list("nodes" = nodes, "links" = links, "attributes" = networkAttributes) +} diff --git a/R/output_trips.R b/R/output_trips.R index ca01bac..d7f6141 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -245,6 +245,7 @@ readTripsTable <-function(input_path = ".", n_max = Inf) { plotAverageTravelWait <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { + .Deprecated("plot_travelwaittime_mean_barchart") # If some columns should be united if (length(unite.columns) != 0) { tripsTable$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable$main_mode)] <- united.name @@ -282,6 +283,7 @@ plotAverageTravelWait <- function(tripsTable, unite.columns = character(0), unit compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { + .Deprecated("plot_compare_travelwaittime_by_mainmode_barchart") # If some columns should be united if (length(unite.columns) != 0) { tripsTable1$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable1$main_mode)] <- united.name @@ -350,6 +352,7 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch plotModalDistanceDistribution <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { + .Deprecated("plot_distcat_by_mainmode_barchart") # If some columns should be united if (length(unite.columns) != 0) { @@ -440,6 +443,9 @@ plotModalDistanceDistribution <- function(tripsTable, unite.columns = character( #' @export compareModalDistanceDistribution <- function(tripsTable1,tripsTable2, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { + + .Deprecated("plot_compare_distcat_by_mainmode_barchart") + if (length(unite.columns) != 0) { tripsTable1$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable1$main_mode)] <- united.name tripsTable2$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable2$main_mode)] <- united.name @@ -516,6 +522,7 @@ plotTripDistanceByMode <- function(tripsTable, dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { + .Deprecated("plot_distance_by_mainmode_barchart") # If some columns should be united if (length(unite.columns) != 0) { @@ -567,6 +574,7 @@ plotTripDistanceByMode <- function(tripsTable, plotTripCountByDepTime <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { + .Deprecated("plot_trips_count_by_deptime_and_mainmode_linechart") # If some columns should be united if (length(unite.columns) != 0) { @@ -952,6 +960,8 @@ plotTripDistancedByType <- function(tripsTable,shapeTable,crs,dump.output.to = m #' #' @export plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FALSE, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory) { + + .Deprecated("plot_compare_mainmode_sankey") StatStratum <- ggalluvial::StatStratum joined <- as_tibble(inner_join(tripsTable1, tripsTable2 %>% select(trip_id, main_mode), by = "trip_id") %>% @@ -1019,6 +1029,8 @@ plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FA #' @export plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, output.name = "modalShiftBarChart") { + + .Deprecated("plot_compare_mainmode_barchart") # If the unite.columns is specified, then #print(dump.output.to) if (length(unite.columns) != 0) { @@ -1075,6 +1087,7 @@ plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRU ggplot() + geom_sf(data = shapeTable) warning("there is no trip filtered for this map") + return(NaN) } filtered_sf <- transformToSf(filtered, crs = crs, geometry.type = st_point()) st_geometry(filtered_sf) <- "start_wkt" @@ -1753,6 +1766,7 @@ compareBasePolicyOutput <- function(baseFolder,policyFolder,dump.output.to = mat #' @export compareBasePolicyShapeOutput <- function(baseFolder,policyFolder,shapeFilePath,crs,dump.output.to = matsimDumpOutputDirectory) { + base_trips = list(NULL) policy_trips = list(NULL) shape = st_read(shapeFilePath) @@ -1814,6 +1828,7 @@ compareBasePolicyShapeOutput <- function(baseFolder,policyFolder,shapeFilePath,c #' appendDistanceCategory <- function(tripsTable){ + .Deprecated("process_append_distcat") modes = levels(factor(tripsTable$main_mode)) #This is a very bad way to do that, but I see no other way to get it done @@ -1844,6 +1859,258 @@ appendDistanceCategory <- function(tripsTable){ return(tripsTable_result) } +#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape +#' +#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +#' and filters the trips from table depending on *.inshape flags: +#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape +#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +#' +#' @param tripsTable tibble of trips_output (from readTripsTable()) +#' +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @param start.inshape bool, defines trips to conclude (see Description) +#' +#' @param end.inshape bool, defines trips to conclude (see Description) +#' +#' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) +#' +#' @export +filterByRegion <- function(tripsTable, + shapeTable, + crs, + start.inshape = TRUE, end.inshape = TRUE) { + .Deprecated("process_filter_by_shape") + # shapeTable <- st_read(shapeFile) + if (st_crs(shapeTable) == NA) { + st_crs(shapeTable) <- crs + } + + sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) + shapeTable <- st_transform(shapeTable, crs = crs) + # shapeTable isn't table - shape + + union_shape <- st_union(shapeTable) # transforms the crs back to the previous in the file + union_shape <- st_transform(union_shape, crs = st_crs(shapeTable)) + + + st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry + cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile + + st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry + cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile + + # get trips that ended outside of shape + cont_end_outside <- setdiff(1:nrow(sf_table), cont2) + + # get trips that started outside of shape + cont_start_outside <- setdiff(1:nrow(sf_table), cont1) + + if (start.inshape == TRUE && end.inshape == TRUE) { + cont_union <- intersect(cont1, cont2) + } else if (start.inshape == TRUE && end.inshape == FALSE) { + cont_union <- intersect(cont1, cont_end_outside) + } else if (start.inshape == FALSE && end.inshape == TRUE) { + cont_union <- intersect(cont2, cont_start_outside) + } else { + cont_union <- intersect(cont_start_outside, cont_end_outside) # Give back trips that are neither starting and ending outside the area + } + + + return(tripsTable[cont_union, ]) +} + + +#' Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper +#' +#' +#' +#' @param tripsTable table of output trips(from readTripsTable) or path to trips_output file +#' +#' @param shapePath full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @param dump.output.to path to a folder to save csv file of ODMatrix +#' +#' @param colnames if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values +#' +#' @param simwrapper create output in a simwrapper form if set to path of the shapefile +#' +#' @param outer logical that represent if the table should contain outside flow of the shape, it isn't +#' +#' @return tibble of origin/destination matrix +#' +#' @export +deriveODMatrix<- function(tripsTable, + shapePath, + crs, + dump.output.to = matsimDumpOutputDirectory, + simwrapper = FALSE, + colnames = "numeric", + outer = FALSE){ + .Deprecated("process_get_OD_matrix") + defaultW <- getOption("warn") + options(warn = -1) + + #if tripstable given as folder/file + if(sum(class(tripsTable) %in% c("tbl_df","tbl","data.frame"))<1){ + tripsTable <- readTripsTable(tripsTable) + } + + sfTable <- transformToSf(tripsTable,crs,geometry.type = st_point()) + + shape = st_read(shapePath) + + if (st_crs(shape) == NA) { + st_crs(shape) <- crs + } + shape = st_transform(shape,crs = crs) + + sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) + + sf_start = sfTable %>% select(trip_id,start_wkt) + st_geometry(sfTable) = "end_wkt" + sf_end = sfTable %>% select(trip_id,end_wkt) + + #Get all inner intersects + sf_intersect_start = st_contains(shape,sf_start) + sf_intersect_end = st_contains(shape,sf_end) + + + if(outer == TRUE){ + #Get all outer intersects + joined_shape = st_union(shape) + + start_inside = st_contains(joined_shape,sf_start) + end_inside = st_contains(joined_shape,sf_end) + + start_outside = 1:nrow(sf_start) + end_outside = 1:nrow(sf_end) + + start_outside = start_outside[! start_outside %in% start_inside[[1]]] + + end_outside = end_outside[! end_outside %in% end_inside[[1]]] + + sf_intersect_start = append(sf_intersect_start,list(start_outside)) + sf_intersect_end = append(sf_intersect_end,list(end_outside)) + } + + # Create matrix out of it + result_tibble = as_tibble(data.frame(matrix(nrow=0,ncol=nrow(shape)))) + colnames(result_tibble) = 1:nrow(shape) + + for(i in 1:length(sf_intersect_start)){ + temp = c() + for(j in 1:length(sf_intersect_start)){ + start_i = sf_intersect_start[[i]] + end_j = sf_intersect_end[[j]] + + number_of_trips = length(intersect(start_i,end_j)) + + temp = append(temp,number_of_trips) + + } + result_tibble = rbind(result_tibble,temp) + } + + if(colnames!="numeric" & colnames %in% colnames(shape)){ + colnames(result_tibble) = shape[[colnames]] + if(outer == TRUE){ + rownames(result_tibble) = c(shape[[colnames]],"outer") + colnames(result_tibble)[length(colnames(result_tibble))] = "outer" + }else{ + rownames(result_tibble) = shape[[colnames]] + } + + }else{ + colnames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) + rownames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) + } + + + result_melt = melt(as.matrix(result_tibble)) + colnames(result_melt) = c("origin","destination",1) + # Generating yaml and output_files + + + + if (file.exists(dump.output.to) & simwrapper == TRUE) { + write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") + } else if(!file.exists(dump.output.to) & simwrapper == TRUE) { + dir.create(dump.output.to) + write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") + } else if (file.exists(dump.output.to) & simwrapper == FALSE) { + write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) + } else { + dir.create(dump.output.to) + write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) + } + + yaml_list <- list( + title = "OD Flow", + description = "generated by deriveODMatrix", + projection = st_crs(shape)$input, + shpFile = paste0("../",shapePath), + dbfFile = paste0("../",substr(shapePath,start = 1,stop = nchar(shapePath)-3),"dbf"), + scaleFactor = 1, + lineWidth = 50, + csvFile = "ODMatrix.csv", + idColumn = colnames(shape)[1] # at the moment idColumn of shapefile should be the first column + + ) + write_yaml(yaml_list, paste0(dump.output.to, "/viz-od-flow.yaml")) + + options(warn = defaultW) + return(result_tibble) +} + + +#' Reads an coordinate referenec system of MATSim output directory +#' from output_config.xml +#' +#' @param folder specifies path to find config +#' +#' +#' @return code of coordinate reference system +#' +#' @export +getCrsFromConfig <- function(folder) { + + if (grepl("output_config.xml$", folder) == TRUE) + { + config <- read_xml(folder) + + param_nodes = xml_find_all(config,"//param") + + coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] + + coord_system = xml_attr(coord_node,"value") + return(coord_system) + } + + files <- list.files(folder, full.names = TRUE) + # Read from global/local directory + # output_config.xml is contained as output_trips.csv.gz + if (length(grep("output_config.xml$", files)) != 0) { + config <- read_xml(files[grep("output_config.xml$", files)]) + + param_nodes = xml_find_all(config,"//param") + + coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] + + coord_system = xml_attr(coord_node,"value") + return(coord_system) + } + return(NA) +} #####Reading##### @@ -2038,11 +2305,11 @@ plot_travelwaittime_mean_barchart <- function(trips_table, + #' Bar Chart comparing two runs with main_mode on x-axis and average travel/wait time on y-axis #' #' Takes two data frames (from \link{readTripsTable()}), #' to plot a comparison bar chart of travel and wait times. -#' #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' @@ -2164,7 +2431,8 @@ plot_distcat_by_mainmode_barchart <- function(trips_table, #' #' @export plot_distance_by_mainmode_barchart <- function(trips_table, - unite.modes = character(0), united.name = "united") { + unite.columns = character(0), united.name = "united", + euclidean = FALSE) { # renaming/uniting of modes @@ -2173,7 +2441,7 @@ plot_distance_by_mainmode_barchart <- function(trips_table, united.name = united.name) #processing - trips_table <- process_get_travdistance_distribution(trips_table = trips_table) + trips_table <- process_get_travdistance_distribution(trips_table = trips_table,euclidean = euclidean) #if(only.process){ @@ -2186,20 +2454,22 @@ plot_distance_by_mainmode_barchart <- function(trips_table, type = 'bar', text = text_for_y, textposition = "auto", - name = "AVG Distance traveled by a person over a day") + name = paste0("AVG " ,if_else(euclidean,"eucliden ","traveled ") ,"distance by mode over a day")) fig <- fig %>% layout(yaxis = list(title = "Distance (in meters)"),barmode = "group") fig return(fig) } + #' Bar chart comparing distance traveled on x-axis and number of trips on y-axis for two different runs -#' + #' Takes two data frames (from \link{readTripsTable()}), categorizes the traveled distances into pre-defined bins #' and plots the difference in number of trips for each bin. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' + #' @param tripsTable1 tibble of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 #' @param tripsTable2 tibble of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted #' @param unite.modes vector of character strings, @@ -2228,7 +2498,8 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, distribution2 <- process_append_distcat(trips_table2,distances_array = distances_array) - #Get category count difference??? + #Get category count difference + table_with_сounts1 = distribution1 %>% count(main_mode,dist_cat) table_with_сounts2 = distribution2 %>% count(main_mode,dist_cat) @@ -2253,6 +2524,7 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, } +<<<<<<< HEAD #' Line plot with departure time on x-axis and number of trips on y-axis #' #' Takes data frame trips_output (from \link{readTripsTable()}), @@ -2283,14 +2555,9 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, tripsTable = tripsTable %>% mutate(dep_time = hour(dep_time)) %>% count(dep_time,main_mode) +======= +>>>>>>> b4c50a65dbd3a28e5601aacf36d1d3cc02fea649 - #plotting - fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) - fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") - - fig - return(fig) -} #' Plot bar chart of changes in modal split #' @@ -2387,7 +2654,7 @@ plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, #plotting - mypal <- colorRampPalette( c( "blue", "red" ) )( 7 ) + palette <- colorRampPalette( c( "blue", "red" ) )( 7 ) fig <- plot_ly( @@ -2396,7 +2663,7 @@ plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, node = list( label = c(modes,modes), - color = c(mypal,mypal), + color = c(palette,palette), pad = 15, thickness = 20, line = list( @@ -2422,8 +2689,73 @@ plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, return(fig) } +#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis +#' +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' time spent on traveling/waiting +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' @param tripsTable1 tible of trips_output (from readTripsTable()) +#' @param tripsTable2 tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' +#' @return Bar Chart plot of average time spent on travel/wait +#' +#' @export +plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_table2, + unite.columns = character(0), + united.name = "united", + time_format = "minute") { + + #TODO: + # . Document and add title to show what means positive/negative value + # . think about comparing processing functions they can appear in future often + + + # If some columns should be united + trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, + unite.columns = unite.columns, + united.name = united.name) + + trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, + unite.columns = unite.columns, + united.name = united.name) + + #processing + avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) + + + + avg_time2 = process_get_travelwaittime_by_mainmode(trips_table2,time_format = time_format) + + + avg_time = full_join(avg_time1, avg_time2, by = "main_mode") %>% + replace_na(list(trav_time_avg.x = 0,wait_time_avg.x = 0,trav_time_avg.y = 0,wait_time_avg.y = 0)) + + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg.x - trav_time_avg.y, + wait_time_avg =wait_time_avg.x - wait_time_avg.y )%>% + select(-wait_time_avg.x,-wait_time_avg.y, -trav_time_avg.x,-trav_time_avg.y) + + + + #plotting + fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") + fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") + fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)")),barmode = "group") + + + fig + return(fig) + +} + +###### Mapping ###### + #####Processing##### process_rename_mainmodes<-function(trips_table, @@ -2447,16 +2779,16 @@ process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ return(trips_table_count) } -process_get_travdistance_distribution<-function(trips_table){ +process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ trips_table = trips_table %>% group_by(main_mode) %>% - summarize(avg_dist = mean(traveled_distance)) + summarize(avg_dist = if_else(euclidian,mean(euclidean_distance),mean(traveled_distance))) return(trips_table) } -process_get_travelwaittime_by_mainmode<-function(trips_table, +process_get_travelwaittime_by_mainmode_barchart<-function(trips_table, time_format = "minute"){#also could be hours/seconds #get 2 columns with mean travel time and mean wait time grouped by main_mode in seconds @@ -2502,18 +2834,87 @@ process_append_distcat <- function(trips_table,distances_array = c(1000,2000,500 return(result_table) } +######Spatial###### +#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape +#' +#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +#' and filters the trips from table depending on *.inshape flags: +#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape +#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +#' +#' @param trips_table tibble of trips_output (from readTripsTable()) +#' +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @param start.inshape bool, defines trips to conclude (see Description) +#' +#' @param end.inshape bool, defines trips to conclude (see Description) +#' +#' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) +#' +#' @export +process_filter_by_shape <- function(trips_table, + shape_table, + crs, + start.inshape = TRUE, end.inshape = TRUE) { + + # shape_table <- st_read(shapeFile) + if (st_crs(shape_table) == NA) { + st_crs(shape_table) <- crs + } + + sf_table <- transformToSf(trips_table, crs = crs, geometry.type = st_point()) + shape_table <- st_transform(shape_table, crs = crs) + # shape_table isn't table - shape + + union_shape <- st_union(shape_table) # transforms the crs back to the previous in the file + union_shape <- st_transform(union_shape, crs = st_crs(shape_table)) + + + st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry + cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile + + st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry + cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile + + # get trips that ended outside of shape + cont_end_outside <- setdiff(1:nrow(sf_table), cont2) + + # get trips that started outside of shape + cont_start_outside <- setdiff(1:nrow(sf_table), cont1) + + if (start.inshape == TRUE && end.inshape == TRUE) { + cont_union <- intersect(cont1, cont2) + } else if (start.inshape == TRUE && end.inshape == FALSE) { + cont_union <- intersect(cont1, cont_end_outside) + } else if (start.inshape == FALSE && end.inshape == TRUE) { + cont_union <- intersect(cont2, cont_start_outside) + } else { + cont_union <- intersect(cont_start_outside, cont_end_outside) # Give back trips that are neither starting and ending outside the area + } + + + return(trips_table[cont_union, ]) +} + #' Reads an coordinate referenec system of MATSim output directory #' from output_config.xml #' -#' @param folder specifies path to find config +#' @param config_path specifies path to find config #' #' #' @return code of coordinate reference system #' #' @export -getCrsFromConfig <- function(folder) { +process_get_crs_from_config <- function(config_path) { - if (grepl("output_config.xml$", folder) == TRUE) + if (grepl("output_config.xml$", config_path) == TRUE) { config <- read_xml(folder) @@ -2525,7 +2926,7 @@ getCrsFromConfig <- function(folder) { return(coord_system) } - files <- list.files(folder, full.names = TRUE) + files <- list.files(config_path, full.names = TRUE) # Read from global/local directory # output_config.xml is contained as output_trips.csv.gz if (length(grep("output_config.xml$", files)) != 0) { @@ -2562,7 +2963,14 @@ getCrsFromConfig <- function(folder) { #' @return tibble of origin/destination matrix #' #' @export -deriveODMatrix<- function(tripsTable,shapePath,crs,dump.output.to = matsimDumpOutputDirectory,simwrapper = FALSE,colnames = "numeric",outer = FALSE){ +process_get_od_matrix<- function(tripsTable, + shapePath, + crs, + dump.output.to = matsimDumpOutputDirectory, + simwrapper = FALSE, + colnames = "numeric", + outer = FALSE){ + defaultW <- getOption("warn") options(warn = -1) @@ -2678,70 +3086,7 @@ deriveODMatrix<- function(tripsTable,shapePath,crs,dump.output.to = matsimDumpOu return(result_tibble) } -#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape -#' -#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) -#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -#' and filters the trips from table depending on *.inshape flags: -#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape -#' -#' @param tripsTable tibble of trips_output (from readTripsTable()) -#' -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) -#' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation -#' -#' @param start.inshape bool, defines trips to conclude (see Description) -#' -#' @param end.inshape bool, defines trips to conclude (see Description) -#' -#' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) -#' -#' @export -filterByRegion <- function(tripsTable, shapeTable, crs, start.inshape = TRUE, end.inshape = TRUE) { - - # shapeTable <- st_read(shapeFile) - if (st_crs(shapeTable) == NA) { - st_crs(shapeTable) <- crs - } - - sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) - shapeTable <- st_transform(shapeTable, crs = crs) - # shapeTable isn't table - shape - union_shape <- st_union(shapeTable) # transforms the crs back to the previous in the file - union_shape <- st_transform(union_shape, crs = st_crs(shapeTable)) - - - st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry - cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile - - st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry - cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile - - # get trips that ended outside of shape - cont_end_outside <- setdiff(1:nrow(sf_table), cont2) - - # get trips that started outside of shape - cont_start_outside <- setdiff(1:nrow(sf_table), cont1) - - if (start.inshape == TRUE && end.inshape == TRUE) { - cont_union <- intersect(cont1, cont2) - } else if (start.inshape == TRUE && end.inshape == FALSE) { - cont_union <- intersect(cont1, cont_end_outside) - } else if (start.inshape == FALSE && end.inshape == TRUE) { - cont_union <- intersect(cont2, cont_start_outside) - } else { - cont_union <- intersect(cont_start_outside, cont_end_outside) # Give back trips that are neither starting and ending outside the area - } - - - return(tripsTable[cont_union, ]) -} #' Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature) #' @@ -2767,7 +3112,9 @@ filterByRegion <- function(tripsTable, shapeTable, crs, start.inshape = TRUE, en #' @return sf object (data.frame with geometries depending to geometry.type) #' #' @export -transformToSf <- function(table, crs, geometry.type = st_multipoint()) { +transformToSf <- function(table, + crs, + geometry.type = st_multipoint()) { if (class(geometry.type)[2] == "POINT") { table1 <- table %>% # mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep ="")) diff --git a/man/plot_compare_travelwaittime_by_mainmode.Rd b/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd similarity index 87% rename from man/plot_compare_travelwaittime_by_mainmode.Rd rename to man/plot_compare_travelwaittime_by_mainmode_barchart.Rd index 546c8d1..351f164 100644 --- a/man/plot_compare_travelwaittime_by_mainmode.Rd +++ b/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/output_trips.R -\name{plot_compare_travelwaittime_by_mainmode} -\alias{plot_compare_travelwaittime_by_mainmode} +\name{plot_compare_travelwaittime_by_mainmode_barchart} +\alias{plot_compare_travelwaittime_by_mainmode_barchart} \title{Bar Chart with main_mode on x-axis and average travel/wait time on y-axis} \usage{ -plot_compare_travelwaittime_by_mainmode( +plot_compare_travelwaittime_by_mainmode_barchart( trips_table1, trips_table2, unite.columns = character(0), diff --git a/man/plot_distance_by_mainmode_barchart.Rd b/man/plot_distance_by_mainmode_barchart.Rd index adbb2df..dc264f5 100644 --- a/man/plot_distance_by_mainmode_barchart.Rd +++ b/man/plot_distance_by_mainmode_barchart.Rd @@ -7,7 +7,8 @@ plot_distance_by_mainmode_barchart( trips_table, unite.columns = character(0), - united.name = "united" + united.name = "united", + euclidean = FALSE ) } \arguments{ diff --git a/man/process_filter_by_shape.Rd b/man/process_filter_by_shape.Rd new file mode 100644 index 0000000..9f3a93f --- /dev/null +++ b/man/process_filter_by_shape.Rd @@ -0,0 +1,38 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_filter_by_shape} +\alias{process_filter_by_shape} +\title{Filtering of trips_table(from readTripsTable) depending on how they located in given shape} +\usage{ +process_filter_by_shape( + trips_table, + shape_table, + crs, + start.inshape = TRUE, + end.inshape = TRUE +) +} +\arguments{ +\item{trips_table}{tibble of trips_output (from readTripsTable())} + +\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} + +\item{start.inshape}{bool, defines trips to conclude (see Description)} + +\item{end.inshape}{bool, defines trips to conclude (see Description)} + +\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +} +\value{ +tibble, with filtered trips depending on shapeTable and special flags (see Description) +} +\description{ +Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +and filters the trips from table depending on *.inshape flags: +if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape +if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +} diff --git a/man/process_get_crs_from_config.Rd b/man/process_get_crs_from_config.Rd new file mode 100644 index 0000000..10cdb61 --- /dev/null +++ b/man/process_get_crs_from_config.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_get_crs_from_config} +\alias{process_get_crs_from_config} +\title{Reads an coordinate referenec system of MATSim output directory +from output_config.xml} +\usage{ +process_get_crs_from_config(config_path) +} +\arguments{ +\item{config_path}{specifies path to find config} +} +\value{ +code of coordinate reference system +} +\description{ +Reads an coordinate referenec system of MATSim output directory +from output_config.xml +} diff --git a/man/process_get_od_matrix.Rd b/man/process_get_od_matrix.Rd new file mode 100644 index 0000000..988818a --- /dev/null +++ b/man/process_get_od_matrix.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_get_od_matrix} +\alias{process_get_od_matrix} +\title{Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper} +\usage{ +process_get_od_matrix( + tripsTable, + shapePath, + crs, + dump.output.to = matsimDumpOutputDirectory, + simwrapper = FALSE, + colnames = "numeric", + outer = FALSE +) +} +\arguments{ +\item{tripsTable}{table of output trips(from readTripsTable) or path to trips_output file} + +\item{shapePath}{full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name)} + +\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} + +\item{dump.output.to}{path to a folder to save csv file of ODMatrix} + +\item{simwrapper}{create output in a simwrapper form if set to path of the shapefile} + +\item{colnames}{if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values} + +\item{outer}{logical that represent if the table should contain outside flow of the shape, it isn't} +} +\value{ +tibble of origin/destination matrix +} +\description{ +Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper +} diff --git a/man/read_config.Rd b/man/read_config.Rd new file mode 100644 index 0000000..fce5fbb --- /dev/null +++ b/man/read_config.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/config.R +\name{read_config} +\alias{read_config} +\title{Load MATSIM config file into Memory} +\usage{ +read_config(input_path = ".", n_max = Inf) +} +\arguments{ +\item{input_path}{character string, path to matsim output directory or http link to the file.} + +\item{n_max}{integer, maximum number of lines to read within output_trips} +} +\value{ +tibble of trips_output +} +\description{ +Loads a MATSim xml config from file or archive, +creating a list with parameters as in xml file +} diff --git a/man/read_network.Rd b/man/read_network.Rd new file mode 100644 index 0000000..2602e44 --- /dev/null +++ b/man/read_network.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/network.R +\name{read_network} +\alias{read_network} +\title{Load MATSim network into memory} +\usage{ +read_network(filename) +} +\arguments{ +\item{filename}{File to load. Can be XML or gzipped XML} +} +\value{ +"nodes" and "links" tibbles in a list object. +} +\description{ +Loads a MATSim XML network file, creating a nodes tibble and a links tibble. +Any node and link attribute records in the network are stored as +additional columns in the respective node and link tibbles. +} +\details{ +The links table is automatically joined with the nodes table so that +node x/y coordinates (and any other node attributes) are available on the +links table without additional processing. +} From af642b7b8fd424ca30351d8788bf3d52bd4dc1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Fri, 9 Jun 2023 16:21:44 +0200 Subject: [PATCH 27/87] WIP updating documentation --- R/output_trips.R | 116 +++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 60 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index d7f6141..2bb058d 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -218,12 +218,12 @@ plotModalSplitBarChart <- function(tripsTable, #' **Deprecated. (see matsimr-deprecated)** Load MATSIM output_trips table into Memory #' -#' Loads a MATSim CSV output_trips from file or archive, -#' creating a tibble with columns as in csv file +#' Loads a MATSim output_trips file from file or archive path, +#' creating a tibble #' #' @name readTripsTable #' -#' @param input_path character string, path to matsim output directory or http link to the file. +#' @param input_path character string, path to MATSim output directory or http link to the file. #' @param n_max integer, maximum number of lines to read within output_trips #' @return tibble of trips_output #' @@ -2073,7 +2073,7 @@ deriveODMatrix<- function(tripsTable, } -#' Reads an coordinate referenec system of MATSim output directory +#' Reads an coordinate reference system of MATSim output directory #' from output_config.xml #' #' @param folder specifies path to find config @@ -2115,12 +2115,12 @@ getCrsFromConfig <- function(folder) { #####Reading##### -#' Load MATSIM output_trips table into Memory +#' Load MATSIM output_trips table into memory #' #' Loads a MATSim CSV output_trips from file or archive, #' creating a tibble with columns as in csv file #' -#' @param input_path character string, path to matsim output directory or http link to the file. +#' @param input_path character string, path to the MATSim output directory or http link to the file. #' @param n_max optional, integer, maximum number of lines to read, standard value is Inf #' @return tibble of trips_output #' @@ -2174,12 +2174,12 @@ read_output_trips <- function(input_path = ".", n_max = Inf) { #####Plotting##### -#' Plot the distribution of modes in main_modes as a pie chart +#' Plot the distribution of modes as a pie chart #' #' Uses the dataframe trips_output (from \link{readTripsTable}), #' to plot a pie chart of the modal split using the column main_mode #' -#' Function automatically detects transport_modes from table and plots a pie chart. +#' The function automatically detects the modes plots a pie chart. #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' @param trips_table tibble of trips_output (from \link{readTripsTable}) @@ -2216,9 +2216,9 @@ plot_mainmode_piechart <- function(trips_table, } -#' Plot the distribution of modes in main_modes as a bar chart +#' Plot the distribution of modes as a bar chart #' -#' Takes the dataframe trips_output (from \link{readTripsTable()}) +#' Takes the data frame trips_output (from \link{readTripsTable()}) #' to plot a bar chart of the modal split using the column main_mode. #' #' The modal shares are given in percentages. @@ -2260,7 +2260,7 @@ plot_mainmode_barchart <- function(trips_table, return(fig) } -#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis +#' Plot travel and wait time for each mode as a bar chart #' #' Takes the data frame trips_output (from \links{readTripsTable()}), #' to plot a bar chart of travel and wait times. @@ -2524,7 +2524,6 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, } -<<<<<<< HEAD #' Line plot with departure time on x-axis and number of trips on y-axis #' #' Takes data frame trips_output (from \link{readTripsTable()}), @@ -2555,8 +2554,7 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, tripsTable = tripsTable %>% mutate(dep_time = hour(dep_time)) %>% count(dep_time,main_mode) -======= ->>>>>>> b4c50a65dbd3a28e5601aacf36d1d3cc02fea649 + #' Plot bar chart of changes in modal split @@ -2691,22 +2689,23 @@ plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, #' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' time spent on traveling/waiting -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes the data frame trips_output (from \link{readTripsTable()}), +#' to plot a bar chart of the traveling/waiting time +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param tripsTable1 tibble of trips_output (from readTripsTable()) +#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' #' @return Bar Chart plot of average time spent on travel/wait #' #' @export plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_table2, - unite.columns = character(0), + unite.modes = character(0), united.name = "united", time_format = "minute") { @@ -2717,11 +2716,11 @@ plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_ # If some columns should be united trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) #processing @@ -2835,12 +2834,13 @@ process_append_distcat <- function(trips_table,distances_array = c(1000,2000,500 } ######Spatial###### -#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape +#' XXXX trips_table but shapeTable - fix naming +#' XXXX finish when code revision is done +#' Filters trips_table(from ,\link{readTripsTable}) depending by location using a shapefile #' -#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) -#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -#' and filters the trips from table depending on *.inshape flags: +#' Uses trips_table and an sf object (can be created using the function st_read()), +#' transforms both objects to match a mutual coordinate system (crs) +#' and filters the trips from trips_table depending on *.inshape flags: #' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape #' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape #' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape @@ -2850,7 +2850,7 @@ process_append_distcat <- function(trips_table,distances_array = c(1000,2000,500 #' #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file #' #' @param start.inshape bool, defines trips to conclude (see Description) #' @@ -2903,10 +2903,10 @@ process_filter_by_shape <- function(trips_table, return(trips_table[cont_union, ]) } -#' Reads an coordinate referenec system of MATSim output directory -#' from output_config.xml +#' Reads the coordinate reference system from an MATSim output directory +#' (output_config.xml) #' -#' @param config_path specifies path to find config +#' @param config_path specifies path to configuration file #' #' #' @return code of coordinate reference system @@ -2942,23 +2942,23 @@ process_get_crs_from_config <- function(config_path) { return(NA) } -#' Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper -#' +#' Creates an origin/destination matrix either in conventional form (row names = origin, column names = destination) +#' or for simwrapper (origin and destination as columns) #' #' -#' @param tripsTable table of output trips(from readTripsTable) or path to trips_output file +#' @param tripsTable tibble of trips_output (from \link{readTripsTable}) #' -#' @param shapePath full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name) +#' @param shapePath string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file) #' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file #' -#' @param dump.output.to path to a folder to save csv file of ODMatrix +#' @param dump.output.to string, path to a folder to save the .csv file #' -#' @param colnames if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values +#' @param colnames string, column names can be specified (i.e. to fit the shape file), if not they are numbered #' -#' @param simwrapper create output in a simwrapper form if set to path of the shapefile +#' @param simwrapper boolean, creates output in the format used for simwrapper if the path for the shapefile is specified #' -#' @param outer logical that represent if the table should contain outside flow of the shape, it isn't +#' @param outer boolean, determines if flows outside of the shapefile are used, standard value is FALSE #' #' @return tibble of origin/destination matrix #' @@ -3088,28 +3088,24 @@ process_get_od_matrix<- function(tripsTable, -#' Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature) +#' Transforms the data frame trips_output (from \links{readTripsTable}) from tibble to sf (table with geometry features) #' -#' Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features -#' deletes from resulting data.frame start_x, end_x, start_y, end_y. -#' And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring() -#' Or adds start_wkt and end_wkt, if geometry.type = st_point() -#' Added column/columns projected to given CRS (coordinate reference system), -#' that can be taken from network file of MATSimOutputDirectory +#' Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features. +#' If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format), +#' if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt. +#' Added column/columns are projected to given CRS (coordinate reference system). +#' The columns start_x, end_x, start_y, end_y are deleted from the resulting data frame. #' -#' Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" -#' to get which type of table was generated, if it is needed +#' @param table tibble trips_output (from readTripsTable()) #' -#' @param table tibble of trips_output (from readTripsTable()) -#' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file #' -#' @param geometry.type function of sf transformation, geometry.type can be (by default is st_multipoint()) -#' !!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or -#' !!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or -#' !!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!! +#' @param geometry.type type of sf transformation, default is st_multipoint(), geometry.type can be: +#' !!!st_point()- resulting table contains two geometry columns: start_wkt and end_wkt, representing start and end points as POINTS!!! or +#' !!!st_multipoint()- resulting table contains one geometry column, representing start and end points as MULTIPOINT!!! or +#' !!!st_linestring() - resulting table contains one geometry column, representing the line between start and end points as LINESTRING!!! #' -#' @return sf object (data.frame with geometries depending to geometry.type) +#' @return sf object (data frame with geometries depending on geometry.type) #' #' @export transformToSf <- function(table, From 8aa71753351dc2362b0710c44d0d22d20a307bd8 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 14 Jun 2023 13:57:55 +0200 Subject: [PATCH 28/87] added process_append_spatialcat and changed parameters in process_filter_by_shape --- NAMESPACE | 2 + R/output_trips.R | 186 +++++++++++++++++++++++++++-- man/process_append_spatialcat.Rd | 33 +++++ man/process_convert_table_to_sf.Rd | 33 +++++ man/process_filter_by_shape.Rd | 20 +--- 5 files changed, 249 insertions(+), 25 deletions(-) create mode 100644 man/process_append_spatialcat.Rd create mode 100644 man/process_convert_table_to_sf.Rd diff --git a/NAMESPACE b/NAMESPACE index 9d846bf..e2962dd 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -44,6 +44,8 @@ export(prepareSimwrapperDashboardFromFolder) export(prepareSimwrapperDashboardFromTable) export(processDtvEstimationQuality) export(processLinkStatsDtvDistribution) +export(process_append_spatialcat) +export(process_convert_table_to_sf) export(process_filter_by_shape) export(process_get_crs_from_config) export(process_get_od_matrix) diff --git a/R/output_trips.R b/R/output_trips.R index 7147bec..a234bac 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2122,6 +2122,83 @@ getCrsFromConfig <- function(folder) { return(NA) } + +#' Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature) +#' +#' Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features +#' deletes from resulting data.frame start_x, end_x, start_y, end_y. +#' And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring() +#' Or adds start_wkt and end_wkt, if geometry.type = st_point() +#' Added column/columns projected to given CRS (coordinate reference system), +#' that can be taken from network file of MATSimOutputDirectory +#' +#' Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" +#' to get which type of table was generated, if it is needed +#' +#' @param table tibble of trips_output (from readTripsTable()) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @param geometry.type function of sf transformation, geometry.type can be (by default is st_multipoint()) +#' !!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or +#' !!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or +#' !!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!! +#' +#' @return sf object (data.frame with geometries depending to geometry.type) +#' +#' @export +transformToSf <- function(table, + crs, + geometry.type = st_multipoint()) { + + .Deprecated("process_convert_table_to_sf") + + if (class(geometry.type)[2] == "POINT") { + table1 <- table %>% + # mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep ="")) + mutate(start_wkt = paste("POINT(", start_x, " ", start_y, ")", sep = "")) + table2 <- table %>% + mutate(end_wkt = paste("POINT(", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "POINT" + + + table1_wkt <- st_as_sf(table1, wkt = "start_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + table2_wkt <- st_as_sf(table2, wkt = "end_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + + result_table <- table1_wkt %>% mutate(end_wkt = table2_wkt$end_wkt) + st_geometry(result_table) <- "start_wkt" + st_crs(result_table) <- crs + st_geometry(result_table) <- "end_wkt" + st_crs(result_table) <- crs + st_geometry(result_table) <- "start_wkt" + return(result_table) + } else if (class(geometry.type)[2] == "MULTIPOINT") { + table <- table %>% + mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "MULTIPOINT" + + + result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + st_crs(result_table) <- crs + return(result_table) + } else if (class(geometry.type)[2] == "LINESTRING") { + table <- table %>% + mutate(wkt = paste("LINESTRING(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "LINESTRING" + + + result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + st_crs(result_table) <- crs + return(result_table) + } else { + return(NA) + } +} + + #####Reading##### @@ -2788,16 +2865,17 @@ process_append_distcat <- function(trips_table,distances_array = c(1000,2000,500 } ######Spatial###### + #' Filtering of trips_table(from readTripsTable) depending on how they located in given shape #' #' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). #' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) #' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) #' and filters the trips from table depending on *.inshape flags: -#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips \strong{inside} of the given shape +#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which \strong{originating} in the shape +#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which \strong{destinating} in the shape +#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which \strong{outside} of the given shape #' #' @param trips_table tibble of trips_output (from readTripsTable()) #' @@ -2805,9 +2883,7 @@ process_append_distcat <- function(trips_table,distances_array = c(1000,2000,500 #' #' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' -#' @param start.inshape bool, defines trips to conclude (see Description) -#' -#' @param end.inshape bool, defines trips to conclude (see Description) +#' @param spatial_type character parameter, used to specify which kind of trips should be filtered. Takes as input 4 templates: inside, outside, originating, destinating #' #' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) #' @@ -2815,14 +2891,32 @@ process_append_distcat <- function(trips_table,distances_array = c(1000,2000,500 process_filter_by_shape <- function(trips_table, shape_table, crs, - start.inshape = TRUE, end.inshape = TRUE) { - + spatial_type = "inside") { + + start.inshape <- TRUE + end.inshape <- TRUE + + if(spatial_type == "inside"){ + start.inshape <- TRUE + end.inshape <- TRUE + }else if(spatial_type == "outside"){ + start.inshape <- FALSE + end.inshape <- FALSE + }else if(spatial_type == "originating"){ + start.inshape <- TRUE + end.inshape <- FALSE + }else if(spatial_type == "destinating"){ + start.inshape <- FALSE + end.inshape <- TRUE + }else{ + stop("There are only 4 possible spatial_types: inside, outside, originating, destinating") + } # shape_table <- st_read(shapeFile) if (st_crs(shape_table) == NA) { st_crs(shape_table) <- crs } - sf_table <- transformToSf(trips_table, crs = crs, geometry.type = st_point()) + sf_table <- process_convert_table_to_sf(trips_table, crs = crs, geometry.type = st_point()) shape_table <- st_transform(shape_table, crs = crs) # shape_table isn't table - shape @@ -2856,6 +2950,76 @@ process_filter_by_shape <- function(trips_table, return(trips_table[cont_union, ]) } +#' Appending spatial category as additional column to output_trips tibble +#' +#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +#' and adds to the output_trips from table spatial category depending on postition related to shape file: +#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips \strong{inside} of the given shape +#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which \strong{originating} in the shape +#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which \strong{destinating} in the shape +#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which \strong{outside} of the given shape +#' +#' @param trips_table tibble of trips_output (from readTripsTable()) +#' +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @return tibble, with additional spatial column related to given shape +#' +#' @export +process_append_spatialcat <- function(trips_table, + shape_table, + crs, + spatial_type = "inside") { + + start.inshape <- TRUE + end.inshape <- TRUE + + # shape_table <- st_read(shapeFile) + if (st_crs(shape_table) == NA) { + st_crs(shape_table) <- crs + } + + sf_table <- process_convert_table_to_sf(trips_table, crs = crs, geometry.type = st_point()) + shape_table <- st_transform(shape_table, crs = crs) + # shape_table isn't table - shape + + union_shape <- st_union(shape_table) # transforms the crs back to the previous in the file + union_shape <- st_transform(union_shape, crs = st_crs(shape_table)) + + + st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry + cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile + + st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry + cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile + + # get trips that ended outside of shape + cont_end_outside <- setdiff(1:nrow(sf_table), cont2) + + # get trips that started outside of shape + cont_start_outside <- setdiff(1:nrow(sf_table), cont1) + + cont_union_inside <- intersect(cont1,cont2) + cont_union_outside <- intersect(cont_start_outside,cont_end_outside) + cont_union_originating <- intersect(cont1,cont_end_outside) + cont_union_destinating <- intersect(cont2, cont_start_outside) + + trips_table$spatial_category = NA + + trips_table[cont_union_inside, ]$spatial_category <- "inside" + trips_table[cont_union_outside, ]$spatial_category <- "outside" + trips_table[cont_union_originating, ]$spatial_category <- "originating" + trips_table[cont_union_destinating, ]$spatial_category <- "destinating" + + + return(trips_table) +} + + #' Reads an coordinate referenec system of MATSim output directory #' from output_config.xml #' @@ -3065,7 +3229,7 @@ process_get_od_matrix<- function(tripsTable, #' @return sf object (data.frame with geometries depending to geometry.type) #' #' @export -transformToSf <- function(table, +process_convert_table_to_sf <- function(table, crs, geometry.type = st_multipoint()) { if (class(geometry.type)[2] == "POINT") { diff --git a/man/process_append_spatialcat.Rd b/man/process_append_spatialcat.Rd new file mode 100644 index 0000000..73a3f68 --- /dev/null +++ b/man/process_append_spatialcat.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_append_spatialcat} +\alias{process_append_spatialcat} +\title{Appending spatial category as additional column to output_trips tibble} +\usage{ +process_append_spatialcat( + trips_table, + shape_table, + crs, + spatial_type = "inside" +) +} +\arguments{ +\item{trips_table}{tibble of trips_output (from readTripsTable())} + +\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} + +\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +} +\value{ +tibble, with additional spatial column related to given shape +} +\description{ +Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +and adds to the output_trips from table spatial category depending on postition related to shape file: +if start.inshape = TRUE & end.inshape = TRUE return table that contains trips \strong{inside} of the given shape +if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which \strong{originating} in the shape +if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which \strong{destinating} in the shape +if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which \strong{outside} of the given shape +} diff --git a/man/process_convert_table_to_sf.Rd b/man/process_convert_table_to_sf.Rd new file mode 100644 index 0000000..8fb90e9 --- /dev/null +++ b/man/process_convert_table_to_sf.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_convert_table_to_sf} +\alias{process_convert_table_to_sf} +\title{Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature)} +\usage{ +process_convert_table_to_sf(table, crs, geometry.type = st_multipoint()) +} +\arguments{ +\item{table}{tibble of trips_output (from readTripsTable())} + +\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} + +\item{geometry.type}{function of sf transformation, geometry.type can be (by default is st_multipoint()) +!!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or +!!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or +!!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!!} +} +\value{ +sf object (data.frame with geometries depending to geometry.type) +} +\description{ +Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features +deletes from resulting data.frame start_x, end_x, start_y, end_y. +And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring() +Or adds start_wkt and end_wkt, if geometry.type = st_point() +Added column/columns projected to given CRS (coordinate reference system), +that can be taken from network file of MATSimOutputDirectory +} +\details{ +Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" +to get which type of table was generated, if it is needed +} diff --git a/man/process_filter_by_shape.Rd b/man/process_filter_by_shape.Rd index 9f3a93f..980e0f5 100644 --- a/man/process_filter_by_shape.Rd +++ b/man/process_filter_by_shape.Rd @@ -4,22 +4,14 @@ \alias{process_filter_by_shape} \title{Filtering of trips_table(from readTripsTable) depending on how they located in given shape} \usage{ -process_filter_by_shape( - trips_table, - shape_table, - crs, - start.inshape = TRUE, - end.inshape = TRUE -) +process_filter_by_shape(trips_table, shape_table, crs, spatial_type = "inside") } \arguments{ \item{trips_table}{tibble of trips_output (from readTripsTable())} \item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} -\item{start.inshape}{bool, defines trips to conclude (see Description)} - -\item{end.inshape}{bool, defines trips to conclude (see Description)} +\item{spatial_type}{character parameter, used to specify which kind of trips should be filtered. Takes as input 4 templates: inside, outside, originating, destinating} \item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} } @@ -31,8 +23,8 @@ Takes trips_table and shapeTable(sf object from file representing geographical d Please be aware that this filterByRegion currently only works, when one geometry is loaded.) transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) and filters the trips from table depending on *.inshape flags: -if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +if start.inshape = TRUE & end.inshape = TRUE return table that contains trips \strong{inside} of the given shape +if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which \strong{originating} in the shape +if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which \strong{destinating} in the shape +if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which \strong{outside} of the given shape } From 23c5c85fa704451cebba57d46b8b058f51bbdf4d Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 14 Jun 2023 14:57:14 +0200 Subject: [PATCH 29/87] plot_spatialtype_by_shape_piechart and changed read_config to list output --- NAMESPACE | 1 + R/config.R | 23 +++--- R/output_trips.R | 89 ++++++++++++++++------- man/plot_spatialtype_by_shape_piechart.Rd | 21 ++++++ 4 files changed, 97 insertions(+), 37 deletions(-) create mode 100644 man/plot_spatialtype_by_shape_piechart.Rd diff --git a/NAMESPACE b/NAMESPACE index e2962dd..7b5aa9c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -37,6 +37,7 @@ export(plot_distance_by_mainmode_barchart) export(plot_distcat_by_mainmode_barchart) export(plot_mainmode_barchart) export(plot_mainmode_piechart) +export(plot_spatialtype_by_shape_piechart) export(plot_travelwaittime_mean_barchart) export(plot_trips_count_by_deptime_and_mainmode_linechart) export(prepareComparisonSimwrapperDashboardFromTable) diff --git a/R/config.R b/R/config.R index 081a03a..a769e79 100644 --- a/R/config.R +++ b/R/config.R @@ -14,27 +14,28 @@ read_config <- function(input_path = ".", n_max = Inf) { param = character(), value = character()) - config_xml = read_xml(input_path) + config_xml<-read_xml(input_path) - module_nodeset = xml_children(config_xml) + module_nodeset<-xml_children(config_xml) + + result_list <- list() for(i in 1:length(module_nodeset)){ module_name = xml_attr(module_nodeset[[i]],"name") - print(module_name) + param_nodeset = xml_children(module_nodeset[[i]]) for(j in 1:length(param_nodeset)){ - param_name = xml_attr(param_nodeset[[j]],"name") - value_name = xml_attr(param_nodeset[[j]],"value") + param_name<-xml_attr(param_nodeset[[j]],"name") + value_name<-xml_attr(param_nodeset[[j]],"value") #print(param_name,value_name) - temp_tibble = tibble(module = module_name, - param = param_name, - value = value_name - ) - result_tibble = rbind(result_tibble,temp_tibble) + + result_list[[module_name]][[param_name]] <- value_name + + } } - return(result_tibble) + return(result_list) } diff --git a/R/output_trips.R b/R/output_trips.R index a234bac..a3cfe89 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -1361,6 +1361,7 @@ plotMapWithTrips <- function(table, crs, optimized = FALSE) { #' @export plotTripTypesPieChart <- function(table, shapeTable, crs) { + .Deprecated("") # table_sf = transformToSf(table,crs = crs) # Maybe union all this tables as 1 extended with additional column filtered_inside <- filterByRegion(table, shapeTable, crs = crs, start.inshape = TRUE, end.inshape = TRUE) @@ -2516,6 +2517,41 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, return(fig) } +#' Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart +#' +#' +#' +#' @param table tibble of trips_output (from readTripsTable()) +#' +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' +#' +#' @return plot with percentage of each type of trips +#' +#' @export +plot_spatialtype_by_shape_piechart <- function(trips_table, shape_table, crs) { + + trips_table <- process_append_spatialcat(trips_table,shape_table = shape_table,crs = crs) + + #print(trips_table) + + + trips_table_distribution <- trips_table %>% count(spatial_category) + + #print(trips_table_distribution) + + fig <- plot_ly(trips_table_distribution, labels = ~spatial_category, values = ~n, type = 'pie') + fig <- fig %>% layout(title = 'Spatial type distribution', + xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE), + yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE)) + fig + + +} + ###### Compare ###### #' Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis @@ -3169,35 +3205,36 @@ process_get_od_matrix<- function(tripsTable, result_melt = melt(as.matrix(result_tibble)) colnames(result_melt) = c("origin","destination",1) - # Generating yaml and output_files - - if (file.exists(dump.output.to) & simwrapper == TRUE) { - write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") - } else if(!file.exists(dump.output.to) & simwrapper == TRUE) { - dir.create(dump.output.to) - write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") - } else if (file.exists(dump.output.to) & simwrapper == FALSE) { - write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) - } else { - dir.create(dump.output.to) - write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) - } - - yaml_list <- list( - title = "OD Flow", - description = "generated by deriveODMatrix", - projection = st_crs(shape)$input, - shpFile = paste0("../",shapePath), - dbfFile = paste0("../",substr(shapePath,start = 1,stop = nchar(shapePath)-3),"dbf"), - scaleFactor = 1, - lineWidth = 50, - csvFile = "ODMatrix.csv", - idColumn = colnames(shape)[1] # at the moment idColumn of shapefile should be the first column + # Generating yaml and output_files + # We remove it from new version, but still we are gonna use it in generate simwrapper of new version - ) - write_yaml(yaml_list, paste0(dump.output.to, "/viz-od-flow.yaml")) + # if (file.exists(dump.output.to) & simwrapper == TRUE) { + # write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") + # } else if(!file.exists(dump.output.to) & simwrapper == TRUE) { + # dir.create(dump.output.to) + # write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") + # } else if (file.exists(dump.output.to) & simwrapper == FALSE) { + # write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) + # } else { + # dir.create(dump.output.to) + # write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) + # } + # + # yaml_list <- list( + # title = "OD Flow", + # description = "generated by deriveODMatrix", + # projection = st_crs(shape)$input, + # shpFile = paste0("../",shapePath), + # dbfFile = paste0("../",substr(shapePath,start = 1,stop = nchar(shapePath)-3),"dbf"), + # scaleFactor = 1, + # lineWidth = 50, + # csvFile = "ODMatrix.csv", + # idColumn = colnames(shape)[1] # at the moment idColumn of shapefile should be the first column + # + # ) + # write_yaml(yaml_list, paste0(dump.output.to, "/viz-od-flow.yaml")) options(warn = defaultW) return(result_tibble) diff --git a/man/plot_spatialtype_by_shape_piechart.Rd b/man/plot_spatialtype_by_shape_piechart.Rd new file mode 100644 index 0000000..91a50a9 --- /dev/null +++ b/man/plot_spatialtype_by_shape_piechart.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{plot_spatialtype_by_shape_piechart} +\alias{plot_spatialtype_by_shape_piechart} +\title{Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart} +\usage{ +plot_spatialtype_by_shape_piechart(trips_table, shape_table, crs) +} +\arguments{ +\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} + +\item{table}{tibble of trips_output (from readTripsTable())} + +\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +} +\value{ +plot with percentage of each type of trips +} +\description{ +Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart +} From a4d1d2f4439f7943070459a8e1d31e04e26b02dd Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 14 Jun 2023 17:43:20 +0200 Subject: [PATCH 30/87] added plot_distance_by_spatialcategory --- NAMESPACE | 5 +++ R/output_trips.R | 41 ++++++++++++++++++++----- man/plot_distance_by_spatialcategory.Rd | 28 +++++++++++++++++ man/process_append_spatialcat.Rd | 7 +---- man/process_filter_by_shape.Rd | 2 +- 5 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 man/plot_distance_by_spatialcategory.Rd diff --git a/NAMESPACE b/NAMESPACE index 7b5aa9c..be119c7 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -34,6 +34,7 @@ export(plot_compare_mainmode_barchart) export(plot_compare_mainmode_sankey) export(plot_compare_travelwaittime_by_mainmode_barchart) export(plot_distance_by_mainmode_barchart) +export(plot_distance_by_spatialcategory) export(plot_distcat_by_mainmode_barchart) export(plot_mainmode_barchart) export(plot_mainmode_piechart) @@ -45,11 +46,15 @@ export(prepareSimwrapperDashboardFromFolder) export(prepareSimwrapperDashboardFromTable) export(processDtvEstimationQuality) export(processLinkStatsDtvDistribution) +export(process_append_distcat) export(process_append_spatialcat) export(process_convert_table_to_sf) export(process_filter_by_shape) export(process_get_crs_from_config) +export(process_get_mainmode_distribution) export(process_get_od_matrix) +export(process_get_travelwaittime_by_mainmode_barchart) +export(process_rename_mainmodes) export(readCounts) export(readLinkStats) export(readPersonsTable) diff --git a/R/output_trips.R b/R/output_trips.R index a3cfe89..4761b0a 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2552,6 +2552,34 @@ plot_spatialtype_by_shape_piechart <- function(trips_table, shape_table, crs) { } +#' Bar Chart with tripType on x-axis and travelled distance on y-axis +#' +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' travelled distance of each tripType related to the shapeTable +#' +#' +#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @return Bar Chart plot of distance traveled by spatial type +#' +#' @export +plot_distance_by_spatialcategory <- function(trips_table, shape_table, crs, euclidian = FALSE) { + + #processing + + trips_table<- process_append_spatialcat(trips_table,shape_table, crs = crs) + + #For plotting + travelled = trips_table %>% group_by(spatial_category) %>% summarize(travelled = sum(traveled_distance)/1000) + fig = plot_ly(data = travelled,x = ~spatial_category,y = ~travelled,type = 'bar',name = "Distance travelled by trip Type") + fig = fig %>% layout(yaxis = list(title = "Distance travelled (in kms)"),barmode = "group") + fig + return(fig) +} + ###### Compare ###### #' Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis @@ -2823,7 +2851,7 @@ plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_ ###### Mapping ###### #####Processing##### - +#' @export process_rename_mainmodes<-function(trips_table, unite.columns = character(0), united.name = "united"){ @@ -2833,7 +2861,7 @@ process_rename_mainmodes<-function(trips_table, } return(trips_table) } - +#' @export process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ trips_table_count <- trips_table %>% @@ -2853,7 +2881,7 @@ process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ return(trips_table) } - +#' @export process_get_travelwaittime_by_mainmode_barchart<-function(trips_table, time_format = "minute"){#also could be hours/seconds @@ -2876,7 +2904,7 @@ process_get_travelwaittime_by_mainmode_barchart<-function(trips_table, } - +#' @export process_append_distcat <- function(trips_table,distances_array = c(1000,2000,5000,10000,20000,50000,100000)){ distances_array = sort(c(distances_array,c(0,Inf))) @@ -2919,7 +2947,7 @@ process_append_distcat <- function(trips_table,distances_array = c(1000,2000,500 #' #' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' -#' @param spatial_type character parameter, used to specify which kind of trips should be filtered. Takes as input 4 templates: inside, outside, originating, destinating +#' @param spatial_type character parameter,categories of spatial information used to specify which kind of trips should be filtered. Takes as input 4 templates: inside, outside, originating, destinating #' #' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) #' @@ -3008,8 +3036,7 @@ process_filter_by_shape <- function(trips_table, #' @export process_append_spatialcat <- function(trips_table, shape_table, - crs, - spatial_type = "inside") { + crs) { start.inshape <- TRUE end.inshape <- TRUE diff --git a/man/plot_distance_by_spatialcategory.Rd b/man/plot_distance_by_spatialcategory.Rd new file mode 100644 index 0000000..4f2d7ee --- /dev/null +++ b/man/plot_distance_by_spatialcategory.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{plot_distance_by_spatialcategory} +\alias{plot_distance_by_spatialcategory} +\title{Bar Chart with tripType on x-axis and travelled distance on y-axis} +\usage{ +plot_distance_by_spatialcategory( + trips_table, + shape_table, + crs, + euclidian = FALSE +) +} +\arguments{ +\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} + +\item{tripsTable}{tible of trips_output (from readTripsTable())} + +\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +} +\value{ +Bar Chart plot of distance traveled by spatial type +} +\description{ +Takes Table trips_output (from readTripsTable()), +to plot bar chart with with values that represent +travelled distance of each tripType related to the shapeTable +} diff --git a/man/process_append_spatialcat.Rd b/man/process_append_spatialcat.Rd index 73a3f68..6c82d88 100644 --- a/man/process_append_spatialcat.Rd +++ b/man/process_append_spatialcat.Rd @@ -4,12 +4,7 @@ \alias{process_append_spatialcat} \title{Appending spatial category as additional column to output_trips tibble} \usage{ -process_append_spatialcat( - trips_table, - shape_table, - crs, - spatial_type = "inside" -) +process_append_spatialcat(trips_table, shape_table, crs) } \arguments{ \item{trips_table}{tibble of trips_output (from readTripsTable())} diff --git a/man/process_filter_by_shape.Rd b/man/process_filter_by_shape.Rd index 980e0f5..ca01767 100644 --- a/man/process_filter_by_shape.Rd +++ b/man/process_filter_by_shape.Rd @@ -11,7 +11,7 @@ process_filter_by_shape(trips_table, shape_table, crs, spatial_type = "inside") \item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} -\item{spatial_type}{character parameter, used to specify which kind of trips should be filtered. Takes as input 4 templates: inside, outside, originating, destinating} +\item{spatial_type}{character parameter,categories of spatial information used to specify which kind of trips should be filtered. Takes as input 4 templates: inside, outside, originating, destinating} \item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} } From 6dcc51aac5b1faa7a754419854ea3eada9aada18 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 21 Jun 2023 14:20:22 +0200 Subject: [PATCH 31/87] added map functions --- NAMESPACE | 5 +- R/output_trips.R | 442 +++++++++++++++++- man/plot_compare_count_by_spatialcat.Rd | 32 ++ ...gory.Rd => plot_distance_by_spatialcat.Rd} | 11 +- man/plot_map_trips.Rd | 21 + man/plot_map_trips_by_spatialcat.Rd | 23 + 6 files changed, 521 insertions(+), 13 deletions(-) create mode 100644 man/plot_compare_count_by_spatialcat.Rd rename man/{plot_distance_by_spatialcategory.Rd => plot_distance_by_spatialcat.Rd} (80%) create mode 100644 man/plot_map_trips.Rd create mode 100644 man/plot_map_trips_by_spatialcat.Rd diff --git a/NAMESPACE b/NAMESPACE index be119c7..2ef9525 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -29,15 +29,18 @@ export(plotTripCountByDepTime) export(plotTripDistanceByMode) export(plotTripDistancedByType) export(plotTripTypesPieChart) +export(plot_compare_count_by_spatialcat) export(plot_compare_distcat_by_mainmode_barchart) export(plot_compare_mainmode_barchart) export(plot_compare_mainmode_sankey) export(plot_compare_travelwaittime_by_mainmode_barchart) export(plot_distance_by_mainmode_barchart) -export(plot_distance_by_spatialcategory) +export(plot_distance_by_spatialcat) export(plot_distcat_by_mainmode_barchart) export(plot_mainmode_barchart) export(plot_mainmode_piechart) +export(plot_map_trips) +export(plot_map_trips_by_spatialcat) export(plot_spatialtype_by_shape_piechart) export(plot_travelwaittime_mean_barchart) export(plot_trips_count_by_deptime_and_mainmode_linechart) diff --git a/R/output_trips.R b/R/output_trips.R index 4761b0a..241c3ef 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -854,7 +854,8 @@ plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character #' @return Line plot with arrival time x-axis and number end activities on y-axis #' #' @export -plotDepartureTimesPerTripPurpose <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, +plotDepartureTimesPerTripPurpose <- function(tripsTable, unite.columns = character(0), united.name = "united", + dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { @@ -1232,6 +1233,7 @@ plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRU #' #' @export plotMapWithTrips <- function(table, crs, optimized = FALSE) { + table_sf <- transformToSf(table, crs = crs, geometry.type = st_point()) st_geometry(table_sf) <- "start_wkt" table_sf_start <- table_sf %>% select(-end_wkt) @@ -1340,7 +1342,7 @@ plotMapWithTrips <- function(table, crs, optimized = FALSE) { # position it on the topleft position = "topleft" ) - + plt return(plt) } @@ -2566,14 +2568,14 @@ plot_spatialtype_by_shape_piechart <- function(trips_table, shape_table, crs) { #' @return Bar Chart plot of distance traveled by spatial type #' #' @export -plot_distance_by_spatialcategory <- function(trips_table, shape_table, crs, euclidian = FALSE) { +plot_distance_by_spatialcat <- function(trips_table, shape_table, crs, euclidian = FALSE) { #processing trips_table<- process_append_spatialcat(trips_table,shape_table, crs = crs) + travelled = trips_table %>% group_by(spatial_category) %>% summarize(travelled = sum(traveled_distance)/1000) #For plotting - travelled = trips_table %>% group_by(spatial_category) %>% summarize(travelled = sum(traveled_distance)/1000) fig = plot_ly(data = travelled,x = ~spatial_category,y = ~travelled,type = 'bar',name = "Distance travelled by trip Type") fig = fig %>% layout(yaxis = list(title = "Distance travelled (in kms)"),barmode = "group") fig @@ -2848,8 +2850,440 @@ plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_ } +#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis +#' +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' time spent on traveling/waiting +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' @param tripsTable1 tible of trips_output (from readTripsTable()) +#' @param tripsTable2 tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' +#' @return Bar Chart plot of average time spent on travel/wait +#' +#' @export +plot_compare_count_by_spatialcat <- function(trips_table1,trips_table2, shape_table ,crs,dump.output.to = matsimDumpOutputDirectory) { + + spatial_table1 <- process_append_spatialcat(trips_table = trips_table1, + shape_table = shape_table, + crs = crs) + + spatial_table2 <- process_append_spatialcat(trips_table = trips_table2, + shape_table = shape_table, + crs = crs) + + + plt = ggplot(result_table, aes(x =type,fill = factor(table_num)))+ + geom_bar(position = position_dodge())+ + coord_flip() + plotly::ggplotly(plt) + + + return(plotly::ggplotly(plt)) + +} + + + + ###### Mapping ###### + +#' Plots start and end coordinates of the given trips table on an osm map +#' +#' @param table tibble of trips_output (from readTripsTable()) +#' +#' +#' @param crs numeric representation of the EPSG code or proj4string for the corresponding coordinate system of the trip coordinates, can be found in network file from output directory of MATSim simulation +#' +#' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot +#' +#' +#' @return plot with trips +#' +#' @export +plot_map_trips <- function(trips_table, crs,optimized = FALSE, + shape_table = NULL ) { + + table_sf <- process_convert_table_to_sf(trips_table, crs = crs, geometry.type = st_point()) + st_geometry(table_sf) <- "start_wkt" + table_sf_start <- table_sf %>% select(-end_wkt) + st_geometry(table_sf) <- "end_wkt" + table_sf_end <- table_sf %>% select(-start_wkt) + + if(!is.null(shape_table)){ + + if (st_crs(shape_table) == NA) { + ct_crs(shape_table) <- crs + } + shape_table <- st_transform(shape_table, crs = "+proj=longlat +datum=WGS84 +no_defs") + + } + + table_sf_start <- st_transform(table_sf_start, "+proj=longlat +datum=WGS84 +no_defs") + table_sf_end <- st_transform(table_sf_end, "+proj=longlat +datum=WGS84 +no_defs") + + if (optimized) { + colors <- c("Start" = "blue", "End" = "red") + shapes <- c("Start" = 5, "End" = 3) + # ggplot2 isn't interactive! + plt <- ggplot() + + geom_sf(data = table_sf_start, aes(color = "Start"), size = 1, shape = 5) + + geom_sf(data = table_sf_end, aes(color = "End"), size = 1, shape = 3) + + labs(color = "Type") + + scale_colour_manual(values = colors) + + if(!is.null(shape_table)){ + plt <-ggplot() + + geom_sf(data = shape_table)+ + geom_sf(data = table_sf_start, aes(color = "Start"), size = 1, shape = 5) + + geom_sf(data = table_sf_end, aes(color = "End"), size = 1, shape = 3) + + labs(color = "Type") + + scale_colour_manual(values = colors) + } + plt + return(plt) + } + + + + + + + + + # If we need to change design + # css_fix <- "div.info.legend.leaflet-control br {clear: both;}" + # Convert CSS to HTML + # html_fix <- htmltools::tags$style(type = "text/css", css_fix) + + plt <- leaflet() %>% + addTiles() %>% + addProviderTiles( + "OpenStreetMap", + # give the layer a name + group = "OpenStreetMap" + ) %>% + addProviderTiles( + "Stamen.Toner", + group = "Stamen.Toner" + ) %>% + addProviderTiles( + "Stamen.Terrain", + group = "Stamen.Terrain" + ) %>% + addProviderTiles( + "Esri.WorldStreetMap", + group = "Esri.WorldStreetMap" + ) %>% + addProviderTiles( + "Wikimedia", + group = "Wikimedia" + ) %>% + addProviderTiles( + "CartoDB.Positron", + group = "CartoDB.Positron" + ) %>% + addProviderTiles( + "Esri.WorldImagery", + group = "Esri.WorldImagery" + ) %>% + addCircleMarkers(table_sf_start, + lng = st_coordinates(table_sf_start$start_wkt)[, 1], + lat = st_coordinates(table_sf_start$start_wkt)[, 2], radius = 3, color = "blue", + label = paste( + "Person_id:", + table_sf_start$person, "
", + "Trip_id:", + table_sf_start$trip_id, "
", + "main_mode:", table_sf_start$main_mode, "
", + "type:", "start", "
", + "Start activity:", + table_sf_start$start_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(table_sf_end, + lng = st_coordinates(table_sf_end$end_wkt)[, 1], + lat = st_coordinates(table_sf_end$end_wkt)[, 2], radius = 0.15, color = "red", + label = paste( + "Person_id:", + table_sf_end$person, "
", + "Trip_id:", + table_sf_end$trip_id, "
", + "main_mode:", table_sf_end$main_mode, "
", + "type:", "end", "
", + "End activity:", + table_sf_end$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addLegend( + colors = c("blue", "red"), + labels = c("Start of trip", "End of trip"), + position = "bottomleft", + title = "Type of the point", + opacity = 0.9 + ) %>% + addMiniMap() %>% + addLayersControl( + baseGroups = c( + "OpenStreetMap", "Stamen.Toner", + "Stamen.Terrain", "Esri.WorldStreetMap", + "Wikimedia", "CartoDB.Positron", "Esri.WorldImagery" + ), + # position it on the topleft + position = "topleft" + ) + if(!is.null(shape_table)){ + plt = plt %>% addPolygons(data = shape_table, opacity = 0.1, color = "green") + + } + plt + return(plt) +} + + +#' Plots every type of trips(inside, outside, origin and destinating) on map +#' +#' +#' +#' @param table tibble of trips_output (from readTripsTable()) +#' +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot +#' +#' @return plot that contains every trip with defined trip type +#' +#' @export +plot_map_trips_by_spatialcat <- function(trips_table, shape_table, + crs, optimized = FALSE) { + + + #processing + + spatial_table <- process_append_spatialcat(trips_table, shape_table = shape_table,crs = crs) + + filtered_sf_inside <- spatial_table %>% filter(spatial_category == "inside") %>% + process_convert_table_to_sf( crs = crs, geometry.type = st_multipoint()) + filtered_sf_origin <- spatial_table %>% filter(spatial_category == "originating") %>% + process_convert_table_to_sf( crs = crs, geometry.type = st_multipoint()) + filtered_sf_destination <- spatial_table %>% filter(spatial_category == "destinating") %>% + process_convert_table_to_sf( crs = crs, geometry.type = st_multipoint()) + filtered_sf_transit <- spatial_table %>% filter(spatial_category == "outside") %>% + process_convert_table_to_sf( crs = crs, geometry.type = st_multipoint()) + + if (st_crs(shape_table) == NA) { + ct_crs(shape_table) <- crs + } + + shape_table <- st_transform(shape_table, crs = "+proj=longlat +datum=WGS84 +no_defs") + + filtered_sf_inside <- st_transform(filtered_sf_inside, "+proj=longlat +datum=WGS84 +no_defs") + filtered_sf_origin <- st_transform(filtered_sf_origin, "+proj=longlat +datum=WGS84 +no_defs") + filtered_sf_destination <- st_transform(filtered_sf_destination, "+proj=longlat +datum=WGS84 +no_defs") + filtered_sf_transit <- st_transform(filtered_sf_transit, "+proj=longlat +datum=WGS84 +no_defs") + + + #plotting + if (optimized) { + colors <- c("inside" = "green", "origin" = "red", "destination" = "orange", "transit" = "blue") + shapes <- c("Start" = 5, "End" = 3) + plt <- ggplot() + + geom_sf(data = shape_table) + + # geom_sf(data = ) + geom_sf(data = filtered_sf_inside, aes(color = "inside"), size = 3, alpha = 0.5) + + geom_sf(data = filtered_sf_origin, aes(color = "origin"), size = 3, alpha = 0.4) + + geom_sf(data = filtered_sf_destination, aes(color = "destination"), size = 3, alpha = 0.3) + + geom_sf(data = filtered_sf_transit, aes(color = "transit"), size = 2, alpha = 0.1) + + labs(color = "Type") + + scale_colour_manual(values = colors) + plt + return((plt)) + } + + # If we need to adjust design + # css_fix <- "div.info.legend.leaflet-control br {clear: both;}" + # Convert CSS to HTML + # html_fix <- htmltools::tags$style(type = "text/css", css_fix) + + + plt <- leaflet() %>% + addTiles() %>% + addProviderTiles( + "OpenStreetMap", + # give the layer a name + group = "OpenStreetMap" + ) %>% + addProviderTiles( + "Stamen.Toner", + group = "Stamen.Toner" + ) %>% + addProviderTiles( + "Stamen.Terrain", + group = "Stamen.Terrain" + ) %>% + addProviderTiles( + "Esri.WorldStreetMap", + group = "Esri.WorldStreetMap" + ) %>% + addProviderTiles( + "Wikimedia", + group = "Wikimedia" + ) %>% + addProviderTiles( + "CartoDB.Positron", + group = "CartoDB.Positron" + ) %>% + addProviderTiles( + "Esri.WorldImagery", + group = "Esri.WorldImagery" + ) %>% + addPolygons(data = shape_table, opacity = 0.1, color = "green") %>% + addCircleMarkers(filtered_sf_inside, + lng = st_coordinates(filtered_sf_inside$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_inside$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 3, color = "blue", + label = paste( + "Person_id:", + filtered_sf_inside$person, "
", + "Trip_id:", + filtered_sf_inside$trip_id, "
", + "main_mode:", filtered_sf_inside$main_mode, "
", + "type:", "start", "
", + "Start activity:", + filtered_sf_inside$start_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(filtered_sf_inside, + lng = st_coordinates(filtered_sf_inside$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_inside$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 3, color = "blue", + label = paste( + "Person_id:", + filtered_sf_inside$person, "
", + "Trip_id:", + filtered_sf_inside$trip_id, "
", + "main_mode:", filtered_sf_inside$main_mode, "
", + "type:", "end", "
", + "End activity:", + filtered_sf_inside$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(filtered_sf_origin, + lng = st_coordinates(filtered_sf_origin$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_origin$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 2, color = "red", + label = paste( + "Person_id:", + filtered_sf_origin$person, "
", + "Trip_id:", + filtered_sf_origin$trip_id, "
", + "main_mode:", filtered_sf_origin$main_mode, "
", + "type:", "start", "
", + "Start activity:", + filtered_sf_origin$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(filtered_sf_origin, + lng = st_coordinates(filtered_sf_origin$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_origin$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 2, color = "red", + label = paste( + "Person_id:", + filtered_sf_origin$person, "
", + "Trip_id:", + filtered_sf_origin$trip_id, "
", + "main_mode:", filtered_sf_origin$main_mode, "
", + "type:", "end", "
", + "End activity:", + filtered_sf_origin$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(filtered_sf_destination, + lng = st_coordinates(filtered_sf_destination$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_destination$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 1, color = "orange", + label = paste( + "Person_id:", + filtered_sf_destination$person, "
", + "Trip_id:", + filtered_sf_destination$trip_id, "
", + "main_mode:", filtered_sf_destination$main_mode, "
", + "type:", "start", "
", + "Start activity:", + filtered_sf_destination$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(filtered_sf_destination, + lng = st_coordinates(filtered_sf_destination$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_destination$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 1, color = "orange", + label = paste( + "Person_id:", + filtered_sf_destination$person, "
", + "Trip_id:", + filtered_sf_destination$trip_id, "
", + "main_mode:", filtered_sf_destination$main_mode, "
", + "type:", "end", "
", + "End activity:", + filtered_sf_destination$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(filtered_sf_transit, + lng = st_coordinates(filtered_sf_transit$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_transit$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 0.15, color = "black", + label = paste( + "Person_id:", + filtered_sf_transit$person, "
", + "Trip_id:", + filtered_sf_transit$trip_id, "
", + "main_mode:", filtered_sf_transit$main_mode, "
", + "type:", "start", "
", + "Start activity:", + filtered_sf_transit$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(filtered_sf_transit, + lng = st_coordinates(filtered_sf_transit$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_transit$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 0.15, color = "black", + label = paste( + "Person_id:", + filtered_sf_transit$person, "
", + "Trip_id:", + filtered_sf_transit$trip_id, "
", + "main_mode:", filtered_sf_transit$main_mode, "
", + "type:", "end", "
", + "End activity:", + filtered_sf_transit$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addLegend( + colors = c("blue", "red", "orange", "black"), + labels = c( + "Trips inside of region", + "Trips with the end outside region", + "Trips with the start outside region", + "Trips that start and end outside region" + ), + position = "bottomleft", + title = "Type of the point", + opacity = 0.9 + ) %>% + addMiniMap() %>% + addLayersControl( + baseGroups = c( + "OpenStreetMap", "Stamen.Toner", + "Stamen.Terrain", "Esri.WorldStreetMap", + "Wikimedia", "CartoDB.Positron", "Esri.WorldImagery" + ), + # position it on the topleft + position = "topleft" + ) + + plt + return(plt) +} + #####Processing##### #' @export process_rename_mainmodes<-function(trips_table, diff --git a/man/plot_compare_count_by_spatialcat.Rd b/man/plot_compare_count_by_spatialcat.Rd new file mode 100644 index 0000000..cc7e191 --- /dev/null +++ b/man/plot_compare_count_by_spatialcat.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{plot_compare_count_by_spatialcat} +\alias{plot_compare_count_by_spatialcat} +\title{Bar Chart with main_mode on x-axis and average travel/wait time on y-axis} +\usage{ +plot_compare_count_by_spatialcat( + trips_table1, + trips_table2, + shape_table, + crs, + dump.output.to = matsimDumpOutputDirectory +) +} +\arguments{ +\item{tripsTable1}{tible of trips_output (from readTripsTable())} + +\item{tripsTable2}{tible of trips_output (from readTripsTable())} + +\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} + +\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +} +\value{ +Bar Chart plot of average time spent on travel/wait +} +\description{ +Takes Table trips_output (from readTripsTable()), +to plot bar chart with with values that represent +time spent on traveling/waiting +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +} diff --git a/man/plot_distance_by_spatialcategory.Rd b/man/plot_distance_by_spatialcat.Rd similarity index 80% rename from man/plot_distance_by_spatialcategory.Rd rename to man/plot_distance_by_spatialcat.Rd index 4f2d7ee..ba138d3 100644 --- a/man/plot_distance_by_spatialcategory.Rd +++ b/man/plot_distance_by_spatialcat.Rd @@ -1,15 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/output_trips.R -\name{plot_distance_by_spatialcategory} -\alias{plot_distance_by_spatialcategory} +\name{plot_distance_by_spatialcat} +\alias{plot_distance_by_spatialcat} \title{Bar Chart with tripType on x-axis and travelled distance on y-axis} \usage{ -plot_distance_by_spatialcategory( - trips_table, - shape_table, - crs, - euclidian = FALSE -) +plot_distance_by_spatialcat(trips_table, shape_table, crs, euclidian = FALSE) } \arguments{ \item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} diff --git a/man/plot_map_trips.Rd b/man/plot_map_trips.Rd new file mode 100644 index 0000000..5665744 --- /dev/null +++ b/man/plot_map_trips.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{plot_map_trips} +\alias{plot_map_trips} +\title{Plots start and end coordinates of the given trips table on an osm map} +\usage{ +plot_map_trips(trips_table, crs, optimized = FALSE, shape_table = NULL) +} +\arguments{ +\item{crs}{numeric representation of the EPSG code or proj4string for the corresponding coordinate system of the trip coordinates, can be found in network file from output directory of MATSim simulation} + +\item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot} + +\item{table}{tibble of trips_output (from readTripsTable())} +} +\value{ +plot with trips +} +\description{ +Plots start and end coordinates of the given trips table on an osm map +} diff --git a/man/plot_map_trips_by_spatialcat.Rd b/man/plot_map_trips_by_spatialcat.Rd new file mode 100644 index 0000000..f540cc8 --- /dev/null +++ b/man/plot_map_trips_by_spatialcat.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{plot_map_trips_by_spatialcat} +\alias{plot_map_trips_by_spatialcat} +\title{Plots every type of trips(inside, outside, origin and destinating) on map} +\usage{ +plot_map_trips_by_spatialcat(trips_table, shape_table, crs, optimized = FALSE) +} +\arguments{ +\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} + +\item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot} + +\item{table}{tibble of trips_output (from readTripsTable())} + +\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +} +\value{ +plot that contains every trip with defined trip type +} +\description{ +Plots every type of trips(inside, outside, origin and destinating) on map +} From 1ed81649710d3b5bd8434d99ae5f57718c0aade1 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 21 Jun 2023 15:36:24 +0200 Subject: [PATCH 32/87] changed documentation for plotModalSplitPieChart --- R/output_trips.R | 13 ++++++++++++- man/matsimr-deprecated.Rd | 7 +++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/R/output_trips.R b/R/output_trips.R index 241c3ef..aa3188c 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -18,11 +18,22 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' the matsimr package. They may eventually be completely #' removed. #' -#' +#' \strong{plotModalSplitPieChart} - Takes Table trips_output (from readTripsTable()), +#' to plot pie chart with with values that represent +#' percentage of using transport modes from trips #' #' @rdname matsimr-deprecated #' @name matsimr-deprecated #' +#' +#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' +#' @return \strong{plotModalSplitPieChart} - Pie Chart plot of transport mode distribution, values given in percents +#' #' @docType package #' @export plotModalSplitPieChart #' @aliases plotModalSplitPieChart diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 080261c..7fd5146 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -73,6 +73,8 @@ appendDistanceCategory(tripsTable) \item{n_max}{integer, maximum number of lines to read within output_trips} } \value{ +\strong{plotModalSplitPieChart} - Pie Chart plot of transport mode distribution, values given in percents + \strong{readTripsTable} - tibble of trips_output \strong{plotAverageTravelWait} - Bar Chart plot of average time spent on travel/wait @@ -98,6 +100,11 @@ to plot bar chart with with values that represent number of trips ~ distance travelled Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') } +\details{ +\strong{plotModalSplitPieChart} - Takes Table trips_output (from readTripsTable()), +to plot pie chart with with values that represent +percentage of using transport modes from trips +} \section{Details}{ \tabular{rl}{ From f5a33fd87f7f51bdaa0cfd1b3ad929e7851d07fc Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 21 Jun 2023 15:40:50 +0200 Subject: [PATCH 33/87] line breaks test --- R/output_trips.R | 3 +-- man/matsimr-deprecated.Rd | 10 ++++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index aa3188c..9fe7775 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -16,8 +16,7 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' #' These functions are provided for compatibility with older version of #' the matsimr package. They may eventually be completely -#' removed. -#' +#' removed.\cr #' \strong{plotModalSplitPieChart} - Takes Table trips_output (from readTripsTable()), #' to plot pie chart with with values that represent #' percentage of using transport modes from trips diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 7fd5146..0cd1991 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -84,7 +84,10 @@ appendDistanceCategory(tripsTable) \description{ These functions are provided for compatibility with older version of the matsimr package. They may eventually be completely -removed. +removed.\cr +\strong{plotModalSplitPieChart} - Takes Table trips_output (from readTripsTable()), +to plot pie chart with with values that represent +percentage of using transport modes from trips \strong{readTripsTable} - Loads a MATSim CSV output_trips from file or archive, creating a tibble with columns as in csv file @@ -100,11 +103,6 @@ to plot bar chart with with values that represent number of trips ~ distance travelled Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') } -\details{ -\strong{plotModalSplitPieChart} - Takes Table trips_output (from readTripsTable()), -to plot pie chart with with values that represent -percentage of using transport modes from trips -} \section{Details}{ \tabular{rl}{ From 5a7cecc61960fbd8b882c0c6c772f76e0090b863 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 21 Jun 2023 15:49:07 +0200 Subject: [PATCH 34/87] added till compare documentations --- R/output_trips.R | 39 ++++++++++++++++----- man/compareModalDistanceDistribution.Rd | 37 -------------------- man/matsimr-deprecated.Rd | 45 ++++++++++++++++++++++++- man/plotTripDistanceByMode.Rd | 34 ------------------- 4 files changed, 74 insertions(+), 81 deletions(-) delete mode 100644 man/compareModalDistanceDistribution.Rd delete mode 100644 man/plotTripDistanceByMode.Rd diff --git a/R/output_trips.R b/R/output_trips.R index 9fe7775..d79a81d 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -16,7 +16,7 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' #' These functions are provided for compatibility with older version of #' the matsimr package. They may eventually be completely -#' removed.\cr +#' removed.\cr\cr #' \strong{plotModalSplitPieChart} - Takes Table trips_output (from readTripsTable()), #' to plot pie chart with with values that represent #' percentage of using transport modes from trips @@ -132,9 +132,21 @@ plotModalSplitPieChart <- function(tripsTable, } #' Deprecated function(s) in the matsimr package #' +#' \strong{plotModalSplitBarChart} - Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' percentage of using transport modes from trips #' #' @rdname matsimr-deprecated #' +#' +#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' +#' @return \strong{plotModalSplitBarChart} - Bar Chart plot of transport mode distribution, values given in percents +#' #' @docType package #' @export plotModalSplitBarChart #' @aliases plotModalSplitBarChart @@ -256,6 +268,11 @@ readTripsTable <-function(input_path = ".", n_max = Inf) { #' #' @rdname matsimr-deprecated #' +#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' #' @return \strong{plotAverageTravelWait} - Bar Chart plot of average time spent on travel/wait #' @docType package @@ -291,6 +308,8 @@ plotAverageTravelWait <- function(tripsTable, unite.columns = character(0), unit } +###Needs to be added, because in master there isn't propper documentation + #' Deprecated function(s) in the matsimr package #' #' @@ -349,7 +368,7 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch } -#' Bar Chart with distance travelled on x-axis and number of trips on y-axis +#' Deprecated function(s) in the matsimr package #' #' \strong{plotModalDistanceDistribution} - Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent @@ -366,6 +385,7 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' #' @return \strong{plotModalDistanceDistribution} Bar Chart plot of count of trips among distance travelled #' #' @export @@ -444,13 +464,14 @@ plotModalDistanceDistribution <- function(tripsTable, unite.columns = character( } -#' Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis +#' Deprecated function(s) in the matsimr package #' -#' Takes 2 Tables trips_output (from readTripsTable()), +#' \strong{compareModalDistanceDistribution} - Takes 2 Tables trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' +#' @rdname matsimr-deprecated #' #' @param tripsTable1 tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 #' @param tripsTable2 tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted @@ -458,7 +479,7 @@ plotModalDistanceDistribution <- function(tripsTable, unite.columns = character( #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' @return Bar Chart plot of count of trips among distance travelled +#' @return \strong{compareModalDistanceDistribution} - Bar Chart plot of count of trips among distance travelled #' #' @export compareModalDistanceDistribution <- function(tripsTable1,tripsTable2, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, @@ -520,21 +541,21 @@ compareModalDistanceDistribution <- function(tripsTable1,tripsTable2, unite.colu } -#' Bar Chart with distance travelled on x-axis and number of trips on y-axis +#' Deprecated function(s) in the matsimr package #' -#' Takes Table trips_output (from readTripsTable()), +#' \strong{plotTripDistanceByMode} - Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' average distance traveled ~ main mode used #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' -#' +#' @rdname matsimr-deprecated #' @param tripsTable tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' -#' @return Bar Chart plot of distance traveled per mode +#' @return \strong{plotTripDistanceByMode} - Bar Chart plot of distance traveled per mode #' #' @export plotTripDistanceByMode <- function(tripsTable, diff --git a/man/compareModalDistanceDistribution.Rd b/man/compareModalDistanceDistribution.Rd deleted file mode 100644 index ea7f77f..0000000 --- a/man/compareModalDistanceDistribution.Rd +++ /dev/null @@ -1,37 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{compareModalDistanceDistribution} -\alias{compareModalDistanceDistribution} -\title{Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis} -\usage{ -compareModalDistanceDistribution( - tripsTable1, - tripsTable2, - unite.columns = character(0), - united.name = "united", - dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE -) -} -\arguments{ -\item{tripsTable1}{tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1} - -\item{tripsTable2}{tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted} - -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} - -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} - -\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} -} -\value{ -Bar Chart plot of count of trips among distance travelled -} -\description{ -Takes 2 Tables trips_output (from readTripsTable()), -to plot bar chart with with values that represent -difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -} diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 0cd1991..2515857 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -9,6 +9,8 @@ \alias{plotAverageTravelWait} \alias{compareAverageTravelWait} \alias{plotModalDistanceDistribution} +\alias{compareModalDistanceDistribution} +\alias{plotTripDistanceByMode} \alias{appendDistanceCategory} \title{Deprecated function(s) in the matsimr package} \usage{ @@ -55,6 +57,23 @@ plotModalDistanceDistribution( only.files = FALSE ) +compareModalDistanceDistribution( + tripsTable1, + tripsTable2, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + only.files = FALSE +) + +plotTripDistanceByMode( + tripsTable, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + only.files = FALSE +) + appendDistanceCategory(tripsTable) } \arguments{ @@ -71,24 +90,38 @@ appendDistanceCategory(tripsTable) \item{input_path}{character string, path to matsim output directory or http link to the file.} \item{n_max}{integer, maximum number of lines to read within output_trips} + +\item{tripsTable1}{tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1} + +\item{tripsTable2}{tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted} } \value{ \strong{plotModalSplitPieChart} - Pie Chart plot of transport mode distribution, values given in percents +\strong{plotModalSplitBarChart} - Bar Chart plot of transport mode distribution, values given in percents + \strong{readTripsTable} - tibble of trips_output \strong{plotAverageTravelWait} - Bar Chart plot of average time spent on travel/wait \strong{plotModalDistanceDistribution} Bar Chart plot of count of trips among distance travelled + +\strong{compareModalDistanceDistribution} - Bar Chart plot of count of trips among distance travelled + +\strong{plotTripDistanceByMode} - Bar Chart plot of distance traveled per mode } \description{ These functions are provided for compatibility with older version of the matsimr package. They may eventually be completely -removed.\cr +removed.\cr\cr \strong{plotModalSplitPieChart} - Takes Table trips_output (from readTripsTable()), to plot pie chart with with values that represent percentage of using transport modes from trips +\strong{plotModalSplitBarChart} - Takes Table trips_output (from readTripsTable()), +to plot bar chart with with values that represent +percentage of using transport modes from trips + \strong{readTripsTable} - Loads a MATSim CSV output_trips from file or archive, creating a tibble with columns as in csv file @@ -102,6 +135,16 @@ to unite them in 1 mode with the name united.name(by default 'united') to plot bar chart with with values that represent number of trips ~ distance travelled Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') + +\strong{compareModalDistanceDistribution} - Takes 2 Tables trips_output (from readTripsTable()), +to plot bar chart with with values that represent +difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') + +\strong{plotTripDistanceByMode} - Takes Table trips_output (from readTripsTable()), +to plot bar chart with with values that represent +average distance traveled ~ main mode used +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') } \section{Details}{ diff --git a/man/plotTripDistanceByMode.Rd b/man/plotTripDistanceByMode.Rd deleted file mode 100644 index 0bc5119..0000000 --- a/man/plotTripDistanceByMode.Rd +++ /dev/null @@ -1,34 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{plotTripDistanceByMode} -\alias{plotTripDistanceByMode} -\title{Bar Chart with distance travelled on x-axis and number of trips on y-axis} -\usage{ -plotTripDistanceByMode( - tripsTable, - unite.columns = character(0), - united.name = "united", - dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE -) -} -\arguments{ -\item{tripsTable}{tible of trips_output (from readTripsTable())} - -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} - -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} - -\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} -} -\value{ -Bar Chart plot of distance traveled per mode -} -\description{ -Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -average distance traveled ~ main mode used -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -} From 4d642e61cc75953923fe5893b6ec4c9e477e67e1 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 22 Jun 2023 16:41:20 +0200 Subject: [PATCH 35/87] documentation structure till plotMapWithTripsType incllusive --- R/output_trips.R | 105 +++++++------ man/compareTripTypesBarChart.Rd | 33 ---- man/matsimr-deprecated.Rd | 200 +++++++++++++++++++++++- man/plotActivityEndTimes.Rd | 35 ----- man/plotArrivalTimesPerTripPurpose.Rd | 35 ----- man/plotDepartureTimesPerTripPurpose.Rd | 34 ---- man/plotMapWithFilteredTrips.Rd | 41 ----- man/plotMapWithTrips.Rd | 21 --- man/plotMapWithTripsType.Rd | 23 --- man/plotModalShiftBar.Rd | 41 ----- man/plotModalShiftSankey.Rd | 43 ----- man/plotTripCountByDepTime.Rd | 34 ---- man/plotTripDistancedByType.Rd | 30 ---- man/plotTripTypesPieChart.Rd | 21 --- 14 files changed, 255 insertions(+), 441 deletions(-) delete mode 100644 man/compareTripTypesBarChart.Rd delete mode 100644 man/plotActivityEndTimes.Rd delete mode 100644 man/plotArrivalTimesPerTripPurpose.Rd delete mode 100644 man/plotDepartureTimesPerTripPurpose.Rd delete mode 100644 man/plotMapWithFilteredTrips.Rd delete mode 100644 man/plotMapWithTrips.Rd delete mode 100644 man/plotMapWithTripsType.Rd delete mode 100644 man/plotModalShiftBar.Rd delete mode 100644 man/plotModalShiftSankey.Rd delete mode 100644 man/plotTripCountByDepTime.Rd delete mode 100644 man/plotTripDistancedByType.Rd delete mode 100644 man/plotTripTypesPieChart.Rd diff --git a/R/output_trips.R b/R/output_trips.R index d79a81d..f51fff4 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -596,20 +596,21 @@ plotTripDistanceByMode <- function(tripsTable, -#' Line plot with departure time x-axis and number of trips on y-axis +#' Deprecated function(s) in the matsimr package #' -#' Takes Table trips_output (from readTripsTable()), +#' \strong{plotTripCountByDepTime} - Takes Table trips_output (from readTripsTable()), #' to make line plot with with values that represent #' count of trips for a specific departure time by main_mode #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' +#' @rdname matsimr-deprecated #' #' @param tripsTable tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' @return Line Chart plot of trips count by departure mode per mode +#' @return \strong{plotTripCountByDepTime} - Line Chart plot of trips count by departure mode per mode #' #' @export plotTripCountByDepTime <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, @@ -669,21 +670,21 @@ plotTripCountByDepTime <- function(tripsTable, unite.columns = character(0), uni } } -#' Line plot that shows the number of activities ending at a given time, per activity type. -#' The activity end time is derived from the departure time in the given trips tibble. +#' Deprecated function(s) in the matsimr package #' -#' Takes Table trips_output (from readTripsTable()), +#' \strong{plotActivityEndTimes} - Takes Table trips_output (from readTripsTable()), #' to make line plot with with values that represent the #' number of activities ending at a specific time. #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' +#' @rdname matsimr-deprecated #' #' @param tripsTable tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' @return Line plot with departure time x-axis and number start activities on y-axis +#' @return \strong{plotActivityEndTimes} Line plot with departure time x-axis and number start activities on y-axis #' #' @export plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, @@ -747,14 +748,14 @@ plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), unite } -#' This function plots the number of trips ending per trip purpose over time. The trip purpose corresponds to the activity type of the destination activity of a given trip. -#' Thus, the y-axis of the plot can also be interpreted as the number of activities starting (based on the assumption that trip end time = activity start time). +#' Deprecated function(s) in the matsimr package #' -#' Takes Table trips_output (from readTripsTable()), +#' \strong{plotArrivalTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), #' to make line plot with with values that represent #' count of destination activities for a specific arrival time #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' +#' @rdname matsimr-deprecated #' #' @param tripsTable tibble of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns @@ -762,7 +763,7 @@ plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), unite #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' -#' @return Line plot with arrival time x-axis and number end activities on y-axis +#' @return \strong{plotArrivalTimesPerTripPurpose} - Line plot with arrival time x-axis and number end activities on y-axis #' #' @export plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, @@ -868,13 +869,14 @@ plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character } -#' This function plots the number of trips starting per trip purpose over time. The trip purpose corresponds to the activity type of the destination activity of a given trip. +#' Deprecated function(s) in the matsimr package #' -#' Takes Table trips_output (from readTripsTable()), +#' \strong{plotDepartureTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), #' to make line plot with with values that represent #' count of destination activities for a specific arrival time #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' +#' @rdname matsimr-deprecated #' #' @param tripsTable tibble of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns @@ -882,7 +884,7 @@ plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' -#' @return Line plot with arrival time x-axis and number end activities on y-axis +#' @return \strong{plotDepartureTimesPerTripPurpose} - Line plot with arrival time x-axis and number end activities on y-axis #' #' @export plotDepartureTimesPerTripPurpose <- function(tripsTable, unite.columns = character(0), united.name = "united", @@ -940,19 +942,20 @@ plotDepartureTimesPerTripPurpose <- function(tripsTable, unite.columns = charact } -#' Bar Chart with tripType on x-axis and travelled distance on y-axis +#' Deprecated function(s) in the matsimr package #' -#' Takes Table trips_output (from readTripsTable()), +#' \strong{plotTripDistancedByType} - Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' travelled distance of each tripType related to the shapeTable #' +#' @rdname matsimr-deprecated #' #' @param tripsTable tible of trips_output (from readTripsTable()) #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' -#' @return Bar Chart plot of distance traveled by type +#' @return \strong{plotTripDistancedByType} - Bar Chart plot of distance traveled by type #' #' @export plotTripDistancedByType <- function(tripsTable,shapeTable,crs,dump.output.to = matsimDumpOutputDirectory) { @@ -979,18 +982,19 @@ plotTripDistancedByType <- function(tripsTable,shapeTable,crs,dump.output.to = m -#' Plot alluvial/sankey diagram of transport mode changes +#' Deprecated function(s) in the matsimr package #' -#' Takes two trips_table (from readTripsTable), and collects +#' \strong{plotModalShiftSankey} - Takes two trips_table (from readTripsTable), and collects #' changes between transport mode distribution of these tables -#' to make alluvial diagram from this data -#' +#' to make alluvial diagram from this data\cr #' Function calculates number of each transport mode used in #' first and second table, and draws plot that represent how #' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) #' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") #' Using parameter show.onlyChanges #' +#' @rdname matsimr-deprecated +#' #' @param tripsTable1 tible of trips_output (from readTripsTable()) #' @param tripsTable2 tible of trips_output (from readTripsTable()) #' @param show.onlyChanges boolean, if it is set to TRUE => sankey diagram only contains changes on axes @@ -998,7 +1002,7 @@ plotTripDistancedByType <- function(tripsTable,shapeTable,crs,dump.output.to = m #' @param united.name if columns were united, you can specify name for the resulting column in plot #' @param dump.output.to folder that saves and configures yaml for simwrapper. folder where png of plot is stored #' -#' @return Alluvial diagram that represents changes in transport mode distribution of trip tables +#' @return \strong{plotModalShiftSankey} - Alluvial diagram that represents changes in transport mode distribution of trip tables #' #' @export plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FALSE, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory) { @@ -1048,25 +1052,24 @@ plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FA return(plt) } -#' Plot bar chart diagram of transport mode changes +#' Deprecated function(s) in the matsimr package #' -#' Takes two trips_table (from readTripsTable), and collects +#' \strong{plotModalShiftBar} - Takes two trips_table (from readTripsTable), and collects #' changes between transport mode distribution of these tables -#' to make bar chart diagram with dodging positioning from this data -#' +#' to make bar chart diagram with dodging positioning from this data\cr #' Function calculates number of each transport mode used in #' first and second table, and draws plot that represent how #' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) #' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") #' Using parameter show.onlyChanges -#' +#' @rdname matsimr-deprecated #' @param tripsTable1 tible of trips_output (from readTripsTable()) #' @param tripsTable2 tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name if columns were united, you can specify name for the resulting column in plot #' @param dump.output.to folder that saves and configures yaml for simwrapper. folder where png of plot is stored #' -#' @return plots Bar Chart of transport mode changes with additional files for simwrapper +#' @return \strong{plotModalShiftBar} - plots Bar Chart of transport mode changes with additional files for simwrapper #' #' @export plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, @@ -1094,17 +1097,18 @@ plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = characte -#' Plots result of filtered trips on the map (from shape) +#' Deprecated function(s) in the matsimr package #' -#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file)) +#' \strong{plotMapWithFilteredTrips} - Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file)) #' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -#' and filters the trips from table depending on *.inshape flags: +#' and filters the trips from table depending on *.inshape flags:\cr #' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape -#' result of filtering is plotted on map of shapeTable where green points are startpoints of trip and red points are endpoints of trip +#' \cr if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +#' \cr if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +#' \cr if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +#' \cr result of filtering is plotted on map of shapeTable where green points are startpoints of trip and red points are endpoints of trip #' +#' @rdname matsimr-deprecated #' @param table tibble of trips_output (from readTripsTable()) #' #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) @@ -1118,7 +1122,7 @@ plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = characte #' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot #' #' -#' @return plot with trips filtered depending on flags *.inshape on map from shapeTable +#' @return \strong{plotMapWithFilteredTrips} - plot with trips filtered depending on flags *.inshape on map from shapeTable #' #' @export plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRUE, end.inshape = TRUE, optimized = FALSE) { @@ -1250,8 +1254,11 @@ plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRU return(plt) } -#' Plots start and end coordinates of the given trips table on an osm map + +#' Deprecated function(s) in the matsimr package #' +#' \strong{plotMapWithTrips} - Plots start and end coordinates of the given trips table on an osm map +#' @rdname matsimr-deprecated #' @param table tibble of trips_output (from readTripsTable()) #' #' @@ -1260,7 +1267,7 @@ plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRU #' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot #' #' -#' @return plot with trips +#' @return \strong{plotMapWithTrips} - plot with trips #' #' @export plotMapWithTrips <- function(table, crs, optimized = FALSE) { @@ -1377,9 +1384,11 @@ plotMapWithTrips <- function(table, crs, optimized = FALSE) { return(plt) } -#' Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart +#' Deprecated function(s) in the matsimr package #' +#' \strong{plotTripTypesPieChart} - plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart #' +#' @rdname matsimr-deprecated #' #' @param table tibble of trips_output (from readTripsTable()) #' @@ -1389,7 +1398,7 @@ plotMapWithTrips <- function(table, crs, optimized = FALSE) { #' #' #' -#' @return plot with percentage of each type of trips +#' @return \strong{plotTripTypesPieChart} - plot with percentage of each type of trips #' #' @export plotTripTypesPieChart <- function(table, shapeTable, crs) { @@ -1433,10 +1442,13 @@ plotTripTypesPieChart <- function(table, shapeTable, crs) { ggtitle("Distribution")) } -#' Creates BarChart of changing trip types(originating,transit etc) between 2 tables -#' and saves output to dump.output.to + +#' Deprecated function(s) in the matsimr package #' +#' \strong{compareTripTypesBarChart} - Creates BarChart of changing trip types(originating,transit etc) between 2 tables +#' and saves output to dump.output.to #' +#' @rdname matsimr-deprecated #' #' @param tripsTable1 tibble of trips_output (from readTripsTable(),f.e. base case) #' @@ -1449,7 +1461,7 @@ plotTripTypesPieChart <- function(table, shapeTable, crs) { #' @param dump.output.to folder that saves resulting image of BarChart #' #' -#' @return plot with percentage of each type of trips between 2 tables +#' @return \strong{compareTripTypesBarChart} - plot with percentage of each type of trips between 2 tables #' #' @export compareTripTypesBarChart <- function(tripsTable1,tripsTable2,shapeTable,crs,dump.output.to = matsimDumpOutputDirectory){ @@ -1493,9 +1505,12 @@ compareTripTypesBarChart <- function(tripsTable1,tripsTable2,shapeTable,crs,dump } -#' Plots every type of trips(inside, outside, origin and destinating) on map + +#' Deprecated function(s) in the matsimr package #' +#' \strong{plotMapWithTripsType} - plots every type of trips(inside, outside, origin and destinating) on map #' +#' @rdname matsimr-deprecated #' #' @param table tibble of trips_output (from readTripsTable()) #' @@ -1505,7 +1520,7 @@ compareTripTypesBarChart <- function(tripsTable1,tripsTable2,shapeTable,crs,dump #' #' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot #' -#' @return plot that contains every trip with defined trip type +#' @return \strong{plotMapWithTripsType} - plot that contains every trip with defined trip type #' #' @export plotMapWithTripsType <- function(table, shapeTable, crs, optimized = FALSE) { diff --git a/man/compareTripTypesBarChart.Rd b/man/compareTripTypesBarChart.Rd deleted file mode 100644 index 9748a4f..0000000 --- a/man/compareTripTypesBarChart.Rd +++ /dev/null @@ -1,33 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{compareTripTypesBarChart} -\alias{compareTripTypesBarChart} -\title{Creates BarChart of changing trip types(originating,transit etc) between 2 tables -and saves output to dump.output.to} -\usage{ -compareTripTypesBarChart( - tripsTable1, - tripsTable2, - shapeTable, - crs, - dump.output.to = matsimDumpOutputDirectory -) -} -\arguments{ -\item{tripsTable1}{tibble of trips_output (from readTripsTable(),f.e. base case)} - -\item{tripsTable2}{tibble of trips_output (from readTripsTable(),f.e. policy case)} - -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} - -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} - -\item{dump.output.to}{folder that saves resulting image of BarChart} -} -\value{ -plot with percentage of each type of trips between 2 tables -} -\description{ -Creates BarChart of changing trip types(originating,transit etc) between 2 tables -and saves output to dump.output.to -} diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 2515857..1700b52 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -11,6 +11,18 @@ \alias{plotModalDistanceDistribution} \alias{compareModalDistanceDistribution} \alias{plotTripDistanceByMode} +\alias{plotTripCountByDepTime} +\alias{plotActivityEndTimes} +\alias{plotArrivalTimesPerTripPurpose} +\alias{plotDepartureTimesPerTripPurpose} +\alias{plotTripDistancedByType} +\alias{plotModalShiftSankey} +\alias{plotModalShiftBar} +\alias{plotMapWithFilteredTrips} +\alias{plotMapWithTrips} +\alias{plotTripTypesPieChart} +\alias{compareTripTypesBarChart} +\alias{plotMapWithTripsType} \alias{appendDistanceCategory} \title{Deprecated function(s) in the matsimr package} \usage{ @@ -74,16 +86,96 @@ plotTripDistanceByMode( only.files = FALSE ) +plotTripCountByDepTime( + tripsTable, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + only.files = FALSE +) + +plotActivityEndTimes( + tripsTable, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + only.files = FALSE +) + +plotArrivalTimesPerTripPurpose( + tripsTable, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + only.files = FALSE +) + +plotDepartureTimesPerTripPurpose( + tripsTable, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + only.files = FALSE +) + +plotTripDistancedByType( + tripsTable, + shapeTable, + crs, + dump.output.to = matsimDumpOutputDirectory +) + +plotModalShiftSankey( + tripsTable1, + tripsTable2, + show.onlyChanges = FALSE, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory +) + +plotModalShiftBar( + tripsTable1, + tripsTable2, + unite.columns = character(0), + united.name = "united", + dump.output.to = matsimDumpOutputDirectory, + output.name = "modalShiftBarChart" +) + +plotMapWithFilteredTrips( + table, + shapeTable, + crs, + start.inshape = TRUE, + end.inshape = TRUE, + optimized = FALSE +) + +plotMapWithTrips(table, crs, optimized = FALSE) + +plotTripTypesPieChart(table, shapeTable, crs) + +compareTripTypesBarChart( + tripsTable1, + tripsTable2, + shapeTable, + crs, + dump.output.to = matsimDumpOutputDirectory +) + +plotMapWithTripsType(table, shapeTable, crs, optimized = FALSE) + appendDistanceCategory(tripsTable) } \arguments{ \item{tripsTable}{tible of trips_output (from readTripsTable())} -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{unite.columns}{vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +\item{united.name}{if columns were united, you can specify name for the resulting column in plot} -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} +\item{dump.output.to}{folder that saves resulting image of BarChart} \item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} @@ -91,9 +183,23 @@ appendDistanceCategory(tripsTable) \item{n_max}{integer, maximum number of lines to read within output_trips} -\item{tripsTable1}{tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1} +\item{tripsTable1}{tibble of trips_output (from readTripsTable(),f.e. base case)} + +\item{tripsTable2}{tibble of trips_output (from readTripsTable(),f.e. policy case)} + +\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} + +\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} -\item{tripsTable2}{tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted} +\item{show.onlyChanges}{boolean, if it is set to TRUE => sankey diagram only contains changes on axes} + +\item{table}{tibble of trips_output (from readTripsTable())} + +\item{start.inshape}{bool, defines trips to conclude (see Description)} + +\item{end.inshape}{bool, defines trips to conclude (see Description)} + +\item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot} } \value{ \strong{plotModalSplitPieChart} - Pie Chart plot of transport mode distribution, values given in percents @@ -109,6 +215,30 @@ appendDistanceCategory(tripsTable) \strong{compareModalDistanceDistribution} - Bar Chart plot of count of trips among distance travelled \strong{plotTripDistanceByMode} - Bar Chart plot of distance traveled per mode + +\strong{plotTripCountByDepTime} - Line Chart plot of trips count by departure mode per mode + +\strong{plotActivityEndTimes} Line plot with departure time x-axis and number start activities on y-axis + +\strong{plotArrivalTimesPerTripPurpose} - Line plot with arrival time x-axis and number end activities on y-axis + +\strong{plotDepartureTimesPerTripPurpose} - Line plot with arrival time x-axis and number end activities on y-axis + +\strong{plotTripDistancedByType} - Bar Chart plot of distance traveled by type + +\strong{plotModalShiftSankey} - Alluvial diagram that represents changes in transport mode distribution of trip tables + +\strong{plotModalShiftBar} - plots Bar Chart of transport mode changes with additional files for simwrapper + +\strong{plotMapWithFilteredTrips} - plot with trips filtered depending on flags *.inshape on map from shapeTable + +\strong{plotMapWithTrips} - plot with trips + +\strong{plotTripTypesPieChart} - plot with percentage of each type of trips + +\strong{compareTripTypesBarChart} - plot with percentage of each type of trips between 2 tables + +\strong{plotMapWithTripsType} - plot that contains every trip with defined trip type } \description{ These functions are provided for compatibility with older version of @@ -145,6 +275,66 @@ Using parameters unite.columns, specific columns could be given, to unite them i to plot bar chart with with values that represent average distance traveled ~ main mode used Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') + +\strong{plotTripCountByDepTime} - Takes Table trips_output (from readTripsTable()), +to make line plot with with values that represent +count of trips for a specific departure time by main_mode +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') + +\strong{plotActivityEndTimes} - Takes Table trips_output (from readTripsTable()), +to make line plot with with values that represent the +number of activities ending at a specific time. +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') + +\strong{plotArrivalTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), +to make line plot with with values that represent +count of destination activities for a specific arrival time +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') + +\strong{plotDepartureTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), +to make line plot with with values that represent +count of destination activities for a specific arrival time +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') + +\strong{plotTripDistancedByType} - Takes Table trips_output (from readTripsTable()), +to plot bar chart with with values that represent +travelled distance of each tripType related to the shapeTable + +\strong{plotModalShiftSankey} - Takes two trips_table (from readTripsTable), and collects +changes between transport mode distribution of these tables +to make alluvial diagram from this data\cr +Function calculates number of each transport mode used in +first and second table, and draws plot that represent how +distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) +Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") +Using parameter show.onlyChanges + +\strong{plotModalShiftBar} - Takes two trips_table (from readTripsTable), and collects +changes between transport mode distribution of these tables +to make bar chart diagram with dodging positioning from this data\cr +Function calculates number of each transport mode used in +first and second table, and draws plot that represent how +distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) +Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") +Using parameter show.onlyChanges + +\strong{plotMapWithFilteredTrips} - Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file)) +transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +and filters the trips from table depending on *.inshape flags:\cr +if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape +\cr if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +\cr if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +\cr if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +\cr result of filtering is plotted on map of shapeTable where green points are startpoints of trip and red points are endpoints of trip + +\strong{plotMapWithTrips} - Plots start and end coordinates of the given trips table on an osm map + +\strong{plotTripTypesPieChart} - plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart + +\strong{compareTripTypesBarChart} - Creates BarChart of changing trip types(originating,transit etc) between 2 tables +and saves output to dump.output.to + +\strong{plotMapWithTripsType} - plots every type of trips(inside, outside, origin and destinating) on map } \section{Details}{ diff --git a/man/plotActivityEndTimes.Rd b/man/plotActivityEndTimes.Rd deleted file mode 100644 index 9a3b92b..0000000 --- a/man/plotActivityEndTimes.Rd +++ /dev/null @@ -1,35 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{plotActivityEndTimes} -\alias{plotActivityEndTimes} -\title{Line plot that shows the number of activities ending at a given time, per activity type. -The activity end time is derived from the departure time in the given trips tibble.} -\usage{ -plotActivityEndTimes( - tripsTable, - unite.columns = character(0), - united.name = "united", - dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE -) -} -\arguments{ -\item{tripsTable}{tible of trips_output (from readTripsTable())} - -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} - -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} - -\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} -} -\value{ -Line plot with departure time x-axis and number start activities on y-axis -} -\description{ -Takes Table trips_output (from readTripsTable()), -to make line plot with with values that represent the -number of activities ending at a specific time. -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -} diff --git a/man/plotArrivalTimesPerTripPurpose.Rd b/man/plotArrivalTimesPerTripPurpose.Rd deleted file mode 100644 index 629cb8f..0000000 --- a/man/plotArrivalTimesPerTripPurpose.Rd +++ /dev/null @@ -1,35 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{plotArrivalTimesPerTripPurpose} -\alias{plotArrivalTimesPerTripPurpose} -\title{This function plots the number of trips ending per trip purpose over time. The trip purpose corresponds to the activity type of the destination activity of a given trip. -Thus, the y-axis of the plot can also be interpreted as the number of activities starting (based on the assumption that trip end time = activity start time).} -\usage{ -plotArrivalTimesPerTripPurpose( - tripsTable, - unite.columns = character(0), - united.name = "united", - dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE -) -} -\arguments{ -\item{tripsTable}{tibble of trips_output (from readTripsTable())} - -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} - -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in plot} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} - -\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} -} -\value{ -Line plot with arrival time x-axis and number end activities on y-axis -} -\description{ -Takes Table trips_output (from readTripsTable()), -to make line plot with with values that represent -count of destination activities for a specific arrival time -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -} diff --git a/man/plotDepartureTimesPerTripPurpose.Rd b/man/plotDepartureTimesPerTripPurpose.Rd deleted file mode 100644 index a6f0c6f..0000000 --- a/man/plotDepartureTimesPerTripPurpose.Rd +++ /dev/null @@ -1,34 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{plotDepartureTimesPerTripPurpose} -\alias{plotDepartureTimesPerTripPurpose} -\title{This function plots the number of trips starting per trip purpose over time. The trip purpose corresponds to the activity type of the destination activity of a given trip.} -\usage{ -plotDepartureTimesPerTripPurpose( - tripsTable, - unite.columns = character(0), - united.name = "united", - dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE -) -} -\arguments{ -\item{tripsTable}{tibble of trips_output (from readTripsTable())} - -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} - -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in plot} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} - -\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} -} -\value{ -Line plot with arrival time x-axis and number end activities on y-axis -} -\description{ -Takes Table trips_output (from readTripsTable()), -to make line plot with with values that represent -count of destination activities for a specific arrival time -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -} diff --git a/man/plotMapWithFilteredTrips.Rd b/man/plotMapWithFilteredTrips.Rd deleted file mode 100644 index 2712476..0000000 --- a/man/plotMapWithFilteredTrips.Rd +++ /dev/null @@ -1,41 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{plotMapWithFilteredTrips} -\alias{plotMapWithFilteredTrips} -\title{Plots result of filtered trips on the map (from shape)} -\usage{ -plotMapWithFilteredTrips( - table, - shapeTable, - crs, - start.inshape = TRUE, - end.inshape = TRUE, - optimized = FALSE -) -} -\arguments{ -\item{table}{tibble of trips_output (from readTripsTable())} - -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} - -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} - -\item{start.inshape}{bool, defines trips to conclude (see Description)} - -\item{end.inshape}{bool, defines trips to conclude (see Description)} - -\item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot} -} -\value{ -plot with trips filtered depending on flags *.inshape on map from shapeTable -} -\description{ -Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file)) -transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -and filters the trips from table depending on *.inshape flags: -if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape -result of filtering is plotted on map of shapeTable where green points are startpoints of trip and red points are endpoints of trip -} diff --git a/man/plotMapWithTrips.Rd b/man/plotMapWithTrips.Rd deleted file mode 100644 index aab27d7..0000000 --- a/man/plotMapWithTrips.Rd +++ /dev/null @@ -1,21 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{plotMapWithTrips} -\alias{plotMapWithTrips} -\title{Plots start and end coordinates of the given trips table on an osm map} -\usage{ -plotMapWithTrips(table, crs, optimized = FALSE) -} -\arguments{ -\item{table}{tibble of trips_output (from readTripsTable())} - -\item{crs}{numeric representation of the EPSG code or proj4string for the corresponding coordinate system of the trip coordinates, can be found in network file from output directory of MATSim simulation} - -\item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot} -} -\value{ -plot with trips -} -\description{ -Plots start and end coordinates of the given trips table on an osm map -} diff --git a/man/plotMapWithTripsType.Rd b/man/plotMapWithTripsType.Rd deleted file mode 100644 index 87814b0..0000000 --- a/man/plotMapWithTripsType.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{plotMapWithTripsType} -\alias{plotMapWithTripsType} -\title{Plots every type of trips(inside, outside, origin and destinating) on map} -\usage{ -plotMapWithTripsType(table, shapeTable, crs, optimized = FALSE) -} -\arguments{ -\item{table}{tibble of trips_output (from readTripsTable())} - -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} - -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} - -\item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot} -} -\value{ -plot that contains every trip with defined trip type -} -\description{ -Plots every type of trips(inside, outside, origin and destinating) on map -} diff --git a/man/plotModalShiftBar.Rd b/man/plotModalShiftBar.Rd deleted file mode 100644 index 460d9c2..0000000 --- a/man/plotModalShiftBar.Rd +++ /dev/null @@ -1,41 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{plotModalShiftBar} -\alias{plotModalShiftBar} -\title{Plot bar chart diagram of transport mode changes} -\usage{ -plotModalShiftBar( - tripsTable1, - tripsTable2, - unite.columns = character(0), - united.name = "united", - dump.output.to = matsimDumpOutputDirectory, - output.name = "modalShiftBarChart" -) -} -\arguments{ -\item{tripsTable1}{tible of trips_output (from readTripsTable())} - -\item{tripsTable2}{tible of trips_output (from readTripsTable())} - -\item{unite.columns}{vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} - -\item{united.name}{if columns were united, you can specify name for the resulting column in plot} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper. folder where png of plot is stored} -} -\value{ -plots Bar Chart of transport mode changes with additional files for simwrapper -} -\description{ -Takes two trips_table (from readTripsTable), and collects -changes between transport mode distribution of these tables -to make bar chart diagram with dodging positioning from this data -} -\details{ -Function calculates number of each transport mode used in -first and second table, and draws plot that represent how -distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) -Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") -Using parameter show.onlyChanges -} diff --git a/man/plotModalShiftSankey.Rd b/man/plotModalShiftSankey.Rd deleted file mode 100644 index bbc87f2..0000000 --- a/man/plotModalShiftSankey.Rd +++ /dev/null @@ -1,43 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{plotModalShiftSankey} -\alias{plotModalShiftSankey} -\title{Plot alluvial/sankey diagram of transport mode changes} -\usage{ -plotModalShiftSankey( - tripsTable1, - tripsTable2, - show.onlyChanges = FALSE, - unite.columns = character(0), - united.name = "united", - dump.output.to = matsimDumpOutputDirectory -) -} -\arguments{ -\item{tripsTable1}{tible of trips_output (from readTripsTable())} - -\item{tripsTable2}{tible of trips_output (from readTripsTable())} - -\item{show.onlyChanges}{boolean, if it is set to TRUE => sankey diagram only contains changes on axes} - -\item{unite.columns}{vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} - -\item{united.name}{if columns were united, you can specify name for the resulting column in plot} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper. folder where png of plot is stored} -} -\value{ -Alluvial diagram that represents changes in transport mode distribution of trip tables -} -\description{ -Takes two trips_table (from readTripsTable), and collects -changes between transport mode distribution of these tables -to make alluvial diagram from this data -} -\details{ -Function calculates number of each transport mode used in -first and second table, and draws plot that represent how -distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) -Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") -Using parameter show.onlyChanges -} diff --git a/man/plotTripCountByDepTime.Rd b/man/plotTripCountByDepTime.Rd deleted file mode 100644 index 89f0329..0000000 --- a/man/plotTripCountByDepTime.Rd +++ /dev/null @@ -1,34 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{plotTripCountByDepTime} -\alias{plotTripCountByDepTime} -\title{Line plot with departure time x-axis and number of trips on y-axis} -\usage{ -plotTripCountByDepTime( - tripsTable, - unite.columns = character(0), - united.name = "united", - dump.output.to = matsimDumpOutputDirectory, - only.files = FALSE -) -} -\arguments{ -\item{tripsTable}{tible of trips_output (from readTripsTable())} - -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} - -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} - -\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} -} -\value{ -Line Chart plot of trips count by departure mode per mode -} -\description{ -Takes Table trips_output (from readTripsTable()), -to make line plot with with values that represent -count of trips for a specific departure time by main_mode -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -} diff --git a/man/plotTripDistancedByType.Rd b/man/plotTripDistancedByType.Rd deleted file mode 100644 index 18d1c3c..0000000 --- a/man/plotTripDistancedByType.Rd +++ /dev/null @@ -1,30 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{plotTripDistancedByType} -\alias{plotTripDistancedByType} -\title{Bar Chart with tripType on x-axis and travelled distance on y-axis} -\usage{ -plotTripDistancedByType( - tripsTable, - shapeTable, - crs, - dump.output.to = matsimDumpOutputDirectory -) -} -\arguments{ -\item{tripsTable}{tible of trips_output (from readTripsTable())} - -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} - -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} -} -\value{ -Bar Chart plot of distance traveled by type -} -\description{ -Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -travelled distance of each tripType related to the shapeTable -} diff --git a/man/plotTripTypesPieChart.Rd b/man/plotTripTypesPieChart.Rd deleted file mode 100644 index 894363b..0000000 --- a/man/plotTripTypesPieChart.Rd +++ /dev/null @@ -1,21 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{plotTripTypesPieChart} -\alias{plotTripTypesPieChart} -\title{Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart} -\usage{ -plotTripTypesPieChart(table, shapeTable, crs) -} -\arguments{ -\item{table}{tibble of trips_output (from readTripsTable())} - -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} - -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} -} -\value{ -plot with percentage of each type of trips -} -\description{ -Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart -} From 8b12d89509ea015d1c3abe5ad7a2b41060fcafc2 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 22 Jun 2023 16:51:45 +0200 Subject: [PATCH 36/87] deprecated documentation is done --- R/output_trips.R | 59 +++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index f51fff4..5a777c1 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -1740,11 +1740,12 @@ plotMapWithTripsType <- function(table, shapeTable, crs, optimized = FALSE) { } - -#' Chooses a function to compare output_trips from the folders. -#' baseFolder contains all base outputs, policyFolder contains all policy outputs. +#' Deprecated function(s) in the matsimr package #' +#' \strong{compareBasePolicyOutput} - Chooses a function to compare output_trips from the folders. +#' baseFolder contains all base outputs, policyFolder contains all policy outputs. #' +#' @rdname matsimr-deprecated #' #' @param baseFolder specifies data source folder with multiple base output_trips #' @@ -1753,7 +1754,7 @@ plotMapWithTripsType <- function(table, shapeTable, crs, optimized = FALSE) { #' @param dump.output.to that saves result of all comparisons between each base and each policy. #' For now it creates plotModalShiftBar() for the output_trips #' -#' @return list of tibbles, list of all base and policy output_trips as tibble +#' @return \strong{compareBasePolicyOutput} - list of tibbles, list of all base and policy output_trips as tibble #' #' @export compareBasePolicyOutput <- function(baseFolder,policyFolder,dump.output.to = matsimDumpOutputDirectory) { @@ -1806,10 +1807,13 @@ compareBasePolicyOutput <- function(baseFolder,policyFolder,dump.output.to = mat } invisible(list(base = base_trips,policy = policy_trips)) } -#' Chooses a function to compare output_trips from the folders. -#' baseFolder contains all base outputs, policyFolder contains all policy outputs. + +#' Deprecated function(s) in the matsimr package #' +#' \strong{compareBasePolicyShapeOutput} - Chooses a function to compare output_trips from the folders. +#' baseFolder contains all base outputs, policyFolder contains all policy outputs. #' +#' @rdname matsimr-deprecated #' #' @param baseFolder specifies data source folder with multiple base output_trips #' @@ -1820,7 +1824,7 @@ compareBasePolicyOutput <- function(baseFolder,policyFolder,dump.output.to = mat #' @param dump.output.to that saves result of all comparisons between each base and each policy. #' For now it creates plotModalShiftBar() for the output_trips #' -#' @return list of tibbles, list of all base and policy output_trips as tibble +#' @return \strong{compareBasePolicyShapeOutput} - list of tibbles, list of all base and policy output_trips as tibble #' #' @export compareBasePolicyShapeOutput <- function(baseFolder,policyFolder,shapeFilePath,crs,dump.output.to = matsimDumpOutputDirectory) { @@ -1878,13 +1882,15 @@ compareBasePolicyShapeOutput <- function(baseFolder,policyFolder,shapeFilePath,c #' Deprecated function(s) in the matsimr package #' +#' \strong{appendDistanceCategory} - adds to trips output tibble additional column that represent distance as category #' #' @rdname matsimr-deprecated #' +#' @return tibble of output_trips with distance category column +#' #' @docType package -#' @export compareAverageTravelWait -#' @aliases compareAverageTravelWait #' +#' @export appendDistanceCategory <- function(tripsTable){ .Deprecated("process_append_distcat") @@ -1918,8 +1924,9 @@ appendDistanceCategory <- function(tripsTable){ return(tripsTable_result) } -#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape +#' Deprecated function(s) in the matsimr package #' +#' \strong{filterByRegion} - Filtering of trips_table(from readTripsTable) depending on how they located in given shape\cr #' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). #' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) #' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) @@ -1939,7 +1946,7 @@ appendDistanceCategory <- function(tripsTable){ #' #' @param end.inshape bool, defines trips to conclude (see Description) #' -#' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) +#' @return \strong{filterByRegion} - tibble, with filtered trips depending on shapeTable and special flags (see Description) #' #' @export filterByRegion <- function(tripsTable, @@ -1987,9 +1994,12 @@ filterByRegion <- function(tripsTable, } -#' Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper + +#' Deprecated function(s) in the matsimr package #' +#' \strong{deriveODMatrix} - Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper #' +#' @rdname matsimr-deprecated #' #' @param tripsTable table of output trips(from readTripsTable) or path to trips_output file #' @@ -2005,7 +2015,7 @@ filterByRegion <- function(tripsTable, #' #' @param outer logical that represent if the table should contain outside flow of the shape, it isn't #' -#' @return tibble of origin/destination matrix +#' @return \strong{deriveODMatrix} - tibble of origin/destination matrix #' #' @export deriveODMatrix<- function(tripsTable, @@ -2131,14 +2141,17 @@ deriveODMatrix<- function(tripsTable, return(result_tibble) } - -#' Reads an coordinate referenec system of MATSim output directory +#' Deprecated function(s) in the matsimr package +#' +#' \strong{getCrsFromConfig} - Reads an coordinate referenec system of MATSim output directory #' from output_config.xml #' +#' @rdname matsimr-deprecated +#' #' @param folder specifies path to find config #' #' -#' @return code of coordinate reference system +#' @return \strong{getCrsFromConfig} - code of coordinate reference system #' #' @export getCrsFromConfig <- function(folder) { @@ -2172,15 +2185,15 @@ getCrsFromConfig <- function(folder) { } -#' Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature) +#' Deprecated function(s) in the matsimr package #' +#' \strong{transformToSf} - Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature)\cr #' Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features -#' deletes from resulting data.frame start_x, end_x, start_y, end_y. -#' And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring() -#' Or adds start_wkt and end_wkt, if geometry.type = st_point() +#' deletes from resulting data.frame start_x, end_x, start_y, end_y.\cr +#' And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring()\cr +#' Or adds start_wkt and end_wkt, if geometry.type = st_point()\cr #' Added column/columns projected to given CRS (coordinate reference system), -#' that can be taken from network file of MATSimOutputDirectory -#' +#' that can be taken from network file of MATSimOutputDirectory\cr #' Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" #' to get which type of table was generated, if it is needed #' @@ -2193,7 +2206,7 @@ getCrsFromConfig <- function(folder) { #' !!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or #' !!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!! #' -#' @return sf object (data.frame with geometries depending to geometry.type) +#' @return \strong{transformToSf} - sf object (data.frame with geometries depending to geometry.type) #' #' @export transformToSf <- function(table, From df0bae28069a4ff501316f51ccd1ddc33b53de17 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 22 Jun 2023 16:54:35 +0200 Subject: [PATCH 37/87] first debug of documenttion --- NAMESPACE | 1 + man/compareBasePolicyOutput.Rd | 28 ----------- man/compareBasePolicyShapeOutput.Rd | 34 -------------- man/deriveODMatrix.Rd | 37 --------------- man/filterByRegion.Rd | 5 +- man/getCrsFromConfig.Rd | 19 -------- man/matsimr-deprecated.Rd | 73 ++++++++++++++++++++++++++++- man/transformToSf.Rd | 15 +++--- 8 files changed, 82 insertions(+), 130 deletions(-) delete mode 100644 man/compareBasePolicyOutput.Rd delete mode 100644 man/compareBasePolicyShapeOutput.Rd delete mode 100644 man/deriveODMatrix.Rd delete mode 100644 man/getCrsFromConfig.Rd diff --git a/NAMESPACE b/NAMESPACE index 2ef9525..72eeb90 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ # Generated by roxygen2: do not edit by hand +export(appendDistanceCategory) export(boxplotScoreDifferences) export(compareAverageTravelWait) export(compareBasePolicyOutput) diff --git a/man/compareBasePolicyOutput.Rd b/man/compareBasePolicyOutput.Rd deleted file mode 100644 index 16a1b0f..0000000 --- a/man/compareBasePolicyOutput.Rd +++ /dev/null @@ -1,28 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{compareBasePolicyOutput} -\alias{compareBasePolicyOutput} -\title{Chooses a function to compare output_trips from the folders. -baseFolder contains all base outputs, policyFolder contains all policy outputs.} -\usage{ -compareBasePolicyOutput( - baseFolder, - policyFolder, - dump.output.to = matsimDumpOutputDirectory -) -} -\arguments{ -\item{baseFolder}{specifies data source folder with multiple base output_trips} - -\item{policyFolder}{specifies data source folder with multiple policy output_trips} - -\item{dump.output.to}{that saves result of all comparisons between each base and each policy. -For now it creates plotModalShiftBar() for the output_trips} -} -\value{ -list of tibbles, list of all base and policy output_trips as tibble -} -\description{ -Chooses a function to compare output_trips from the folders. -baseFolder contains all base outputs, policyFolder contains all policy outputs. -} diff --git a/man/compareBasePolicyShapeOutput.Rd b/man/compareBasePolicyShapeOutput.Rd deleted file mode 100644 index a2afee6..0000000 --- a/man/compareBasePolicyShapeOutput.Rd +++ /dev/null @@ -1,34 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{compareBasePolicyShapeOutput} -\alias{compareBasePolicyShapeOutput} -\title{Chooses a function to compare output_trips from the folders. -baseFolder contains all base outputs, policyFolder contains all policy outputs.} -\usage{ -compareBasePolicyShapeOutput( - baseFolder, - policyFolder, - shapeFilePath, - crs, - dump.output.to = matsimDumpOutputDirectory -) -} -\arguments{ -\item{baseFolder}{specifies data source folder with multiple base output_trips} - -\item{policyFolder}{specifies data source folder with multiple policy output_trips} - -\item{shapeFilePath}{specifies shapeFile used for comparison} - -\item{crs}{numeric of EPSG code or proj4string, can be found in network/config file from output directory of MATSim simulation} - -\item{dump.output.to}{that saves result of all comparisons between each base and each policy. -For now it creates plotModalShiftBar() for the output_trips} -} -\value{ -list of tibbles, list of all base and policy output_trips as tibble -} -\description{ -Chooses a function to compare output_trips from the folders. -baseFolder contains all base outputs, policyFolder contains all policy outputs. -} diff --git a/man/deriveODMatrix.Rd b/man/deriveODMatrix.Rd deleted file mode 100644 index ef9f9fe..0000000 --- a/man/deriveODMatrix.Rd +++ /dev/null @@ -1,37 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{deriveODMatrix} -\alias{deriveODMatrix} -\title{Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper} -\usage{ -deriveODMatrix( - tripsTable, - shapePath, - crs, - dump.output.to = matsimDumpOutputDirectory, - simwrapper = FALSE, - colnames = "numeric", - outer = FALSE -) -} -\arguments{ -\item{tripsTable}{table of output trips(from readTripsTable) or path to trips_output file} - -\item{shapePath}{full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name)} - -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} - -\item{dump.output.to}{path to a folder to save csv file of ODMatrix} - -\item{simwrapper}{create output in a simwrapper form if set to path of the shapefile} - -\item{colnames}{if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values} - -\item{outer}{logical that represent if the table should contain outside flow of the shape, it isn't} -} -\value{ -tibble of origin/destination matrix -} -\description{ -Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper -} diff --git a/man/filterByRegion.Rd b/man/filterByRegion.Rd index d8677a3..9fc7348 100644 --- a/man/filterByRegion.Rd +++ b/man/filterByRegion.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/output_trips.R \name{filterByRegion} \alias{filterByRegion} -\title{Filtering of trips_table(from readTripsTable) depending on how they located in given shape} +\title{Deprecated function(s) in the matsimr package} \usage{ filterByRegion( tripsTable, @@ -24,9 +24,10 @@ filterByRegion( \item{end.inshape}{bool, defines trips to conclude (see Description)} } \value{ -tibble, with filtered trips depending on shapeTable and special flags (see Description) +\strong{filterByRegion} - tibble, with filtered trips depending on shapeTable and special flags (see Description) } \description{ +\strong{filterByRegion} - Filtering of trips_table(from readTripsTable) depending on how they located in given shape\cr Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). Please be aware that this filterByRegion currently only works, when one geometry is loaded.) transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) diff --git a/man/getCrsFromConfig.Rd b/man/getCrsFromConfig.Rd deleted file mode 100644 index 2401be7..0000000 --- a/man/getCrsFromConfig.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{getCrsFromConfig} -\alias{getCrsFromConfig} -\title{Reads an coordinate referenec system of MATSim output directory -from output_config.xml} -\usage{ -getCrsFromConfig(folder) -} -\arguments{ -\item{folder}{specifies path to find config} -} -\value{ -code of coordinate reference system -} -\description{ -Reads an coordinate referenec system of MATSim output directory -from output_config.xml -} diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 1700b52..f99d5b0 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -23,7 +23,11 @@ \alias{plotTripTypesPieChart} \alias{compareTripTypesBarChart} \alias{plotMapWithTripsType} +\alias{compareBasePolicyOutput} +\alias{compareBasePolicyShapeOutput} \alias{appendDistanceCategory} +\alias{deriveODMatrix} +\alias{getCrsFromConfig} \title{Deprecated function(s) in the matsimr package} \usage{ plotModalSplitPieChart( @@ -166,16 +170,42 @@ compareTripTypesBarChart( plotMapWithTripsType(table, shapeTable, crs, optimized = FALSE) +compareBasePolicyOutput( + baseFolder, + policyFolder, + dump.output.to = matsimDumpOutputDirectory +) + +compareBasePolicyShapeOutput( + baseFolder, + policyFolder, + shapeFilePath, + crs, + dump.output.to = matsimDumpOutputDirectory +) + appendDistanceCategory(tripsTable) + +deriveODMatrix( + tripsTable, + shapePath, + crs, + dump.output.to = matsimDumpOutputDirectory, + simwrapper = FALSE, + colnames = "numeric", + outer = FALSE +) + +getCrsFromConfig(folder) } \arguments{ -\item{tripsTable}{tible of trips_output (from readTripsTable())} +\item{tripsTable}{table of output trips(from readTripsTable) or path to trips_output file} \item{unite.columns}{vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} \item{united.name}{if columns were united, you can specify name for the resulting column in plot} -\item{dump.output.to}{folder that saves resulting image of BarChart} +\item{dump.output.to}{path to a folder to save csv file of ODMatrix} \item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} @@ -200,6 +230,22 @@ appendDistanceCategory(tripsTable) \item{end.inshape}{bool, defines trips to conclude (see Description)} \item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot} + +\item{baseFolder}{specifies data source folder with multiple base output_trips} + +\item{policyFolder}{specifies data source folder with multiple policy output_trips} + +\item{shapeFilePath}{specifies shapeFile used for comparison} + +\item{shapePath}{full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name)} + +\item{simwrapper}{create output in a simwrapper form if set to path of the shapefile} + +\item{colnames}{if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values} + +\item{outer}{logical that represent if the table should contain outside flow of the shape, it isn't} + +\item{folder}{specifies path to find config} } \value{ \strong{plotModalSplitPieChart} - Pie Chart plot of transport mode distribution, values given in percents @@ -239,6 +285,16 @@ appendDistanceCategory(tripsTable) \strong{compareTripTypesBarChart} - plot with percentage of each type of trips between 2 tables \strong{plotMapWithTripsType} - plot that contains every trip with defined trip type + +\strong{compareBasePolicyOutput} - list of tibbles, list of all base and policy output_trips as tibble + +\strong{compareBasePolicyShapeOutput} - list of tibbles, list of all base and policy output_trips as tibble + +tibble of output_trips with distance category column + +\strong{deriveODMatrix} - tibble of origin/destination matrix + +\strong{getCrsFromConfig} - code of coordinate reference system } \description{ These functions are provided for compatibility with older version of @@ -335,6 +391,19 @@ if start.inshape = TRUE & end.inshape = TRUE return table that contains trips in and saves output to dump.output.to \strong{plotMapWithTripsType} - plots every type of trips(inside, outside, origin and destinating) on map + +\strong{compareBasePolicyOutput} - Chooses a function to compare output_trips from the folders. +baseFolder contains all base outputs, policyFolder contains all policy outputs. + +\strong{compareBasePolicyShapeOutput} - Chooses a function to compare output_trips from the folders. +baseFolder contains all base outputs, policyFolder contains all policy outputs. + +\strong{appendDistanceCategory} - adds to trips output tibble additional column that represent distance as category + +\strong{deriveODMatrix} - Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper + +\strong{getCrsFromConfig} - Reads an coordinate referenec system of MATSim output directory +from output_config.xml } \section{Details}{ diff --git a/man/transformToSf.Rd b/man/transformToSf.Rd index 3a4f6c6..74eb5cf 100644 --- a/man/transformToSf.Rd +++ b/man/transformToSf.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/output_trips.R \name{transformToSf} \alias{transformToSf} -\title{Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature)} +\title{Deprecated function(s) in the matsimr package} \usage{ transformToSf(table, crs, geometry.type = st_multipoint()) } @@ -17,17 +17,16 @@ transformToSf(table, crs, geometry.type = st_multipoint()) !!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!!} } \value{ -sf object (data.frame with geometries depending to geometry.type) +\strong{transformToSf} - sf object (data.frame with geometries depending to geometry.type) } \description{ +\strong{transformToSf} - Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature)\cr Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features -deletes from resulting data.frame start_x, end_x, start_y, end_y. -And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring() -Or adds start_wkt and end_wkt, if geometry.type = st_point() +deletes from resulting data.frame start_x, end_x, start_y, end_y.\cr +And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring()\cr +Or adds start_wkt and end_wkt, if geometry.type = st_point()\cr Added column/columns projected to given CRS (coordinate reference system), -that can be taken from network file of MATSimOutputDirectory -} -\details{ +that can be taken from network file of MATSimOutputDirectory\cr Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" to get which type of table was generated, if it is needed } From 0be95909a68b1a8ea2eb1a3f17f8b2678bdf36ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Mon, 26 Jun 2023 13:34:30 +0200 Subject: [PATCH 38/87] WIP first batch of documentation ready to merge --- R/counts.R | 52 +- R/network.R | 24 +- R/output_trips.R | 1625 ++++++++++++++++++++++++++++++++-------------- R/simwrapper.R | 32 +- 4 files changed, 1202 insertions(+), 531 deletions(-) diff --git a/R/counts.R b/R/counts.R index f386707..84aa58a 100644 --- a/R/counts.R +++ b/R/counts.R @@ -8,14 +8,14 @@ #' #'@title Load a MATSim Counts file into memory #' -#'@description Loads a MATSim Counts XML-File as tibble into memory#' +#'@description Loads a MATSim Counts XML-file as tibble into memory +#' #' #'@param file File to load. Must be an .xml file #' #'@return tibble with MATSim link id ("loc_id") as key #' #'@export -#' readCounts <- function(file){ message = paste("Read counts file from", file) @@ -51,9 +51,6 @@ readCounts <- function(file){ result } -# XXXX - why tsv file when it's supposed to be comma separated? is this a standard MATSim output? -# XXXX - what are time bins? qsim mode? are they supposed to be parameters? how are they provided? - #' Load a MATSim linkstats file into memory #' #' Loads a linkstats tsv file created from the LinkStats class @@ -80,7 +77,7 @@ readLinkStats <- function(runId, file, sampleSize = 0.25){ return(NA) } - message <- paste("Read link stats from run", runId, ". Loading data from", file ) + message <- paste("Read in link stats from run", runId, ". Loading data from", file ) print(message) linkstats <- readr::read_csv(file = file) @@ -110,13 +107,7 @@ readLinkStats <- function(runId, file, sampleSize = 0.25){ } -#XXXX why is linkstats a list? in the other function we create a tibble, no? -#XXXX can this be done without linkstats or is that a different function? -#XXXX in error message it says network needs to be a list, in description a vector? - - #' Join counts and linkstats to the network, creating a tibble into memory -#' //Load Counts, a limited number of Linkstats and Network links as joined tibble into memory #' #'Function to join counts, linkstats and network links. Data can be aggregated #'and filtered by time or mode. @@ -128,13 +119,13 @@ readLinkStats <- function(runId, file, sampleSize = 0.25){ #' #'@param linkStats List with linkstats tibbles #' -#'@param networkModes a vector with network modes that will be analyzed, default is "car". +#'@param networkModes Vector with network modes that will be analyzed, default is "car". #' #'@param aggr_to Determines if data should be aggregated into hourly bins or as daily traffic volume, can either be "day" or "hour" #' -#'@param earliest Lower limit to filter link stats by time, default is 0. +#'@param earliest Integer. Lower limit to filter link stats by time, default = 0. #' -#'@param latest Upper limit to filter link stats by time, default is 86400 (midnight). +#'@param latest Integer. Upper limit to filter link stats by time, default = 86400 (midnight). #' #'@return Long-format tibble with MATSim link id as key ("loc_id"), traffic volumes from MATSim runs and link type #' @@ -251,7 +242,7 @@ mergeCountsAndLinks <- function(counts, network, linkStats, networkModes = c("ca join.long } -#' Group daily traffic volume (DTV) +#' Categorize daily traffic volume (DTV) and calculate DTV for different link types. #' #' Takes a tibble from mergeCountsAndLinks. DTV is categorized into bins. Finally #' data is aggregated to calculate DTV distribution in each link type category, @@ -261,13 +252,13 @@ mergeCountsAndLinks <- function(counts, network, linkStats, networkModes = c("ca #' #' @param joinedFrame A tibble from mergeCountsAndLinks #' -#' @param from Lower limit for count bin +#' @param from Integer. Lower limit for count bin, default = 0. #' -#' @param to Upper limit for count bins +#' @param to Integer. Upper limit for count bins, default = 40000. #' -#' @param by Size of each count bin +#' @param by Integer. Size of each count bin, default = 5000. #' -#' @return A long-format tibble which contains share of DTV Categories +#' @return A long-format tibble which contains share of DTV for link types #' #' @export processLinkStatsDtvDistribution <- function(joinedFrame, from = 0, to = 40000, by = 5000){ @@ -320,17 +311,16 @@ processLinkStatsDtvDistribution <- function(joinedFrame, from = 0, to = 40000, b #' Categorize DTV deviation and aggregate data #' #' Takes a tibble from mergeCountsAndLinks. -#' Deviation between count volumes and Linkstats is calculated -#' (e.g. deviation of 1.2 means 20 percent more DTV in MATSim than in counts) and -#' categorized. +#' Deviation between count volumes and Linkstats is calculated and +#' categorized (i.e. deviation of 1.2 means 20 percent more DTV in MATSim than in counts). #' If parameter 'aggr' is set to TRUE, data will be aggregated for each run and link type. #' Can be used to visualize model quality by link type and to compare several runs. #' -#' Estimation quality is determinated by the 'cut' function, limits for the label -#' 'exact' can be adjusted by tuning the parameter 'll' and 'ul' +#' Estimation quality is determined by the 'cut' function, limits for the label +#' 'exact' can be adjusted by tuning the parameters 'll' (lower limit) and 'ul' (upper limit) #' #' @param joinedFrame A tibble from mergeCountsAndLinks -#' @param aggr Boolean, if categorized data should returned aggregated +#' @param aggr Boolean, if categorized data should returned aggregated, default is TRUE. #' @param ll Formula to calculate lower limit of the quality label 'exact', default = 0.8*x - 200 #' @param ul Formula to calculate lower limit of the quality label 'exact', default = 1.2*x + 200 #' @@ -350,8 +340,8 @@ processDtvEstimationQuality <- function(joinedFrame, aggr = TRUE, ll = ~ x *0.8 join.1 <- joinedFrame %>% mutate(ll = ifelse(ll < 0, 0, ll), estimation = ifelse(volume < ll, "less", - ifelse(volume > ul, "more", - "exact")), + ifelse(volume > ul, "more", + "exact")), estimation = factor(estimation, levels = c("less", "exact", "more"))) if(aggr){ @@ -370,12 +360,12 @@ processDtvEstimationQuality <- function(joinedFrame, aggr = TRUE, ll = ~ x *0.8 #' Creates a Via-Style scatterplot for each run #' #' Takes a tibble from mergeCountsAndLinks. -#' A scatterplot with counts on the x axis and matsim dtv on the y axis is created and colored +#' A scatterplot with counts on the x axis and MATSim dtv on the y axis is created and colored #' by the road type. -#' Lower and upper Limits define the section which is considered as an 'exact' estimation. Limits +#' Lower and upper limits define the section which is considered an 'exact' estimation. Limits #' are defined by custom formulas. #' -#' The function calls the matsim-r function processDtvEstimationQuality which is handeling the limits. +#' The function calls the matsim-r function processDtvEstimationQuality which is handling the limits. #' #' @param joinedFrame A tibble from mergeCountsAndLinks #' @param ll Formula to calculate lower limit of the quality label 'exact', default = 0.8*x - 200 diff --git a/R/network.R b/R/network.R index f2313de..53a556f 100644 --- a/R/network.R +++ b/R/network.R @@ -45,7 +45,7 @@ utils::globalVariables(c("name")) #' additional columns in the respective node and link tibbles. #' #' The links table is automatically joined with the nodes table so that -#' node x/y coordinates (and any other node attributes) are available on the +#' node x/y coordinates (and any other node attributes) are available in the #' links table without additional processing. #' #' @param filename File to load. Can be XML or gzipped XML @@ -85,9 +85,9 @@ read_network <- function(filename) { # convert to a format we can join to the links nodeAttributes <- (nodeAttributes - %>% select(-class) - %>% pivot_wider(names_from = "name", values_from = "value") - %>% mutate_at(vars(one_of(convert)), as.double) + %>% select(-class) + %>% pivot_wider(names_from = "name", values_from = "value") + %>% mutate_at(vars(one_of(convert)), as.double) ) nodes <- nodes %>% left_join(nodeAttributes, by = "id") } @@ -108,8 +108,8 @@ read_network <- function(filename) { # merge node coordinates links <- (links - %>% left_join(nodes, by = c("from" = "id")) - %>% left_join(nodes, by = c("to" = "id"), suffix = c(".from", ".to")) + %>% left_join(nodes, by = c("from" = "id")) + %>% left_join(nodes, by = c("to" = "id"), suffix = c(".from", ".to")) ) # attributes don't have IDs on them! JFC, MATSim! @@ -135,9 +135,9 @@ read_network <- function(filename) { # convert to a format we can join to the links linkAttributes <- (linkAttributes - %>% select(-class) - %>% pivot_wider(names_from = "name", values_from = "value") - %>% mutate_at(vars(one_of(convert)), as.double) + %>% select(-class) + %>% pivot_wider(names_from = "name", values_from = "value") + %>% mutate_at(vars(one_of(convert)), as.double) ) links <- links %>% left_join(linkAttributes, by = "id", suffix = c(".link", ".attr")) @@ -161,9 +161,9 @@ read_network <- function(filename) { # convert to a format we can join to the links networkAttributes <- (networkAttributes - %>% select(-class) - %>% pivot_wider(names_from = "name", values_from = "value") - %>% mutate_at(vars(one_of(convert)), as.double) + %>% select(-class) + %>% pivot_wider(names_from = "name", values_from = "value") + %>% mutate_at(vars(one_of(convert)), as.double) ) } diff --git a/R/output_trips.R b/R/output_trips.R index 2bb058d..9570456 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -1,3 +1,4 @@ + #####Variables#### matsimDumpOutputDirectory <- "./matsim_r_output" @@ -16,13 +17,23 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' #' These functions are provided for compatibility with older version of #' the matsimr package. They may eventually be completely -#' removed. -#' -#' +#' removed.\cr\cr +#' \strong{plotModalSplitPieChart} - Takes Table trips_output (from readTripsTable()), +#' to plot pie chart with with values that represent +#' percentage of using transport modes from trips #' #' @rdname matsimr-deprecated #' @name matsimr-deprecated #' +#' +#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' +#' @return \strong{plotModalSplitPieChart} - Pie Chart plot of transport mode distribution, values given in percents +#' #' @docType package #' @export plotModalSplitPieChart #' @aliases plotModalSplitPieChart @@ -44,7 +55,7 @@ plotModalSplitPieChart <- function(tripsTable, tripsTable$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable$main_mode)] <- united.name } - # calculates the mode share and saves it as a tibble + # tripsTableCount gives percentage representation out tripsTableCount <- tripsTable %>% count(main_mode) %>% mutate(n = n / sum(n) * 100) @@ -70,7 +81,6 @@ plotModalSplitPieChart <- function(tripsTable, ggtitle("Distribution of transport type") + theme_void() plt - if (file.exists(dump.output.to)) { ggsave(paste0(dump.output.to, "/modalSplitPieChart.png"),width = 6,height = 10, plt) } else { @@ -123,9 +133,21 @@ plotModalSplitPieChart <- function(tripsTable, } #' Deprecated function(s) in the matsimr package #' +#' \strong{plotModalSplitBarChart} - Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' percentage of using transport modes from trips #' #' @rdname matsimr-deprecated #' +#' +#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' +#' @return \strong{plotModalSplitBarChart} - Bar Chart plot of transport mode distribution, values given in percents +#' #' @docType package #' @export plotModalSplitBarChart #' @aliases plotModalSplitBarChart @@ -218,14 +240,15 @@ plotModalSplitBarChart <- function(tripsTable, #' **Deprecated. (see matsimr-deprecated)** Load MATSIM output_trips table into Memory #' -#' Loads a MATSim output_trips file from file or archive path, -#' creating a tibble +#' \strong{readTripsTable} - Loads a MATSim CSV output_trips from file or archive, +#' creating a tibble with columns as in csv file #' +#' @rdname matsimr-deprecated #' @name readTripsTable #' -#' @param input_path character string, path to MATSim output directory or http link to the file. +#' @param input_path character string, path to matsim output directory or http link to the file. #' @param n_max integer, maximum number of lines to read within output_trips -#' @return tibble of trips_output +#' @return \strong{readTripsTable} - tibble of trips_output #' #' @export readTripsTable <-function(input_path = ".", n_max = Inf) { @@ -236,8 +259,23 @@ readTripsTable <-function(input_path = ".", n_max = Inf) { #' Deprecated function(s) in the matsimr package #' #' +#' \strong{plotAverageTravelWait} - Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' time spent on traveling/waiting +#' Using parameters unite.columns, specific columns could be given, +#' to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' #' @rdname matsimr-deprecated #' +#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' +#' @return \strong{plotAverageTravelWait} - Bar Chart plot of average time spent on travel/wait #' @docType package #' @export plotAverageTravelWait #' @aliases plotAverageTravelWait @@ -271,6 +309,8 @@ plotAverageTravelWait <- function(tripsTable, unite.columns = character(0), unit } +###Needs to be added, because in master there isn't propper documentation + #' Deprecated function(s) in the matsimr package #' #' @@ -329,9 +369,9 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch } -#' Bar Chart with distance travelled on x-axis and number of trips on y-axis +#' Deprecated function(s) in the matsimr package #' -#' Takes Table trips_output (from readTripsTable()), +#' \strong{plotModalDistanceDistribution} - Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' number of trips ~ distance travelled #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') @@ -346,7 +386,8 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' @return Bar Chart plot of count of trips among distance travelled +#' +#' @return \strong{plotModalDistanceDistribution} Bar Chart plot of count of trips among distance travelled #' #' @export plotModalDistanceDistribution <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, @@ -424,13 +465,14 @@ plotModalDistanceDistribution <- function(tripsTable, unite.columns = character( } -#' Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis +#' Deprecated function(s) in the matsimr package #' -#' Takes 2 Tables trips_output (from readTripsTable()), +#' \strong{compareModalDistanceDistribution} - Takes 2 Tables trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' +#' @rdname matsimr-deprecated #' #' @param tripsTable1 tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 #' @param tripsTable2 tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted @@ -438,7 +480,7 @@ plotModalDistanceDistribution <- function(tripsTable, unite.columns = character( #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' @return Bar Chart plot of count of trips among distance travelled +#' @return \strong{compareModalDistanceDistribution} - Bar Chart plot of count of trips among distance travelled #' #' @export compareModalDistanceDistribution <- function(tripsTable1,tripsTable2, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, @@ -500,21 +542,21 @@ compareModalDistanceDistribution <- function(tripsTable1,tripsTable2, unite.colu } -#' Bar Chart with distance travelled on x-axis and number of trips on y-axis +#' Deprecated function(s) in the matsimr package #' -#' Takes Table trips_output (from readTripsTable()), +#' \strong{plotTripDistanceByMode} - Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' average distance traveled ~ main mode used #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' -#' +#' @rdname matsimr-deprecated #' @param tripsTable tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' -#' @return Bar Chart plot of distance traveled per mode +#' @return \strong{plotTripDistanceByMode} - Bar Chart plot of distance traveled per mode #' #' @export plotTripDistanceByMode <- function(tripsTable, @@ -555,20 +597,21 @@ plotTripDistanceByMode <- function(tripsTable, -#' Line plot with departure time x-axis and number of trips on y-axis +#' Deprecated function(s) in the matsimr package #' -#' Takes Table trips_output (from readTripsTable()), +#' \strong{plotTripCountByDepTime} - Takes Table trips_output (from readTripsTable()), #' to make line plot with with values that represent #' count of trips for a specific departure time by main_mode #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' +#' @rdname matsimr-deprecated #' #' @param tripsTable tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' @return Line Chart plot of trips count by departure mode per mode +#' @return \strong{plotTripCountByDepTime} - Line Chart plot of trips count by departure mode per mode #' #' @export plotTripCountByDepTime <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, @@ -628,21 +671,21 @@ plotTripCountByDepTime <- function(tripsTable, unite.columns = character(0), uni } } -#' Line plot that shows the number of activities ending at a given time, per activity type. -#' The activity end time is derived from the departure time in the given trips tibble. +#' Deprecated function(s) in the matsimr package #' -#' Takes Table trips_output (from readTripsTable()), +#' \strong{plotActivityEndTimes} - Takes Table trips_output (from readTripsTable()), #' to make line plot with with values that represent the #' number of activities ending at a specific time. #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' +#' @rdname matsimr-deprecated #' #' @param tripsTable tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' @return Line plot with departure time x-axis and number start activities on y-axis +#' @return \strong{plotActivityEndTimes} Line plot with departure time x-axis and number start activities on y-axis #' #' @export plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, @@ -706,14 +749,14 @@ plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), unite } -#' This function plots the number of trips ending per trip purpose over time. The trip purpose corresponds to the activity type of the destination activity of a given trip. -#' Thus, the y-axis of the plot can also be interpreted as the number of activities starting (based on the assumption that trip end time = activity start time). +#' Deprecated function(s) in the matsimr package #' -#' Takes Table trips_output (from readTripsTable()), +#' \strong{plotArrivalTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), #' to make line plot with with values that represent #' count of destination activities for a specific arrival time #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' +#' @rdname matsimr-deprecated #' #' @param tripsTable tibble of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns @@ -721,7 +764,7 @@ plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), unite #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' -#' @return Line plot with arrival time x-axis and number end activities on y-axis +#' @return \strong{plotArrivalTimesPerTripPurpose} - Line plot with arrival time x-axis and number end activities on y-axis #' #' @export plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, @@ -827,13 +870,14 @@ plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character } -#' This function plots the number of trips starting per trip purpose over time. The trip purpose corresponds to the activity type of the destination activity of a given trip. +#' Deprecated function(s) in the matsimr package #' -#' Takes Table trips_output (from readTripsTable()), +#' \strong{plotDepartureTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), #' to make line plot with with values that represent #' count of destination activities for a specific arrival time #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' +#' @rdname matsimr-deprecated #' #' @param tripsTable tibble of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns @@ -841,10 +885,11 @@ plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' -#' @return Line plot with arrival time x-axis and number end activities on y-axis +#' @return \strong{plotDepartureTimesPerTripPurpose} - Line plot with arrival time x-axis and number end activities on y-axis #' #' @export -plotDepartureTimesPerTripPurpose <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, +plotDepartureTimesPerTripPurpose <- function(tripsTable, unite.columns = character(0), united.name = "united", + dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { @@ -898,19 +943,20 @@ plotDepartureTimesPerTripPurpose <- function(tripsTable, unite.columns = charact } -#' Bar Chart with tripType on x-axis and travelled distance on y-axis +#' Deprecated function(s) in the matsimr package #' -#' Takes Table trips_output (from readTripsTable()), +#' \strong{plotTripDistancedByType} - Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' travelled distance of each tripType related to the shapeTable #' +#' @rdname matsimr-deprecated #' #' @param tripsTable tible of trips_output (from readTripsTable()) #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' -#' @return Bar Chart plot of distance traveled by type +#' @return \strong{plotTripDistancedByType} - Bar Chart plot of distance traveled by type #' #' @export plotTripDistancedByType <- function(tripsTable,shapeTable,crs,dump.output.to = matsimDumpOutputDirectory) { @@ -937,18 +983,19 @@ plotTripDistancedByType <- function(tripsTable,shapeTable,crs,dump.output.to = m -#' Plot alluvial/sankey diagram of transport mode changes +#' Deprecated function(s) in the matsimr package #' -#' Takes two trips_table (from readTripsTable), and collects +#' \strong{plotModalShiftSankey} - Takes two trips_table (from readTripsTable), and collects #' changes between transport mode distribution of these tables -#' to make alluvial diagram from this data -#' +#' to make alluvial diagram from this data\cr #' Function calculates number of each transport mode used in #' first and second table, and draws plot that represent how #' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) #' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") #' Using parameter show.onlyChanges #' +#' @rdname matsimr-deprecated +#' #' @param tripsTable1 tible of trips_output (from readTripsTable()) #' @param tripsTable2 tible of trips_output (from readTripsTable()) #' @param show.onlyChanges boolean, if it is set to TRUE => sankey diagram only contains changes on axes @@ -956,7 +1003,7 @@ plotTripDistancedByType <- function(tripsTable,shapeTable,crs,dump.output.to = m #' @param united.name if columns were united, you can specify name for the resulting column in plot #' @param dump.output.to folder that saves and configures yaml for simwrapper. folder where png of plot is stored #' -#' @return Alluvial diagram that represents changes in transport mode distribution of trip tables +#' @return \strong{plotModalShiftSankey} - Alluvial diagram that represents changes in transport mode distribution of trip tables #' #' @export plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FALSE, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory) { @@ -1006,25 +1053,24 @@ plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FA return(plt) } -#' Plot bar chart diagram of transport mode changes +#' Deprecated function(s) in the matsimr package #' -#' Takes two trips_table (from readTripsTable), and collects +#' \strong{plotModalShiftBar} - Takes two trips_table (from readTripsTable), and collects #' changes between transport mode distribution of these tables -#' to make bar chart diagram with dodging positioning from this data -#' +#' to make bar chart diagram with dodging positioning from this data\cr #' Function calculates number of each transport mode used in #' first and second table, and draws plot that represent how #' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) #' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") #' Using parameter show.onlyChanges -#' +#' @rdname matsimr-deprecated #' @param tripsTable1 tible of trips_output (from readTripsTable()) #' @param tripsTable2 tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name if columns were united, you can specify name for the resulting column in plot #' @param dump.output.to folder that saves and configures yaml for simwrapper. folder where png of plot is stored #' -#' @return plots Bar Chart of transport mode changes with additional files for simwrapper +#' @return \strong{plotModalShiftBar} - plots Bar Chart of transport mode changes with additional files for simwrapper #' #' @export plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, @@ -1052,17 +1098,18 @@ plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = characte -#' Plots result of filtered trips on the map (from shape) +#' Deprecated function(s) in the matsimr package #' -#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file)) +#' \strong{plotMapWithFilteredTrips} - Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file)) #' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -#' and filters the trips from table depending on *.inshape flags: +#' and filters the trips from table depending on *.inshape flags:\cr #' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape -#' result of filtering is plotted on map of shapeTable where green points are startpoints of trip and red points are endpoints of trip +#' \cr if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +#' \cr if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +#' \cr if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +#' \cr result of filtering is plotted on map of shapeTable where green points are startpoints of trip and red points are endpoints of trip #' +#' @rdname matsimr-deprecated #' @param table tibble of trips_output (from readTripsTable()) #' #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) @@ -1076,7 +1123,7 @@ plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = characte #' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot #' #' -#' @return plot with trips filtered depending on flags *.inshape on map from shapeTable +#' @return \strong{plotMapWithFilteredTrips} - plot with trips filtered depending on flags *.inshape on map from shapeTable #' #' @export plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRUE, end.inshape = TRUE, optimized = FALSE) { @@ -1208,8 +1255,11 @@ plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRU return(plt) } -#' Plots start and end coordinates of the given trips table on an osm map + +#' Deprecated function(s) in the matsimr package #' +#' \strong{plotMapWithTrips} - Plots start and end coordinates of the given trips table on an osm map +#' @rdname matsimr-deprecated #' @param table tibble of trips_output (from readTripsTable()) #' #' @@ -1218,10 +1268,11 @@ plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRU #' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot #' #' -#' @return plot with trips +#' @return \strong{plotMapWithTrips} - plot with trips #' #' @export plotMapWithTrips <- function(table, crs, optimized = FALSE) { + table_sf <- transformToSf(table, crs = crs, geometry.type = st_point()) st_geometry(table_sf) <- "start_wkt" table_sf_start <- table_sf %>% select(-end_wkt) @@ -1330,13 +1381,15 @@ plotMapWithTrips <- function(table, crs, optimized = FALSE) { # position it on the topleft position = "topleft" ) - + plt return(plt) } -#' Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart +#' Deprecated function(s) in the matsimr package #' +#' \strong{plotTripTypesPieChart} - plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart #' +#' @rdname matsimr-deprecated #' #' @param table tibble of trips_output (from readTripsTable()) #' @@ -1346,11 +1399,12 @@ plotMapWithTrips <- function(table, crs, optimized = FALSE) { #' #' #' -#' @return plot with percentage of each type of trips +#' @return \strong{plotTripTypesPieChart} - plot with percentage of each type of trips #' #' @export plotTripTypesPieChart <- function(table, shapeTable, crs) { + .Deprecated("") # table_sf = transformToSf(table,crs = crs) # Maybe union all this tables as 1 extended with additional column filtered_inside <- filterByRegion(table, shapeTable, crs = crs, start.inshape = TRUE, end.inshape = TRUE) @@ -1389,10 +1443,13 @@ plotTripTypesPieChart <- function(table, shapeTable, crs) { ggtitle("Distribution")) } -#' Creates BarChart of changing trip types(originating,transit etc) between 2 tables -#' and saves output to dump.output.to + +#' Deprecated function(s) in the matsimr package #' +#' \strong{compareTripTypesBarChart} - Creates BarChart of changing trip types(originating,transit etc) between 2 tables +#' and saves output to dump.output.to #' +#' @rdname matsimr-deprecated #' #' @param tripsTable1 tibble of trips_output (from readTripsTable(),f.e. base case) #' @@ -1405,7 +1462,7 @@ plotTripTypesPieChart <- function(table, shapeTable, crs) { #' @param dump.output.to folder that saves resulting image of BarChart #' #' -#' @return plot with percentage of each type of trips between 2 tables +#' @return \strong{compareTripTypesBarChart} - plot with percentage of each type of trips between 2 tables #' #' @export compareTripTypesBarChart <- function(tripsTable1,tripsTable2,shapeTable,crs,dump.output.to = matsimDumpOutputDirectory){ @@ -1449,9 +1506,12 @@ compareTripTypesBarChart <- function(tripsTable1,tripsTable2,shapeTable,crs,dump } -#' Plots every type of trips(inside, outside, origin and destinating) on map + +#' Deprecated function(s) in the matsimr package #' +#' \strong{plotMapWithTripsType} - plots every type of trips(inside, outside, origin and destinating) on map #' +#' @rdname matsimr-deprecated #' #' @param table tibble of trips_output (from readTripsTable()) #' @@ -1461,7 +1521,7 @@ compareTripTypesBarChart <- function(tripsTable1,tripsTable2,shapeTable,crs,dump #' #' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot #' -#' @return plot that contains every trip with defined trip type +#' @return \strong{plotMapWithTripsType} - plot that contains every trip with defined trip type #' #' @export plotMapWithTripsType <- function(table, shapeTable, crs, optimized = FALSE) { @@ -1681,11 +1741,12 @@ plotMapWithTripsType <- function(table, shapeTable, crs, optimized = FALSE) { } - -#' Chooses a function to compare output_trips from the folders. -#' baseFolder contains all base outputs, policyFolder contains all policy outputs. +#' Deprecated function(s) in the matsimr package #' +#' \strong{compareBasePolicyOutput} - Chooses a function to compare output_trips from the folders. +#' baseFolder contains all base outputs, policyFolder contains all policy outputs. #' +#' @rdname matsimr-deprecated #' #' @param baseFolder specifies data source folder with multiple base output_trips #' @@ -1694,7 +1755,7 @@ plotMapWithTripsType <- function(table, shapeTable, crs, optimized = FALSE) { #' @param dump.output.to that saves result of all comparisons between each base and each policy. #' For now it creates plotModalShiftBar() for the output_trips #' -#' @return list of tibbles, list of all base and policy output_trips as tibble +#' @return \strong{compareBasePolicyOutput} - list of tibbles, list of all base and policy output_trips as tibble #' #' @export compareBasePolicyOutput <- function(baseFolder,policyFolder,dump.output.to = matsimDumpOutputDirectory) { @@ -1747,10 +1808,13 @@ compareBasePolicyOutput <- function(baseFolder,policyFolder,dump.output.to = mat } invisible(list(base = base_trips,policy = policy_trips)) } -#' Chooses a function to compare output_trips from the folders. -#' baseFolder contains all base outputs, policyFolder contains all policy outputs. + +#' Deprecated function(s) in the matsimr package #' +#' \strong{compareBasePolicyShapeOutput} - Chooses a function to compare output_trips from the folders. +#' baseFolder contains all base outputs, policyFolder contains all policy outputs. #' +#' @rdname matsimr-deprecated #' #' @param baseFolder specifies data source folder with multiple base output_trips #' @@ -1761,7 +1825,7 @@ compareBasePolicyOutput <- function(baseFolder,policyFolder,dump.output.to = mat #' @param dump.output.to that saves result of all comparisons between each base and each policy. #' For now it creates plotModalShiftBar() for the output_trips #' -#' @return list of tibbles, list of all base and policy output_trips as tibble +#' @return \strong{compareBasePolicyShapeOutput} - list of tibbles, list of all base and policy output_trips as tibble #' #' @export compareBasePolicyShapeOutput <- function(baseFolder,policyFolder,shapeFilePath,crs,dump.output.to = matsimDumpOutputDirectory) { @@ -1819,13 +1883,15 @@ compareBasePolicyShapeOutput <- function(baseFolder,policyFolder,shapeFilePath,c #' Deprecated function(s) in the matsimr package #' +#' \strong{appendDistanceCategory} - adds to trips output tibble additional column that represent distance as category #' #' @rdname matsimr-deprecated #' +#' @return tibble of output_trips with distance category column +#' #' @docType package -#' @export compareAverageTravelWait -#' @aliases compareAverageTravelWait #' +#' @export appendDistanceCategory <- function(tripsTable){ .Deprecated("process_append_distcat") @@ -1859,8 +1925,9 @@ appendDistanceCategory <- function(tripsTable){ return(tripsTable_result) } -#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape +#' Deprecated function(s) in the matsimr package #' +#' \strong{filterByRegion} - Filtering of trips_table(from readTripsTable) depending on how they located in given shape\cr #' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). #' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) #' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) @@ -1880,7 +1947,7 @@ appendDistanceCategory <- function(tripsTable){ #' #' @param end.inshape bool, defines trips to conclude (see Description) #' -#' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) +#' @return \strong{filterByRegion} - tibble, with filtered trips depending on shapeTable and special flags (see Description) #' #' @export filterByRegion <- function(tripsTable, @@ -1928,9 +1995,12 @@ filterByRegion <- function(tripsTable, } -#' Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper + +#' Deprecated function(s) in the matsimr package #' +#' \strong{deriveODMatrix} - Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper #' +#' @rdname matsimr-deprecated #' #' @param tripsTable table of output trips(from readTripsTable) or path to trips_output file #' @@ -1946,7 +2016,7 @@ filterByRegion <- function(tripsTable, #' #' @param outer logical that represent if the table should contain outside flow of the shape, it isn't #' -#' @return tibble of origin/destination matrix +#' @return \strong{deriveODMatrix} - tibble of origin/destination matrix #' #' @export deriveODMatrix<- function(tripsTable, @@ -2072,14 +2142,17 @@ deriveODMatrix<- function(tripsTable, return(result_tibble) } - -#' Reads an coordinate reference system of MATSim output directory +#' Deprecated function(s) in the matsimr package +#' +#' \strong{getCrsFromConfig} - Reads an coordinate referenec system of MATSim output directory #' from output_config.xml #' +#' @rdname matsimr-deprecated +#' #' @param folder specifies path to find config #' #' -#' @return code of coordinate reference system +#' @return \strong{getCrsFromConfig} - code of coordinate reference system #' #' @export getCrsFromConfig <- function(folder) { @@ -2112,16 +2185,93 @@ getCrsFromConfig <- function(folder) { return(NA) } + +#' Deprecated function(s) in the matsimr package +#' +#' \strong{transformToSf} - Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature)\cr +#' Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features +#' deletes from resulting data.frame start_x, end_x, start_y, end_y.\cr +#' And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring()\cr +#' Or adds start_wkt and end_wkt, if geometry.type = st_point()\cr +#' Added column/columns projected to given CRS (coordinate reference system), +#' that can be taken from network file of MATSimOutputDirectory\cr +#' Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" +#' to get which type of table was generated, if it is needed +#' +#' @param table tibble of trips_output (from readTripsTable()) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @param geometry.type function of sf transformation, geometry.type can be (by default is st_multipoint()) +#' !!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or +#' !!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or +#' !!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!! +#' +#' @return \strong{transformToSf} - sf object (data.frame with geometries depending to geometry.type) +#' +#' @export +transformToSf <- function(table, + crs, + geometry.type = st_multipoint()) { + + .Deprecated("process_convert_table_to_sf") + + if (class(geometry.type)[2] == "POINT") { + table1 <- table %>% + # mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep ="")) + mutate(start_wkt = paste("POINT(", start_x, " ", start_y, ")", sep = "")) + table2 <- table %>% + mutate(end_wkt = paste("POINT(", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "POINT" + + + table1_wkt <- st_as_sf(table1, wkt = "start_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + table2_wkt <- st_as_sf(table2, wkt = "end_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + + result_table <- table1_wkt %>% mutate(end_wkt = table2_wkt$end_wkt) + st_geometry(result_table) <- "start_wkt" + st_crs(result_table) <- crs + st_geometry(result_table) <- "end_wkt" + st_crs(result_table) <- crs + st_geometry(result_table) <- "start_wkt" + return(result_table) + } else if (class(geometry.type)[2] == "MULTIPOINT") { + table <- table %>% + mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "MULTIPOINT" + + + result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + st_crs(result_table) <- crs + return(result_table) + } else if (class(geometry.type)[2] == "LINESTRING") { + table <- table %>% + mutate(wkt = paste("LINESTRING(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "LINESTRING" + + + result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + st_crs(result_table) <- crs + return(result_table) + } else { + return(NA) + } +} + + #####Reading##### -#' Load MATSIM output_trips table into memory +#' Load MATSIM output_trips table into Memory #' #' Loads a MATSim CSV output_trips from file or archive, #' creating a tibble with columns as in csv file #' -#' @param input_path character string, path to the MATSim output directory or http link to the file. -#' @param n_max optional, integer, maximum number of lines to read, standard value is Inf +#' @param input_path character string, path to matsim output directory or http link to the file. +#' @param n_max integer, maximum number of lines to read within output_trips #' @return tibble of trips_output #' #' @export @@ -2157,7 +2307,7 @@ read_output_trips <- function(input_path = ".", n_max = Inf) { ) ) # person is mostly integer, but contains also chars(see Hamburg 110813 observation) - # doesn't read coordinates correctly + # doesn't reads coordinates correctly trips_output_table <- trips_output_table %>% mutate( start_x = as.double(start_x), @@ -2174,34 +2324,34 @@ read_output_trips <- function(input_path = ".", n_max = Inf) { #####Plotting##### -#' Plot the distribution of modes as a pie chart +#' Plot main_mode distribution as a Pie Chart #' -#' Uses the dataframe trips_output (from \link{readTripsTable}), -#' to plot a pie chart of the modal split using the column main_mode +#' Takes Table trips_output (from \link{readTripsTable}), +#' to plot pie chart with with values that represent +#' percentage of using transport modes from trips #' -#' The function automatically detects the modes plots a pie chart. -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Function automatically detects transport_modes from table +#' and plots pie chart. +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' #' @param trips_table tibble of trips_output (from \link{readTripsTable}) -#' @param unite.modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' -#' @return pie chart plot of transport mode distribution, values given in percent +#' @return Pie Chart plot of transport mode distribution, values given in percents #' #' @export plot_mainmode_piechart <- function(trips_table, - unite.modes = character(0), united.name = "united", + unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory) { - # renaming/uniting of modes + # If some columns should be united trips_table = process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, + unite.columns = unite.columns, united.name = united.name) # processing - # calculates the mode share and saves it as a tibble + # tripsTableCount gives percentage representation out trips_table_count<-process_get_mainmode_distribution(trips_table, percentage= percentage) @@ -2216,37 +2366,35 @@ plot_mainmode_piechart <- function(trips_table, } -#' Plot the distribution of modes as a bar chart -#' -#' Takes the data frame trips_output (from \link{readTripsTable()}) -#' to plot a bar chart of the modal split using the column main_mode. +#' Plot main_mode distribution as a bar Chart #' -#' The modal shares are given in percentages. +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' percentage of using transport modes from trips #' -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Function automatically detects transport_modes from table +#' and plots pie chart with percentage of distribution. +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' #' -#' @param trips_table tibble of trips_output (from \link{readTripsTable()}) -#' @param unite.modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param trips_table tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' #' @return Bar Chart plot of transport mode distribution, values given in percents #' #' @export plot_mainmode_barchart <- function(trips_table, - unite.modes = character(0), + unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, percentage = FALSE) { - # renaming/uniting of modes + # If some columns should be united trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, + unite.columns = unite.columns, united.name = united.name) # processing - # calculates the mode share and saves it as a tibble trips_table_count <- process_get_mainmode_distribution(trips_table, percentage = percentage) @@ -2260,33 +2408,32 @@ plot_mainmode_barchart <- function(trips_table, return(fig) } -#' Plot travel and wait time for each mode as a bar chart +#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis #' -#' Takes the data frame trips_output (from \links{readTripsTable()}), -#' to plot a bar chart of travel and wait times. -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' time spent on traveling/waiting +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' #' -#' @param trips_table tibble of trips_output (from \links{readTripsTable()}) -#' @param unite.modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param trips_table tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' #' @return Bar Chart plot of average time spent on travel/wait #' #' @export plot_travelwaittime_mean_barchart <- function(trips_table, - unite.modes = character(0), + unite.columns = character(0), united.name = "united", time_format = "minute") { - # renaming/uniting of modes + # If some columns should be united trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, + unite.columns = unite.columns, united.name = united.name) - #processing + #processing of result table avg_time = process_get_travelwaittime_by_mainmode(trips_table,time_format = time_format) #plotting @@ -2306,190 +2453,225 @@ plot_travelwaittime_mean_barchart <- function(trips_table, -#' Bar Chart comparing two runs with main_mode on x-axis and average travel/wait time on y-axis -#' -#' Takes two data frames (from \link{readTripsTable()}), -#' to plot a comparison bar chart of travel and wait times. -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') + +#' Bar Chart with distance travelled on x-axis and number of trips on y-axis #' +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' number of trips ~ distance travelled +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()) -#' @param tripsTable2 tibble of trips_output (from readTripsTable()) -#' @param unite.modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode #' -#' @return Bar chart plot comparing average time spent on travel/wait of two runs +#' @param trips_table tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @return Bar Chart plot of count of trips among distance travelled #' #' @export -plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, - unite.modes = character(0), - united.name = "united", - time_format = "minute") { - - #TODO: - # . Document and add title to show what means positive/negative value - # . think about comparing processing functions they can appear in future often - +plot_distcat_by_mainmode_barchart <- function(trips_table, + unite.columns = character(0), + united.name = "united", + dist_column = "dist_cat", + distances_array = c(1000,2000,5000,10000,20000,50000,100000)) { - # renaming/uniting of modes - trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.modes = unite.modes, - united.name = united.name) - trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.modes = unite.modes, + # If some columns should be united + trips_table <- process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, united.name = united.name) #processing - avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) - + trips_table <- process_append_distcat(trips_table =trips_table, + distances_array = distances_array) - avg_time2 = process_get_travelwaittime_by_mainmode(trips_table2,time_format = time_format) + #plotting + plt = ggplot(trips_table) + + geom_bar(aes(x = dist_cat,fill = main_mode),position = position_dodge())+ + ggtitle("Number of trips per travelling distance") + fig = plotly::ggplotly(plt) + fig + return(fig) - avg_time = full_join(avg_time1, avg_time2, by = "main_mode") %>% - replace_na(list(trav_time_avg.x = 0,wait_time_avg.x = 0,trav_time_avg.y = 0,wait_time_avg.y = 0)) +} +#' Bar Chart with distance travelled on x-axis and number of trips on y-axis +#' +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' average distance traveled ~ main mode used +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' @param trips_table tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart#' +#' @return Bar Chart plot of distance traveled per mode +#' +#' @export +plot_distance_by_mainmode_barchart <- function(trips_table, + unite.columns = character(0), united.name = "united", + euclidean = FALSE) { - avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg.x - trav_time_avg.y, - wait_time_avg =wait_time_avg.x - wait_time_avg.y )%>% - select(-wait_time_avg.x,-wait_time_avg.y, -trav_time_avg.x,-trav_time_avg.y) + # If some columns should be united + trips_table <- process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, + united.name = united.name) + #processing + trips_table <- process_get_travdistance_distribution(trips_table = trips_table,euclidean = euclidean) - #plotting - fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") - fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") - fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)")),barmode = "group") + #if(only.process){ + # return(trips_table) + #} + #plotting + text_for_y <- round(trips_table$avg_dist,digits = 2) + fig <- plot_ly(data = trips_table,x = ~main_mode,y = ~avg_dist, + type = 'bar', + text = text_for_y, + textposition = "auto", + name = paste0("AVG " ,if_else(euclidean,"eucliden ","traveled ") ,"distance by mode over a day")) + fig <- fig %>% layout(yaxis = list(title = "Distance (in meters)"),barmode = "group") fig return(fig) - } -#' Bar Chart with distance traveled on x-axis and number of trips on y-axis +#' Line plot with departure time x-axis and number of trips on y-axis #' -#' Takes the data frame trips_output (from \link{readTripsTable()}) and categorizes the traveled distances into pre-defined bins -#' to plot a histogram of the traveled distances. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Takes Table trips_output (from readTripsTable()), +#' to make line plot with with values that represent +#' count of trips for a specific departure time by main_mode +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' #' -#' @param trips_table tibble of trips_output (from readTripsTable()) -#' @param unite.modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode -#' @return Bar Chart plot of count of trips among distance travelled +#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @return Line Chart plot of trips count by departure mode per mode #' #' @export -plot_distcat_by_mainmode_barchart <- function(trips_table, - unite.modes = character(0), - united.name = "united", - dist_column = "dist_cat", - distances_array = c(1000,2000,5000,10000,20000,50000,100000)) { +plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, + unite.columns = character(0), + united.name = "united") { - # renaming/uniting of modes + # If some columns should be united trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, - united.name = united.name) + unite.columns = unite.columns, + united.name = united.name) - #processing - trips_table <- process_append_distcat(trips_table =trips_table, - distances_array = distances_array) + #processing + tripsTable = tripsTable %>% + mutate(dep_time = hour(dep_time)) %>% + count(dep_time,main_mode) #plotting - plt = ggplot(trips_table) + - geom_bar(aes(x = dist_cat,fill = main_mode),position = position_dodge())+ - ggtitle("Number of trips per travelling distance") - fig = plotly::ggplotly(plt) + fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) + fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") fig return(fig) - } -#' Bar chart with average distance traveled for each mode on x-axis and number of trips on y-axis +#' Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart #' -#' Takes the data frame trips_output (from \link{readTripsTable()}), -#' to plot a bar chart of the average distance traveled for each main mode, -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tibble of trips_output (from readTripsTable()) -#'@param unite.modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode -#' @return Bar Chart plot of distance traveled per mode +#' @param table tibble of trips_output (from readTripsTable()) +#' +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' +#' +#' @return plot with percentage of each type of trips #' #' @export -plot_distance_by_mainmode_barchart <- function(trips_table, - unite.columns = character(0), united.name = "united", - euclidean = FALSE) { +plot_spatialtype_by_shape_piechart <- function(trips_table, shape_table, crs) { + trips_table <- process_append_spatialcat(trips_table,shape_table = shape_table,crs = crs) - # renaming/uniting of modes - trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, - united.name = united.name) + #print(trips_table) - #processing - trips_table <- process_get_travdistance_distribution(trips_table = trips_table,euclidean = euclidean) + trips_table_distribution <- trips_table %>% count(spatial_category) - #if(only.process){ - # return(trips_table) - #} + #print(trips_table_distribution) - #plotting - text_for_y <- round(trips_table$avg_dist,digits = 2) - fig <- plot_ly(data = trips_table,x = ~main_mode,y = ~avg_dist, - type = 'bar', - text = text_for_y, - textposition = "auto", - name = paste0("AVG " ,if_else(euclidean,"eucliden ","traveled ") ,"distance by mode over a day")) - fig <- fig %>% layout(yaxis = list(title = "Distance (in meters)"),barmode = "group") + fig <- plot_ly(trips_table_distribution, labels = ~spatial_category, values = ~n, type = 'pie') + fig <- fig %>% layout(title = 'Spatial type distribution', + xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE), + yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE)) + fig + + +} + +#' Bar Chart with tripType on x-axis and travelled distance on y-axis +#' +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' travelled distance of each tripType related to the shapeTable +#' +#' +#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @return Bar Chart plot of distance traveled by spatial type +#' +#' @export +plot_distance_by_spatialcat <- function(trips_table, shape_table, crs, euclidian = FALSE) { + + #processing + trips_table<- process_append_spatialcat(trips_table,shape_table, crs = crs) + travelled = trips_table %>% group_by(spatial_category) %>% summarize(travelled = sum(traveled_distance)/1000) + + #For plotting + fig = plot_ly(data = travelled,x = ~spatial_category,y = ~travelled,type = 'bar',name = "Distance travelled by trip Type") + fig = fig %>% layout(yaxis = list(title = "Distance travelled (in kms)"),barmode = "group") fig return(fig) } +###### Compare ###### -#' Bar chart comparing distance traveled on x-axis and number of trips on y-axis for two different runs - -#' Takes two data frames (from \link{readTripsTable()}), categorizes the traveled distances into pre-defined bins -#' and plots the difference in number of trips for each bin. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis +#' +#' Takes 2 Tables trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' #' - -#' @param tripsTable1 tibble of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 -#' @param tripsTable2 tibble of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted -#' @param unite.modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param trips_table1 tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 +#' @param trips_table2 tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' @return Bar Chart plot of count of trips among distance travelled #' #' @export plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, - unite.modes = character(0), united.name = "united", - dist_column = "dist_cat", - distances_array = c(1000,2000,5000,10000,20000,50000,100000)) { + unite.columns = character(0), united.name = "united", + dist_column = "dist_cat", + distances_array = c(1000,2000,5000,10000,20000,50000,100000)) { trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.modes = unite.modes, - united.name = united.name) + unite.columns = unite.columns, + united.name = united.name) trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.modes = unite.modes, + unite.columns = unite.columns, united.name = united.name) modes = unique(c(unique(trips_table1$main_mode),unique(trips_table2$main_mode))) @@ -2524,68 +2706,40 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, } -#' Line plot with departure time on x-axis and number of trips on y-axis -#' -#' Takes data frame trips_output (from \link{readTripsTable()}), -#' to create a line plot of the number of trips for a specific departure time by main_mode -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') -#' -#' -#' @param tripsTable tibble of trips_output (from readTripsTable()) -#' @param unite.modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode -#' @return Line plot of trips count by departure time per mode -#' -#' @export -plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, - unite.modes = character(0), - united.name = "united") { - - - # renaming/uniting of modes - trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, - united.name = united.name) - - - #processing - tripsTable = tripsTable %>% - mutate(dep_time = hour(dep_time)) %>% - count(dep_time,main_mode) - -#' Plot bar chart of changes in modal split -#' -#' Takes two data frames (from \link{readTripsTable()}), calculates the -#' changes in mode shares and plots them as a bar chart -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Plot bar chart diagram of transport mode changes #' +#' Takes two trips_table (from readTripsTable), and collects +#' changes between transport mode distribution of these tables +#' to make bar chart diagram with dodging positioning from this data #' +#' Function calculates number of each transport mode used in +#' first and second table, and draws plot that represent how +#' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) +#' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") +#' Using parameter show.onlyChanges #' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()) -#' @param tripsTable2 tibble of trips_output (from readTripsTable()) -#'@param unite.modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param tripsTable1 tible of trips_output (from readTripsTable()) +#' @param tripsTable2 tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name if columns were united, you can specify name for the resulting column in plot #' -#' @return plots bar chart of changes in modal split +#' @return plots Bar Chart of transport mode changes with additional files for simwrapper #' #' @export plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, - unite.modes = character(0), + unite.columns = character(0), united.name = "united") { - # renaming/uniting of modes + # If the unite.columns is specified, then + #print(dump.output.to) trips_table1 <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, - united.name = united.name) + unite.columns = unite.columns, + united.name = united.name) trips_table2 <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, - united.name = united.name) + unite.columns = unite.columns, + united.name = united.name) trips_table1 = trips_table1 %>% mutate(type = "base") trips_table2 = trips_table2 %>% mutate(type = "policy") @@ -2602,33 +2756,37 @@ plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, #' Plot alluvial/sankey diagram of transport mode changes #' -#' Takes two data frames (from \link{readTripsTable()}) and compares the mode choice for each agent and summarizes the results, showing the modal shift. -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') -#' The parameter show.onlyChanges allows the visualization of only the mode shift (excluding the trips that do not change mode). Standard value is FALSE. +#' Takes two trips_table (from readTripsTable), and collects +#' changes between transport mode distribution of these tables +#' to make alluvial diagram from this data +#' +#' Function calculates number of each transport mode used in +#' first and second table, and draws plot that represent how +#' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) +#' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") +#' Using parameter show.onlyChanges #' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()) -#' @param tripsTable2 tibble of trips_output (from readTripsTable()) -#' @param show.onlyChanges boolean, if it is set to TRUE the sankey diagram only shows the mode shift -#' @param unite.modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param tripsTable1 tible of trips_output (from readTripsTable()) +#' @param tripsTable2 tible of trips_output (from readTripsTable()) +#' @param show.onlyChanges boolean, if it is set to TRUE => sankey diagram only contains changes on axes +#' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name if columns were united, you can specify name for the resulting column in plot #' -#' @return Alluvial diagram that represents changes in transport mode distribution +#' @return Alluvial diagram that represents changes in transport mode distribution of trip tables #' #' @export plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, show.onlyChanges = FALSE, - unite.modes = character(0), + unite.columns = character(0), united.name = "united") { - # renaming/uniting of modes + #rename trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.modes = unite.modes, + unite.columns = unite.columns, united.name = united.name) trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.modes = unite.modes, + unite.columns = unite.columns, united.name = united.name) #processing joined <- as_tibble(inner_join(trips_table1, trips_table2 %>% @@ -2681,92 +2839,523 @@ plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, font = list( size = 10 ) - ) - - fig - return(fig) -} - -#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis -#' -#' Takes the data frame trips_output (from \link{readTripsTable()}), -#' to plot a bar chart of the traveling/waiting time -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') -#' -#' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()) -#' @param tripsTable2 tibble of trips_output (from readTripsTable()) -#' @param unite.modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode -#' -#' @return Bar Chart plot of average time spent on travel/wait -#' -#' @export -plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_table2, - unite.modes = character(0), - united.name = "united", - time_format = "minute") { - - #TODO: - # . Document and add title to show what means positive/negative value - # . think about comparing processing functions they can appear in future often - - - # If some columns should be united - trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.modes = unite.modes, - united.name = united.name) - - trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.modes = unite.modes, - united.name = united.name) - - #processing - avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) - - - - avg_time2 = process_get_travelwaittime_by_mainmode(trips_table2,time_format = time_format) - - - avg_time = full_join(avg_time1, avg_time2, by = "main_mode") %>% - replace_na(list(trav_time_avg.x = 0,wait_time_avg.x = 0,trav_time_avg.y = 0,wait_time_avg.y = 0)) - - - - avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg.x - trav_time_avg.y, - wait_time_avg =wait_time_avg.x - wait_time_avg.y )%>% - select(-wait_time_avg.x,-wait_time_avg.y, -trav_time_avg.x,-trav_time_avg.y) - - - - #plotting - fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") - fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") - fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)")),barmode = "group") - - - fig - return(fig) + ) + + fig + return(fig) +} + +#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis +#' +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' time spent on traveling/waiting +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' @param tripsTable1 tible of trips_output (from readTripsTable()) +#' @param tripsTable2 tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' +#' @return Bar Chart plot of average time spent on travel/wait +#' +#' @export +plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_table2, + unite.columns = character(0), + united.name = "united", + time_format = "minute") { + + #TODO: + # . Document and add title to show what means positive/negative value + # . think about comparing processing functions they can appear in future often + + + # If some columns should be united + trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, + unite.columns = unite.columns, + united.name = united.name) + + trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, + unite.columns = unite.columns, + united.name = united.name) + + #processing + avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) + + + + avg_time2 = process_get_travelwaittime_by_mainmode(trips_table2,time_format = time_format) + + + avg_time = full_join(avg_time1, avg_time2, by = "main_mode") %>% + replace_na(list(trav_time_avg.x = 0,wait_time_avg.x = 0,trav_time_avg.y = 0,wait_time_avg.y = 0)) + + + + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg.x - trav_time_avg.y, + wait_time_avg =wait_time_avg.x - wait_time_avg.y )%>% + select(-wait_time_avg.x,-wait_time_avg.y, -trav_time_avg.x,-trav_time_avg.y) + + + + #plotting + fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") + fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") + fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)")),barmode = "group") + + + fig + return(fig) + +} + +#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis +#' +#' Takes Table trips_output (from readTripsTable()), +#' to plot bar chart with with values that represent +#' time spent on traveling/waiting +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' @param tripsTable1 tible of trips_output (from readTripsTable()) +#' @param tripsTable2 tible of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' +#' @return Bar Chart plot of average time spent on travel/wait +#' +#' @export +plot_compare_count_by_spatialcat <- function(trips_table1,trips_table2, shape_table ,crs,dump.output.to = matsimDumpOutputDirectory) { + + spatial_table1 <- process_append_spatialcat(trips_table = trips_table1, + shape_table = shape_table, + crs = crs) + + spatial_table2 <- process_append_spatialcat(trips_table = trips_table2, + shape_table = shape_table, + crs = crs) + + + plt = ggplot(result_table, aes(x =type,fill = factor(table_num)))+ + geom_bar(position = position_dodge())+ + coord_flip() + plotly::ggplotly(plt) + + + return(plotly::ggplotly(plt)) + +} + + + + +###### Mapping ###### + + +#' Plots start and end coordinates of the given trips table on an osm map +#' +#' @param table tibble of trips_output (from readTripsTable()) +#' +#' +#' @param crs numeric representation of the EPSG code or proj4string for the corresponding coordinate system of the trip coordinates, can be found in network file from output directory of MATSim simulation +#' +#' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot +#' +#' +#' @return plot with trips +#' +#' @export +plot_map_trips <- function(trips_table, crs,optimized = FALSE, + shape_table = NULL ) { + + table_sf <- process_convert_table_to_sf(trips_table, crs = crs, geometry.type = st_point()) + st_geometry(table_sf) <- "start_wkt" + table_sf_start <- table_sf %>% select(-end_wkt) + st_geometry(table_sf) <- "end_wkt" + table_sf_end <- table_sf %>% select(-start_wkt) + + if(!is.null(shape_table)){ + + if (st_crs(shape_table) == NA) { + ct_crs(shape_table) <- crs + } + shape_table <- st_transform(shape_table, crs = "+proj=longlat +datum=WGS84 +no_defs") + + } + + table_sf_start <- st_transform(table_sf_start, "+proj=longlat +datum=WGS84 +no_defs") + table_sf_end <- st_transform(table_sf_end, "+proj=longlat +datum=WGS84 +no_defs") + + if (optimized) { + colors <- c("Start" = "blue", "End" = "red") + shapes <- c("Start" = 5, "End" = 3) + # ggplot2 isn't interactive! + plt <- ggplot() + + geom_sf(data = table_sf_start, aes(color = "Start"), size = 1, shape = 5) + + geom_sf(data = table_sf_end, aes(color = "End"), size = 1, shape = 3) + + labs(color = "Type") + + scale_colour_manual(values = colors) + + if(!is.null(shape_table)){ + plt <-ggplot() + + geom_sf(data = shape_table)+ + geom_sf(data = table_sf_start, aes(color = "Start"), size = 1, shape = 5) + + geom_sf(data = table_sf_end, aes(color = "End"), size = 1, shape = 3) + + labs(color = "Type") + + scale_colour_manual(values = colors) + } + plt + return(plt) + } + + + + + + + + + # If we need to change design + # css_fix <- "div.info.legend.leaflet-control br {clear: both;}" + # Convert CSS to HTML + # html_fix <- htmltools::tags$style(type = "text/css", css_fix) + + plt <- leaflet() %>% + addTiles() %>% + addProviderTiles( + "OpenStreetMap", + # give the layer a name + group = "OpenStreetMap" + ) %>% + addProviderTiles( + "Stamen.Toner", + group = "Stamen.Toner" + ) %>% + addProviderTiles( + "Stamen.Terrain", + group = "Stamen.Terrain" + ) %>% + addProviderTiles( + "Esri.WorldStreetMap", + group = "Esri.WorldStreetMap" + ) %>% + addProviderTiles( + "Wikimedia", + group = "Wikimedia" + ) %>% + addProviderTiles( + "CartoDB.Positron", + group = "CartoDB.Positron" + ) %>% + addProviderTiles( + "Esri.WorldImagery", + group = "Esri.WorldImagery" + ) %>% + addCircleMarkers(table_sf_start, + lng = st_coordinates(table_sf_start$start_wkt)[, 1], + lat = st_coordinates(table_sf_start$start_wkt)[, 2], radius = 3, color = "blue", + label = paste( + "Person_id:", + table_sf_start$person, "
", + "Trip_id:", + table_sf_start$trip_id, "
", + "main_mode:", table_sf_start$main_mode, "
", + "type:", "start", "
", + "Start activity:", + table_sf_start$start_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(table_sf_end, + lng = st_coordinates(table_sf_end$end_wkt)[, 1], + lat = st_coordinates(table_sf_end$end_wkt)[, 2], radius = 0.15, color = "red", + label = paste( + "Person_id:", + table_sf_end$person, "
", + "Trip_id:", + table_sf_end$trip_id, "
", + "main_mode:", table_sf_end$main_mode, "
", + "type:", "end", "
", + "End activity:", + table_sf_end$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addLegend( + colors = c("blue", "red"), + labels = c("Start of trip", "End of trip"), + position = "bottomleft", + title = "Type of the point", + opacity = 0.9 + ) %>% + addMiniMap() %>% + addLayersControl( + baseGroups = c( + "OpenStreetMap", "Stamen.Toner", + "Stamen.Terrain", "Esri.WorldStreetMap", + "Wikimedia", "CartoDB.Positron", "Esri.WorldImagery" + ), + # position it on the topleft + position = "topleft" + ) + if(!is.null(shape_table)){ + plt = plt %>% addPolygons(data = shape_table, opacity = 0.1, color = "green") + + } + plt + return(plt) +} + + +#' Plots every type of trips(inside, outside, origin and destinating) on map +#' +#' +#' +#' @param table tibble of trips_output (from readTripsTable()) +#' +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot +#' +#' @return plot that contains every trip with defined trip type +#' +#' @export +plot_map_trips_by_spatialcat <- function(trips_table, shape_table, + crs, optimized = FALSE) { + + + #processing + + spatial_table <- process_append_spatialcat(trips_table, shape_table = shape_table,crs = crs) + + filtered_sf_inside <- spatial_table %>% filter(spatial_category == "inside") %>% + process_convert_table_to_sf( crs = crs, geometry.type = st_multipoint()) + filtered_sf_origin <- spatial_table %>% filter(spatial_category == "originating") %>% + process_convert_table_to_sf( crs = crs, geometry.type = st_multipoint()) + filtered_sf_destination <- spatial_table %>% filter(spatial_category == "destinating") %>% + process_convert_table_to_sf( crs = crs, geometry.type = st_multipoint()) + filtered_sf_transit <- spatial_table %>% filter(spatial_category == "outside") %>% + process_convert_table_to_sf( crs = crs, geometry.type = st_multipoint()) + + if (st_crs(shape_table) == NA) { + ct_crs(shape_table) <- crs + } + + shape_table <- st_transform(shape_table, crs = "+proj=longlat +datum=WGS84 +no_defs") + + filtered_sf_inside <- st_transform(filtered_sf_inside, "+proj=longlat +datum=WGS84 +no_defs") + filtered_sf_origin <- st_transform(filtered_sf_origin, "+proj=longlat +datum=WGS84 +no_defs") + filtered_sf_destination <- st_transform(filtered_sf_destination, "+proj=longlat +datum=WGS84 +no_defs") + filtered_sf_transit <- st_transform(filtered_sf_transit, "+proj=longlat +datum=WGS84 +no_defs") + + + #plotting + if (optimized) { + colors <- c("inside" = "green", "origin" = "red", "destination" = "orange", "transit" = "blue") + shapes <- c("Start" = 5, "End" = 3) + plt <- ggplot() + + geom_sf(data = shape_table) + + # geom_sf(data = ) + geom_sf(data = filtered_sf_inside, aes(color = "inside"), size = 3, alpha = 0.5) + + geom_sf(data = filtered_sf_origin, aes(color = "origin"), size = 3, alpha = 0.4) + + geom_sf(data = filtered_sf_destination, aes(color = "destination"), size = 3, alpha = 0.3) + + geom_sf(data = filtered_sf_transit, aes(color = "transit"), size = 2, alpha = 0.1) + + labs(color = "Type") + + scale_colour_manual(values = colors) + plt + return((plt)) + } + + # If we need to adjust design + # css_fix <- "div.info.legend.leaflet-control br {clear: both;}" + # Convert CSS to HTML + # html_fix <- htmltools::tags$style(type = "text/css", css_fix) + + + plt <- leaflet() %>% + addTiles() %>% + addProviderTiles( + "OpenStreetMap", + # give the layer a name + group = "OpenStreetMap" + ) %>% + addProviderTiles( + "Stamen.Toner", + group = "Stamen.Toner" + ) %>% + addProviderTiles( + "Stamen.Terrain", + group = "Stamen.Terrain" + ) %>% + addProviderTiles( + "Esri.WorldStreetMap", + group = "Esri.WorldStreetMap" + ) %>% + addProviderTiles( + "Wikimedia", + group = "Wikimedia" + ) %>% + addProviderTiles( + "CartoDB.Positron", + group = "CartoDB.Positron" + ) %>% + addProviderTiles( + "Esri.WorldImagery", + group = "Esri.WorldImagery" + ) %>% + addPolygons(data = shape_table, opacity = 0.1, color = "green") %>% + addCircleMarkers(filtered_sf_inside, + lng = st_coordinates(filtered_sf_inside$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_inside$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 3, color = "blue", + label = paste( + "Person_id:", + filtered_sf_inside$person, "
", + "Trip_id:", + filtered_sf_inside$trip_id, "
", + "main_mode:", filtered_sf_inside$main_mode, "
", + "type:", "start", "
", + "Start activity:", + filtered_sf_inside$start_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(filtered_sf_inside, + lng = st_coordinates(filtered_sf_inside$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_inside$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 3, color = "blue", + label = paste( + "Person_id:", + filtered_sf_inside$person, "
", + "Trip_id:", + filtered_sf_inside$trip_id, "
", + "main_mode:", filtered_sf_inside$main_mode, "
", + "type:", "end", "
", + "End activity:", + filtered_sf_inside$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(filtered_sf_origin, + lng = st_coordinates(filtered_sf_origin$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_origin$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 2, color = "red", + label = paste( + "Person_id:", + filtered_sf_origin$person, "
", + "Trip_id:", + filtered_sf_origin$trip_id, "
", + "main_mode:", filtered_sf_origin$main_mode, "
", + "type:", "start", "
", + "Start activity:", + filtered_sf_origin$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(filtered_sf_origin, + lng = st_coordinates(filtered_sf_origin$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_origin$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 2, color = "red", + label = paste( + "Person_id:", + filtered_sf_origin$person, "
", + "Trip_id:", + filtered_sf_origin$trip_id, "
", + "main_mode:", filtered_sf_origin$main_mode, "
", + "type:", "end", "
", + "End activity:", + filtered_sf_origin$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(filtered_sf_destination, + lng = st_coordinates(filtered_sf_destination$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_destination$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 1, color = "orange", + label = paste( + "Person_id:", + filtered_sf_destination$person, "
", + "Trip_id:", + filtered_sf_destination$trip_id, "
", + "main_mode:", filtered_sf_destination$main_mode, "
", + "type:", "start", "
", + "Start activity:", + filtered_sf_destination$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(filtered_sf_destination, + lng = st_coordinates(filtered_sf_destination$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_destination$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 1, color = "orange", + label = paste( + "Person_id:", + filtered_sf_destination$person, "
", + "Trip_id:", + filtered_sf_destination$trip_id, "
", + "main_mode:", filtered_sf_destination$main_mode, "
", + "type:", "end", "
", + "End activity:", + filtered_sf_destination$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(filtered_sf_transit, + lng = st_coordinates(filtered_sf_transit$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_transit$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 0.15, color = "black", + label = paste( + "Person_id:", + filtered_sf_transit$person, "
", + "Trip_id:", + filtered_sf_transit$trip_id, "
", + "main_mode:", filtered_sf_transit$main_mode, "
", + "type:", "start", "
", + "Start activity:", + filtered_sf_transit$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addCircleMarkers(filtered_sf_transit, + lng = st_coordinates(filtered_sf_transit$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], + lat = st_coordinates(filtered_sf_transit$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 0.15, color = "black", + label = paste( + "Person_id:", + filtered_sf_transit$person, "
", + "Trip_id:", + filtered_sf_transit$trip_id, "
", + "main_mode:", filtered_sf_transit$main_mode, "
", + "type:", "end", "
", + "End activity:", + filtered_sf_transit$end_activity_type, "
" + ) %>% lapply(htmltools::HTML) + ) %>% + addLegend( + colors = c("blue", "red", "orange", "black"), + labels = c( + "Trips inside of region", + "Trips with the end outside region", + "Trips with the start outside region", + "Trips that start and end outside region" + ), + position = "bottomleft", + title = "Type of the point", + opacity = 0.9 + ) %>% + addMiniMap() %>% + addLayersControl( + baseGroups = c( + "OpenStreetMap", "Stamen.Toner", + "Stamen.Terrain", "Esri.WorldStreetMap", + "Wikimedia", "CartoDB.Positron", "Esri.WorldImagery" + ), + # position it on the topleft + position = "topleft" + ) + plt + return(plt) } -###### Mapping ###### - #####Processing##### - +#' @export process_rename_mainmodes<-function(trips_table, - unite.modes = character(0), united.name = "united"){ + unite.columns = character(0), united.name = "united"){ - if (length(unite.modes) != 0) { - trips_table$main_mode[grep(paste0(unite.modes, collapse = "|") + if (length(unite.columns) != 0) { + trips_table$main_mode[grep(paste0(unite.columns, collapse = "|") , trips_table$main_mode)] <- united.name } return(trips_table) } - +#' @export process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ trips_table_count <- trips_table %>% @@ -2786,30 +3375,30 @@ process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ return(trips_table) } - +#' @export process_get_travelwaittime_by_mainmode_barchart<-function(trips_table, - time_format = "minute"){#also could be hours/seconds + time_format = "minute"){#also could be hours/seconds #get 2 columns with mean travel time and mean wait time grouped by main_mode in seconds - avg_time = trips_table %>% group_by(main_mode)%>% + avg_time = trips_table %>% group_by(main_mode)%>% summarize(trav_time_avg = hms::hms(seconds_to_period(mean(trav_time))), wait_time_avg = hms::hms(seconds_to_period(mean(wait_time)))) %>% mutate(trav_time_avg = as.numeric(trav_time_avg),wait_time_avg = as.numeric(wait_time_avg)) - if(time_format == "minute"){ - #convert seconds to minutes - avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/60, wait_time_avg = wait_time_avg/60) - return(avg_time) - }else if(time_format == "hour"){ - avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/3600, wait_time_avg = wait_time_avg/3600) - return(avg_time) - } + if(time_format == "minute"){ + #convert seconds to minutes + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/60, wait_time_avg = wait_time_avg/60) + return(avg_time) + }else if(time_format == "hour"){ + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/3600, wait_time_avg = wait_time_avg/3600) + return(avg_time) + } - return(avg_time) + return(avg_time) } - +#' @export process_append_distcat <- function(trips_table,distances_array = c(1000,2000,5000,10000,20000,50000,100000)){ distances_array = sort(c(distances_array,c(0,Inf))) @@ -2834,27 +3423,25 @@ process_append_distcat <- function(trips_table,distances_array = c(1000,2000,500 } ######Spatial###### -#' XXXX trips_table but shapeTable - fix naming -#' XXXX finish when code revision is done -#' Filters trips_table(from ,\link{readTripsTable}) depending by location using a shapefile + +#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape #' -#' Uses trips_table and an sf object (can be created using the function st_read()), -#' transforms both objects to match a mutual coordinate system (crs) -#' and filters the trips from trips_table depending on *.inshape flags: -#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +#' and filters the trips from table depending on *.inshape flags: +#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips \strong{inside} of the given shape +#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which \strong{originating} in the shape +#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which \strong{destinating} in the shape +#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which \strong{outside} of the given shape #' #' @param trips_table tibble of trips_output (from readTripsTable()) #' #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' -#' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file -#' -#' @param start.inshape bool, defines trips to conclude (see Description) +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' -#' @param end.inshape bool, defines trips to conclude (see Description) +#' @param spatial_type character parameter,categories of spatial information used to specify which kind of trips should be filtered. Takes as input 4 templates: inside, outside, originating, destinating #' #' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) #' @@ -2862,14 +3449,32 @@ process_append_distcat <- function(trips_table,distances_array = c(1000,2000,500 process_filter_by_shape <- function(trips_table, shape_table, crs, - start.inshape = TRUE, end.inshape = TRUE) { - + spatial_type = "inside") { + + start.inshape <- TRUE + end.inshape <- TRUE + + if(spatial_type == "inside"){ + start.inshape <- TRUE + end.inshape <- TRUE + }else if(spatial_type == "outside"){ + start.inshape <- FALSE + end.inshape <- FALSE + }else if(spatial_type == "originating"){ + start.inshape <- TRUE + end.inshape <- FALSE + }else if(spatial_type == "destinating"){ + start.inshape <- FALSE + end.inshape <- TRUE + }else{ + stop("There are only 4 possible spatial_types: inside, outside, originating, destinating") + } # shape_table <- st_read(shapeFile) if (st_crs(shape_table) == NA) { st_crs(shape_table) <- crs } - sf_table <- transformToSf(trips_table, crs = crs, geometry.type = st_point()) + sf_table <- process_convert_table_to_sf(trips_table, crs = crs, geometry.type = st_point()) shape_table <- st_transform(shape_table, crs = crs) # shape_table isn't table - shape @@ -2903,10 +3508,79 @@ process_filter_by_shape <- function(trips_table, return(trips_table[cont_union, ]) } -#' Reads the coordinate reference system from an MATSim output directory -#' (output_config.xml) +#' Appending spatial category as additional column to output_trips tibble +#' +#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +#' and adds to the output_trips from table spatial category depending on postition related to shape file: +#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips \strong{inside} of the given shape +#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which \strong{originating} in the shape +#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which \strong{destinating} in the shape +#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which \strong{outside} of the given shape +#' +#' @param trips_table tibble of trips_output (from readTripsTable()) +#' +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' +#' @return tibble, with additional spatial column related to given shape +#' +#' @export +process_append_spatialcat <- function(trips_table, + shape_table, + crs) { + + start.inshape <- TRUE + end.inshape <- TRUE + + # shape_table <- st_read(shapeFile) + if (st_crs(shape_table) == NA) { + st_crs(shape_table) <- crs + } + + sf_table <- process_convert_table_to_sf(trips_table, crs = crs, geometry.type = st_point()) + shape_table <- st_transform(shape_table, crs = crs) + # shape_table isn't table - shape + + union_shape <- st_union(shape_table) # transforms the crs back to the previous in the file + union_shape <- st_transform(union_shape, crs = st_crs(shape_table)) + + + st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry + cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile + + st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry + cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile + + # get trips that ended outside of shape + cont_end_outside <- setdiff(1:nrow(sf_table), cont2) + + # get trips that started outside of shape + cont_start_outside <- setdiff(1:nrow(sf_table), cont1) + + cont_union_inside <- intersect(cont1,cont2) + cont_union_outside <- intersect(cont_start_outside,cont_end_outside) + cont_union_originating <- intersect(cont1,cont_end_outside) + cont_union_destinating <- intersect(cont2, cont_start_outside) + + trips_table$spatial_category = NA + + trips_table[cont_union_inside, ]$spatial_category <- "inside" + trips_table[cont_union_outside, ]$spatial_category <- "outside" + trips_table[cont_union_originating, ]$spatial_category <- "originating" + trips_table[cont_union_destinating, ]$spatial_category <- "destinating" + + + return(trips_table) +} + + +#' Reads an coordinate referenec system of MATSim output directory +#' from output_config.xml #' -#' @param config_path specifies path to configuration file +#' @param config_path specifies path to find config #' #' #' @return code of coordinate reference system @@ -2942,34 +3616,34 @@ process_get_crs_from_config <- function(config_path) { return(NA) } -#' Creates an origin/destination matrix either in conventional form (row names = origin, column names = destination) -#' or for simwrapper (origin and destination as columns) +#' Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper +#' #' #' -#' @param tripsTable tibble of trips_output (from \link{readTripsTable}) +#' @param tripsTable table of output trips(from readTripsTable) or path to trips_output file #' -#' @param shapePath string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file) +#' @param shapePath full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name) #' -#' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' -#' @param dump.output.to string, path to a folder to save the .csv file +#' @param dump.output.to path to a folder to save csv file of ODMatrix #' -#' @param colnames string, column names can be specified (i.e. to fit the shape file), if not they are numbered +#' @param colnames if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values #' -#' @param simwrapper boolean, creates output in the format used for simwrapper if the path for the shapefile is specified +#' @param simwrapper create output in a simwrapper form if set to path of the shapefile #' -#' @param outer boolean, determines if flows outside of the shapefile are used, standard value is FALSE +#' @param outer logical that represent if the table should contain outside flow of the shape, it isn't #' #' @return tibble of origin/destination matrix #' #' @export process_get_od_matrix<- function(tripsTable, - shapePath, - crs, - dump.output.to = matsimDumpOutputDirectory, - simwrapper = FALSE, - colnames = "numeric", - outer = FALSE){ + shapePath, + crs, + dump.output.to = matsimDumpOutputDirectory, + simwrapper = FALSE, + colnames = "numeric", + outer = FALSE){ defaultW <- getOption("warn") options(warn = -1) @@ -3052,35 +3726,36 @@ process_get_od_matrix<- function(tripsTable, result_melt = melt(as.matrix(result_tibble)) colnames(result_melt) = c("origin","destination",1) - # Generating yaml and output_files + # Generating yaml and output_files + # We remove it from new version, but still we are gonna use it in generate simwrapper of new version - if (file.exists(dump.output.to) & simwrapper == TRUE) { - write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") - } else if(!file.exists(dump.output.to) & simwrapper == TRUE) { - dir.create(dump.output.to) - write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") - } else if (file.exists(dump.output.to) & simwrapper == FALSE) { - write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) - } else { - dir.create(dump.output.to) - write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) - } - - yaml_list <- list( - title = "OD Flow", - description = "generated by deriveODMatrix", - projection = st_crs(shape)$input, - shpFile = paste0("../",shapePath), - dbfFile = paste0("../",substr(shapePath,start = 1,stop = nchar(shapePath)-3),"dbf"), - scaleFactor = 1, - lineWidth = 50, - csvFile = "ODMatrix.csv", - idColumn = colnames(shape)[1] # at the moment idColumn of shapefile should be the first column - - ) - write_yaml(yaml_list, paste0(dump.output.to, "/viz-od-flow.yaml")) + # if (file.exists(dump.output.to) & simwrapper == TRUE) { + # write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") + # } else if(!file.exists(dump.output.to) & simwrapper == TRUE) { + # dir.create(dump.output.to) + # write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") + # } else if (file.exists(dump.output.to) & simwrapper == FALSE) { + # write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) + # } else { + # dir.create(dump.output.to) + # write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) + # } + # + # yaml_list <- list( + # title = "OD Flow", + # description = "generated by deriveODMatrix", + # projection = st_crs(shape)$input, + # shpFile = paste0("../",shapePath), + # dbfFile = paste0("../",substr(shapePath,start = 1,stop = nchar(shapePath)-3),"dbf"), + # scaleFactor = 1, + # lineWidth = 50, + # csvFile = "ODMatrix.csv", + # idColumn = colnames(shape)[1] # at the moment idColumn of shapefile should be the first column + # + # ) + # write_yaml(yaml_list, paste0(dump.output.to, "/viz-od-flow.yaml")) options(warn = defaultW) return(result_tibble) @@ -3088,29 +3763,33 @@ process_get_od_matrix<- function(tripsTable, -#' Transforms the data frame trips_output (from \links{readTripsTable}) from tibble to sf (table with geometry features) +#' Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature) #' -#' Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features. -#' If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format), -#' if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt. -#' Added column/columns are projected to given CRS (coordinate reference system). -#' The columns start_x, end_x, start_y, end_y are deleted from the resulting data frame. +#' Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features +#' deletes from resulting data.frame start_x, end_x, start_y, end_y. +#' And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring() +#' Or adds start_wkt and end_wkt, if geometry.type = st_point() +#' Added column/columns projected to given CRS (coordinate reference system), +#' that can be taken from network file of MATSimOutputDirectory #' -#' @param table tibble trips_output (from readTripsTable()) +#' Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" +#' to get which type of table was generated, if it is needed #' -#' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file +#' @param table tibble of trips_output (from readTripsTable()) +#' +#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' -#' @param geometry.type type of sf transformation, default is st_multipoint(), geometry.type can be: -#' !!!st_point()- resulting table contains two geometry columns: start_wkt and end_wkt, representing start and end points as POINTS!!! or -#' !!!st_multipoint()- resulting table contains one geometry column, representing start and end points as MULTIPOINT!!! or -#' !!!st_linestring() - resulting table contains one geometry column, representing the line between start and end points as LINESTRING!!! +#' @param geometry.type function of sf transformation, geometry.type can be (by default is st_multipoint()) +#' !!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or +#' !!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or +#' !!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!! #' -#' @return sf object (data frame with geometries depending on geometry.type) +#' @return sf object (data.frame with geometries depending to geometry.type) #' #' @export -transformToSf <- function(table, - crs, - geometry.type = st_multipoint()) { +process_convert_table_to_sf <- function(table, + crs, + geometry.type = st_multipoint()) { if (class(geometry.type)[2] == "POINT") { table1 <- table %>% # mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep ="")) @@ -3158,3 +3837,5 @@ transformToSf <- function(table, #####Helping functions#### + + diff --git a/R/simwrapper.R b/R/simwrapper.R index f128bda..08321d1 100644 --- a/R/simwrapper.R +++ b/R/simwrapper.R @@ -1,12 +1,12 @@ -#' Creates dashboard for the given table or folder with data -#' + +#' Creates dashboard for the given table with data #' #' #' @param table trips_output tibble from readTripsTable() #' -#' @param append specifies if the ouput folder should be erased before creating +#' @param append specifies if the ouput folder should be erased before creating, default = FALSE #' -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard and all plots using functions: +#' @param dump.output.to output folder, yaml files and plots from the following functions are saved there: #' plotModalSplitBarChart(),plotModalSplitPieChart(),plotModalShift(). #' #' @return generates folder with content for simwrapper out of trips table @@ -32,17 +32,17 @@ prepareSimwrapperDashboardFromTable <- function(table, dump.output.to = matsimDu -#' Creates dashboard for the given table or folder with data +#' Creates dashboard for the given folder with data #' #' #' -#' @param folder specifies data source folder with tripsOutput +#' @param folder file path, specifies data source folder that includes a output_trips.csv file #' -#' @param append specifies if the ouput folder should be erased before creating +#' @param append specifies if the ouput folder should be erased before creating, default = FALSE #' -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard and all plots +#' @param dump.output.to output folder, yaml files are saved there #' -#' @return tibble of output_trips from folder. Generates content needed for Simwrapper +#' @return tibble of output_trips from folder and content needed for Simwrapper #' #' @export prepareSimwrapperDashboardFromFolder <- function(folder,dump.output.to = matsimDumpOutputDirectory, append = FALSE) { @@ -59,11 +59,11 @@ prepareSimwrapperDashboardFromFolder <- function(folder,dump.output.to = matsimD #' Creates/adds XY hexagon definition of output trips to a summary dashboard #' -#' @param pathToOutputTrips specifies path to a data source of output_trips +#' @param pathToOutputTrips file path to output_trips.csv file #' -#' @param crs specifies an coordinate reference system of output_trips +#' @param crs specifies the coordinate reference system of output_trips #' -#' @param dump.output.to path to an folder with dashboard +#' @param dump.output.to path to a folder with simwrapper dashboard #' #' @return changed file #' @@ -127,7 +127,7 @@ clearDashboard<- function(matsimOutputFolder){ -#' Creates comparison dashboard for the 2 given tables or folder with data +#' Creates comparison dashboard for the two given tables or folders with data #' #' #' @@ -135,12 +135,12 @@ clearDashboard<- function(matsimOutputFolder){ #' #' @param table2 trips_output tibble from readTripsTable() #' -#' @param append specifies if the ouput folder should be erased before creating +#' @param append specifies if the output folder should be erased before creating, default = FALSE #' -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard and all plots using functions: +#' @param dump.output.to output folder, yaml files and plots from the following functions are saved there: #' plotModalSplitBarChart(),plotModalSplitPieChart(),plotModalShift(). #' -#' @return generates folder with content for simwrapper out of trips table +#' @return generates folder with content for simwrapper from a trips table #' #' @export prepareComparisonSimwrapperDashboardFromTable <- function(table1,table2, dump.output.to = matsimDumpOutputDirectory, append = FALSE) { From 25f8e852666a37302bc80ac444c1c5c67e88a42a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Mon, 26 Jun 2023 14:06:39 +0200 Subject: [PATCH 39/87] WIP documentation to merge --- R/output_trips.R | 2147 ++++++++++++++++------------------------------ 1 file changed, 733 insertions(+), 1414 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 9570456..41a9faa 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -1,4 +1,3 @@ - #####Variables#### matsimDumpOutputDirectory <- "./matsim_r_output" @@ -17,22 +16,12 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' #' These functions are provided for compatibility with older version of #' the matsimr package. They may eventually be completely -#' removed.\cr\cr -#' \strong{plotModalSplitPieChart} - Takes Table trips_output (from readTripsTable()), -#' to plot pie chart with with values that represent -#' percentage of using transport modes from trips -#' -#' @rdname matsimr-deprecated -#' @name matsimr-deprecated +#' removed. #' #' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' -#' @return \strong{plotModalSplitPieChart} - Pie Chart plot of transport mode distribution, values given in percents +#' @rdname matsimr-deprecated +#' @name matsimr-deprecated #' #' @docType package #' @export plotModalSplitPieChart @@ -55,7 +44,7 @@ plotModalSplitPieChart <- function(tripsTable, tripsTable$main_mode[grep(paste0(unite.columns, collapse = "|"), tripsTable$main_mode)] <- united.name } - # tripsTableCount gives percentage representation out + # calculates the mode share and saves it as a tibble tripsTableCount <- tripsTable %>% count(main_mode) %>% mutate(n = n / sum(n) * 100) @@ -81,6 +70,7 @@ plotModalSplitPieChart <- function(tripsTable, ggtitle("Distribution of transport type") + theme_void() plt + if (file.exists(dump.output.to)) { ggsave(paste0(dump.output.to, "/modalSplitPieChart.png"),width = 6,height = 10, plt) } else { @@ -133,21 +123,9 @@ plotModalSplitPieChart <- function(tripsTable, } #' Deprecated function(s) in the matsimr package #' -#' \strong{plotModalSplitBarChart} - Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' percentage of using transport modes from trips #' #' @rdname matsimr-deprecated #' -#' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' -#' @return \strong{plotModalSplitBarChart} - Bar Chart plot of transport mode distribution, values given in percents -#' #' @docType package #' @export plotModalSplitBarChart #' @aliases plotModalSplitBarChart @@ -240,15 +218,14 @@ plotModalSplitBarChart <- function(tripsTable, #' **Deprecated. (see matsimr-deprecated)** Load MATSIM output_trips table into Memory #' -#' \strong{readTripsTable} - Loads a MATSim CSV output_trips from file or archive, -#' creating a tibble with columns as in csv file +#' Loads a MATSim output_trips file from file or archive path, +#' creating a tibble #' -#' @rdname matsimr-deprecated #' @name readTripsTable #' -#' @param input_path character string, path to matsim output directory or http link to the file. +#' @param input_path character string, path to MATSim output directory or http link to the file. #' @param n_max integer, maximum number of lines to read within output_trips -#' @return \strong{readTripsTable} - tibble of trips_output +#' @return tibble of trips_output #' #' @export readTripsTable <-function(input_path = ".", n_max = Inf) { @@ -259,23 +236,8 @@ readTripsTable <-function(input_path = ".", n_max = Inf) { #' Deprecated function(s) in the matsimr package #' #' -#' \strong{plotAverageTravelWait} - Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' time spent on traveling/waiting -#' Using parameters unite.columns, specific columns could be given, -#' to unite them in 1 mode with the name united.name(by default 'united') -#' -#' -#' #' @rdname matsimr-deprecated #' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' -#' @return \strong{plotAverageTravelWait} - Bar Chart plot of average time spent on travel/wait #' @docType package #' @export plotAverageTravelWait #' @aliases plotAverageTravelWait @@ -309,8 +271,6 @@ plotAverageTravelWait <- function(tripsTable, unite.columns = character(0), unit } -###Needs to be added, because in master there isn't propper documentation - #' Deprecated function(s) in the matsimr package #' #' @@ -369,9 +329,9 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch } -#' Deprecated function(s) in the matsimr package +#' Bar Chart with distance travelled on x-axis and number of trips on y-axis #' -#' \strong{plotModalDistanceDistribution} - Takes Table trips_output (from readTripsTable()), +#' Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' number of trips ~ distance travelled #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') @@ -386,8 +346,7 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' -#' @return \strong{plotModalDistanceDistribution} Bar Chart plot of count of trips among distance travelled +#' @return Bar Chart plot of count of trips among distance travelled #' #' @export plotModalDistanceDistribution <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, @@ -465,14 +424,13 @@ plotModalDistanceDistribution <- function(tripsTable, unite.columns = character( } -#' Deprecated function(s) in the matsimr package +#' Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis #' -#' \strong{compareModalDistanceDistribution} - Takes 2 Tables trips_output (from readTripsTable()), +#' Takes 2 Tables trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' -#' @rdname matsimr-deprecated #' #' @param tripsTable1 tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 #' @param tripsTable2 tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted @@ -480,7 +438,7 @@ plotModalDistanceDistribution <- function(tripsTable, unite.columns = character( #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' @return \strong{compareModalDistanceDistribution} - Bar Chart plot of count of trips among distance travelled +#' @return Bar Chart plot of count of trips among distance travelled #' #' @export compareModalDistanceDistribution <- function(tripsTable1,tripsTable2, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, @@ -542,21 +500,21 @@ compareModalDistanceDistribution <- function(tripsTable1,tripsTable2, unite.colu } -#' Deprecated function(s) in the matsimr package +#' Bar Chart with distance travelled on x-axis and number of trips on y-axis #' -#' \strong{plotTripDistanceByMode} - Takes Table trips_output (from readTripsTable()), +#' Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' average distance traveled ~ main mode used #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' -#' @rdname matsimr-deprecated +#' #' @param tripsTable tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' -#' @return \strong{plotTripDistanceByMode} - Bar Chart plot of distance traveled per mode +#' @return Bar Chart plot of distance traveled per mode #' #' @export plotTripDistanceByMode <- function(tripsTable, @@ -597,21 +555,20 @@ plotTripDistanceByMode <- function(tripsTable, -#' Deprecated function(s) in the matsimr package +#' Line plot with departure time x-axis and number of trips on y-axis #' -#' \strong{plotTripCountByDepTime} - Takes Table trips_output (from readTripsTable()), +#' Takes Table trips_output (from readTripsTable()), #' to make line plot with with values that represent #' count of trips for a specific departure time by main_mode #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' -#' @rdname matsimr-deprecated #' #' @param tripsTable tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' @return \strong{plotTripCountByDepTime} - Line Chart plot of trips count by departure mode per mode +#' @return Line Chart plot of trips count by departure mode per mode #' #' @export plotTripCountByDepTime <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, @@ -671,21 +628,21 @@ plotTripCountByDepTime <- function(tripsTable, unite.columns = character(0), uni } } -#' Deprecated function(s) in the matsimr package +#' Line plot that shows the number of activities ending at a given time, per activity type. +#' The activity end time is derived from the departure time in the given trips tibble. #' -#' \strong{plotActivityEndTimes} - Takes Table trips_output (from readTripsTable()), +#' Takes Table trips_output (from readTripsTable()), #' to make line plot with with values that represent the #' number of activities ending at a specific time. #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' -#' @rdname matsimr-deprecated #' #' @param tripsTable tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly -#' @return \strong{plotActivityEndTimes} Line plot with departure time x-axis and number start activities on y-axis +#' @return Line plot with departure time x-axis and number start activities on y-axis #' #' @export plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, @@ -749,14 +706,14 @@ plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), unite } -#' Deprecated function(s) in the matsimr package +#' This function plots the number of trips ending per trip purpose over time. The trip purpose corresponds to the activity type of the destination activity of a given trip. +#' Thus, the y-axis of the plot can also be interpreted as the number of activities starting (based on the assumption that trip end time = activity start time). #' -#' \strong{plotArrivalTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), +#' Takes Table trips_output (from readTripsTable()), #' to make line plot with with values that represent #' count of destination activities for a specific arrival time #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' -#' @rdname matsimr-deprecated #' #' @param tripsTable tibble of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns @@ -764,7 +721,7 @@ plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), unite #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' -#' @return \strong{plotArrivalTimesPerTripPurpose} - Line plot with arrival time x-axis and number end activities on y-axis +#' @return Line plot with arrival time x-axis and number end activities on y-axis #' #' @export plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, @@ -870,14 +827,13 @@ plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character } -#' Deprecated function(s) in the matsimr package +#' This function plots the number of trips starting per trip purpose over time. The trip purpose corresponds to the activity type of the destination activity of a given trip. #' -#' \strong{plotDepartureTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), +#' Takes Table trips_output (from readTripsTable()), #' to make line plot with with values that represent #' count of destination activities for a specific arrival time #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' -#' @rdname matsimr-deprecated #' #' @param tripsTable tibble of trips_output (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns @@ -885,11 +841,10 @@ plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' -#' @return \strong{plotDepartureTimesPerTripPurpose} - Line plot with arrival time x-axis and number end activities on y-axis +#' @return Line plot with arrival time x-axis and number end activities on y-axis #' #' @export -plotDepartureTimesPerTripPurpose <- function(tripsTable, unite.columns = character(0), united.name = "united", - dump.output.to = matsimDumpOutputDirectory, +plotDepartureTimesPerTripPurpose <- function(tripsTable, unite.columns = character(0), united.name = "united",dump.output.to = matsimDumpOutputDirectory, only.files = FALSE) { @@ -943,20 +898,19 @@ plotDepartureTimesPerTripPurpose <- function(tripsTable, unite.columns = charact } -#' Deprecated function(s) in the matsimr package +#' Bar Chart with tripType on x-axis and travelled distance on y-axis #' -#' \strong{plotTripDistancedByType} - Takes Table trips_output (from readTripsTable()), +#' Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' travelled distance of each tripType related to the shapeTable #' -#' @rdname matsimr-deprecated #' #' @param tripsTable tible of trips_output (from readTripsTable()) #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' -#' @return \strong{plotTripDistancedByType} - Bar Chart plot of distance traveled by type +#' @return Bar Chart plot of distance traveled by type #' #' @export plotTripDistancedByType <- function(tripsTable,shapeTable,crs,dump.output.to = matsimDumpOutputDirectory) { @@ -983,19 +937,18 @@ plotTripDistancedByType <- function(tripsTable,shapeTable,crs,dump.output.to = m -#' Deprecated function(s) in the matsimr package +#' Plot alluvial/sankey diagram of transport mode changes #' -#' \strong{plotModalShiftSankey} - Takes two trips_table (from readTripsTable), and collects +#' Takes two trips_table (from readTripsTable), and collects #' changes between transport mode distribution of these tables -#' to make alluvial diagram from this data\cr +#' to make alluvial diagram from this data +#' #' Function calculates number of each transport mode used in #' first and second table, and draws plot that represent how #' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) #' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") #' Using parameter show.onlyChanges #' -#' @rdname matsimr-deprecated -#' #' @param tripsTable1 tible of trips_output (from readTripsTable()) #' @param tripsTable2 tible of trips_output (from readTripsTable()) #' @param show.onlyChanges boolean, if it is set to TRUE => sankey diagram only contains changes on axes @@ -1003,7 +956,7 @@ plotTripDistancedByType <- function(tripsTable,shapeTable,crs,dump.output.to = m #' @param united.name if columns were united, you can specify name for the resulting column in plot #' @param dump.output.to folder that saves and configures yaml for simwrapper. folder where png of plot is stored #' -#' @return \strong{plotModalShiftSankey} - Alluvial diagram that represents changes in transport mode distribution of trip tables +#' @return Alluvial diagram that represents changes in transport mode distribution of trip tables #' #' @export plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FALSE, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory) { @@ -1053,24 +1006,25 @@ plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FA return(plt) } -#' Deprecated function(s) in the matsimr package +#' Plot bar chart diagram of transport mode changes #' -#' \strong{plotModalShiftBar} - Takes two trips_table (from readTripsTable), and collects +#' Takes two trips_table (from readTripsTable), and collects #' changes between transport mode distribution of these tables -#' to make bar chart diagram with dodging positioning from this data\cr +#' to make bar chart diagram with dodging positioning from this data +#' #' Function calculates number of each transport mode used in #' first and second table, and draws plot that represent how #' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) #' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") #' Using parameter show.onlyChanges -#' @rdname matsimr-deprecated +#' #' @param tripsTable1 tible of trips_output (from readTripsTable()) #' @param tripsTable2 tible of trips_output (from readTripsTable()) #' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name if columns were united, you can specify name for the resulting column in plot #' @param dump.output.to folder that saves and configures yaml for simwrapper. folder where png of plot is stored #' -#' @return \strong{plotModalShiftBar} - plots Bar Chart of transport mode changes with additional files for simwrapper +#' @return plots Bar Chart of transport mode changes with additional files for simwrapper #' #' @export plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, @@ -1098,18 +1052,17 @@ plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = characte -#' Deprecated function(s) in the matsimr package +#' Plots result of filtered trips on the map (from shape) #' -#' \strong{plotMapWithFilteredTrips} - Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file)) +#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file)) #' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -#' and filters the trips from table depending on *.inshape flags:\cr +#' and filters the trips from table depending on *.inshape flags: #' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -#' \cr if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -#' \cr if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -#' \cr if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape -#' \cr result of filtering is plotted on map of shapeTable where green points are startpoints of trip and red points are endpoints of trip +#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +#' result of filtering is plotted on map of shapeTable where green points are startpoints of trip and red points are endpoints of trip #' -#' @rdname matsimr-deprecated #' @param table tibble of trips_output (from readTripsTable()) #' #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) @@ -1123,7 +1076,7 @@ plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = characte #' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot #' #' -#' @return \strong{plotMapWithFilteredTrips} - plot with trips filtered depending on flags *.inshape on map from shapeTable +#' @return plot with trips filtered depending on flags *.inshape on map from shapeTable #' #' @export plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRUE, end.inshape = TRUE, optimized = FALSE) { @@ -1255,11 +1208,8 @@ plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRU return(plt) } - -#' Deprecated function(s) in the matsimr package +#' Plots start and end coordinates of the given trips table on an osm map #' -#' \strong{plotMapWithTrips} - Plots start and end coordinates of the given trips table on an osm map -#' @rdname matsimr-deprecated #' @param table tibble of trips_output (from readTripsTable()) #' #' @@ -1268,11 +1218,10 @@ plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRU #' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot #' #' -#' @return \strong{plotMapWithTrips} - plot with trips +#' @return plot with trips #' #' @export plotMapWithTrips <- function(table, crs, optimized = FALSE) { - table_sf <- transformToSf(table, crs = crs, geometry.type = st_point()) st_geometry(table_sf) <- "start_wkt" table_sf_start <- table_sf %>% select(-end_wkt) @@ -1381,15 +1330,13 @@ plotMapWithTrips <- function(table, crs, optimized = FALSE) { # position it on the topleft position = "topleft" ) - plt + return(plt) } -#' Deprecated function(s) in the matsimr package +#' Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart #' -#' \strong{plotTripTypesPieChart} - plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart #' -#' @rdname matsimr-deprecated #' #' @param table tibble of trips_output (from readTripsTable()) #' @@ -1399,12 +1346,11 @@ plotMapWithTrips <- function(table, crs, optimized = FALSE) { #' #' #' -#' @return \strong{plotTripTypesPieChart} - plot with percentage of each type of trips +#' @return plot with percentage of each type of trips #' #' @export plotTripTypesPieChart <- function(table, shapeTable, crs) { - .Deprecated("") # table_sf = transformToSf(table,crs = crs) # Maybe union all this tables as 1 extended with additional column filtered_inside <- filterByRegion(table, shapeTable, crs = crs, start.inshape = TRUE, end.inshape = TRUE) @@ -1443,13 +1389,10 @@ plotTripTypesPieChart <- function(table, shapeTable, crs) { ggtitle("Distribution")) } - -#' Deprecated function(s) in the matsimr package -#' -#' \strong{compareTripTypesBarChart} - Creates BarChart of changing trip types(originating,transit etc) between 2 tables +#' Creates BarChart of changing trip types(originating,transit etc) between 2 tables #' and saves output to dump.output.to #' -#' @rdname matsimr-deprecated +#' #' #' @param tripsTable1 tibble of trips_output (from readTripsTable(),f.e. base case) #' @@ -1462,7 +1405,7 @@ plotTripTypesPieChart <- function(table, shapeTable, crs) { #' @param dump.output.to folder that saves resulting image of BarChart #' #' -#' @return \strong{compareTripTypesBarChart} - plot with percentage of each type of trips between 2 tables +#' @return plot with percentage of each type of trips between 2 tables #' #' @export compareTripTypesBarChart <- function(tripsTable1,tripsTable2,shapeTable,crs,dump.output.to = matsimDumpOutputDirectory){ @@ -1506,12 +1449,9 @@ compareTripTypesBarChart <- function(tripsTable1,tripsTable2,shapeTable,crs,dump } - -#' Deprecated function(s) in the matsimr package +#' Plots every type of trips(inside, outside, origin and destinating) on map #' -#' \strong{plotMapWithTripsType} - plots every type of trips(inside, outside, origin and destinating) on map #' -#' @rdname matsimr-deprecated #' #' @param table tibble of trips_output (from readTripsTable()) #' @@ -1521,7 +1461,7 @@ compareTripTypesBarChart <- function(tripsTable1,tripsTable2,shapeTable,crs,dump #' #' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot #' -#' @return \strong{plotMapWithTripsType} - plot that contains every trip with defined trip type +#' @return plot that contains every trip with defined trip type #' #' @export plotMapWithTripsType <- function(table, shapeTable, crs, optimized = FALSE) { @@ -1741,12 +1681,11 @@ plotMapWithTripsType <- function(table, shapeTable, crs, optimized = FALSE) { } -#' Deprecated function(s) in the matsimr package -#' -#' \strong{compareBasePolicyOutput} - Chooses a function to compare output_trips from the folders. + +#' Chooses a function to compare output_trips from the folders. #' baseFolder contains all base outputs, policyFolder contains all policy outputs. #' -#' @rdname matsimr-deprecated +#' #' #' @param baseFolder specifies data source folder with multiple base output_trips #' @@ -1755,7 +1694,7 @@ plotMapWithTripsType <- function(table, shapeTable, crs, optimized = FALSE) { #' @param dump.output.to that saves result of all comparisons between each base and each policy. #' For now it creates plotModalShiftBar() for the output_trips #' -#' @return \strong{compareBasePolicyOutput} - list of tibbles, list of all base and policy output_trips as tibble +#' @return list of tibbles, list of all base and policy output_trips as tibble #' #' @export compareBasePolicyOutput <- function(baseFolder,policyFolder,dump.output.to = matsimDumpOutputDirectory) { @@ -1808,13 +1747,10 @@ compareBasePolicyOutput <- function(baseFolder,policyFolder,dump.output.to = mat } invisible(list(base = base_trips,policy = policy_trips)) } - -#' Deprecated function(s) in the matsimr package -#' -#' \strong{compareBasePolicyShapeOutput} - Chooses a function to compare output_trips from the folders. +#' Chooses a function to compare output_trips from the folders. #' baseFolder contains all base outputs, policyFolder contains all policy outputs. #' -#' @rdname matsimr-deprecated +#' #' #' @param baseFolder specifies data source folder with multiple base output_trips #' @@ -1825,7 +1761,7 @@ compareBasePolicyOutput <- function(baseFolder,policyFolder,dump.output.to = mat #' @param dump.output.to that saves result of all comparisons between each base and each policy. #' For now it creates plotModalShiftBar() for the output_trips #' -#' @return \strong{compareBasePolicyShapeOutput} - list of tibbles, list of all base and policy output_trips as tibble +#' @return list of tibbles, list of all base and policy output_trips as tibble #' #' @export compareBasePolicyShapeOutput <- function(baseFolder,policyFolder,shapeFilePath,crs,dump.output.to = matsimDumpOutputDirectory) { @@ -1883,15 +1819,13 @@ compareBasePolicyShapeOutput <- function(baseFolder,policyFolder,shapeFilePath,c #' Deprecated function(s) in the matsimr package #' -#' \strong{appendDistanceCategory} - adds to trips output tibble additional column that represent distance as category #' #' @rdname matsimr-deprecated #' -#' @return tibble of output_trips with distance category column -#' #' @docType package +#' @export compareAverageTravelWait +#' @aliases compareAverageTravelWait #' -#' @export appendDistanceCategory <- function(tripsTable){ .Deprecated("process_append_distcat") @@ -1925,9 +1859,8 @@ appendDistanceCategory <- function(tripsTable){ return(tripsTable_result) } -#' Deprecated function(s) in the matsimr package +#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape #' -#' \strong{filterByRegion} - Filtering of trips_table(from readTripsTable) depending on how they located in given shape\cr #' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). #' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) #' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) @@ -1947,7 +1880,7 @@ appendDistanceCategory <- function(tripsTable){ #' #' @param end.inshape bool, defines trips to conclude (see Description) #' -#' @return \strong{filterByRegion} - tibble, with filtered trips depending on shapeTable and special flags (see Description) +#' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) #' #' @export filterByRegion <- function(tripsTable, @@ -1995,12 +1928,9 @@ filterByRegion <- function(tripsTable, } - -#' Deprecated function(s) in the matsimr package +#' Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper #' -#' \strong{deriveODMatrix} - Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper #' -#' @rdname matsimr-deprecated #' #' @param tripsTable table of output trips(from readTripsTable) or path to trips_output file #' @@ -2016,7 +1946,7 @@ filterByRegion <- function(tripsTable, #' #' @param outer logical that represent if the table should contain outside flow of the shape, it isn't #' -#' @return \strong{deriveODMatrix} - tibble of origin/destination matrix +#' @return tibble of origin/destination matrix #' #' @export deriveODMatrix<- function(tripsTable, @@ -2142,17 +2072,14 @@ deriveODMatrix<- function(tripsTable, return(result_tibble) } -#' Deprecated function(s) in the matsimr package -#' -#' \strong{getCrsFromConfig} - Reads an coordinate referenec system of MATSim output directory + +#' Reads an coordinate reference system of MATSim output directory #' from output_config.xml #' -#' @rdname matsimr-deprecated -#' #' @param folder specifies path to find config #' #' -#' @return \strong{getCrsFromConfig} - code of coordinate reference system +#' @return code of coordinate reference system #' #' @export getCrsFromConfig <- function(folder) { @@ -2185,93 +2112,16 @@ getCrsFromConfig <- function(folder) { return(NA) } - -#' Deprecated function(s) in the matsimr package -#' -#' \strong{transformToSf} - Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature)\cr -#' Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features -#' deletes from resulting data.frame start_x, end_x, start_y, end_y.\cr -#' And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring()\cr -#' Or adds start_wkt and end_wkt, if geometry.type = st_point()\cr -#' Added column/columns projected to given CRS (coordinate reference system), -#' that can be taken from network file of MATSimOutputDirectory\cr -#' Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" -#' to get which type of table was generated, if it is needed -#' -#' @param table tibble of trips_output (from readTripsTable()) -#' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation -#' -#' @param geometry.type function of sf transformation, geometry.type can be (by default is st_multipoint()) -#' !!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or -#' !!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or -#' !!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!! -#' -#' @return \strong{transformToSf} - sf object (data.frame with geometries depending to geometry.type) -#' -#' @export -transformToSf <- function(table, - crs, - geometry.type = st_multipoint()) { - - .Deprecated("process_convert_table_to_sf") - - if (class(geometry.type)[2] == "POINT") { - table1 <- table %>% - # mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep ="")) - mutate(start_wkt = paste("POINT(", start_x, " ", start_y, ")", sep = "")) - table2 <- table %>% - mutate(end_wkt = paste("POINT(", end_x, " ", end_y, ")", sep = "")) - attr(table, "geometry.type") <- "POINT" - - - table1_wkt <- st_as_sf(table1, wkt = "start_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - table2_wkt <- st_as_sf(table2, wkt = "end_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - - - result_table <- table1_wkt %>% mutate(end_wkt = table2_wkt$end_wkt) - st_geometry(result_table) <- "start_wkt" - st_crs(result_table) <- crs - st_geometry(result_table) <- "end_wkt" - st_crs(result_table) <- crs - st_geometry(result_table) <- "start_wkt" - return(result_table) - } else if (class(geometry.type)[2] == "MULTIPOINT") { - table <- table %>% - mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) - attr(table, "geometry.type") <- "MULTIPOINT" - - - result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - - st_crs(result_table) <- crs - return(result_table) - } else if (class(geometry.type)[2] == "LINESTRING") { - table <- table %>% - mutate(wkt = paste("LINESTRING(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) - attr(table, "geometry.type") <- "LINESTRING" - - - result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - - st_crs(result_table) <- crs - return(result_table) - } else { - return(NA) - } -} - - #####Reading##### -#' Load MATSIM output_trips table into Memory +#' Load MATSIM output_trips table into memory #' #' Loads a MATSim CSV output_trips from file or archive, #' creating a tibble with columns as in csv file #' -#' @param input_path character string, path to matsim output directory or http link to the file. -#' @param n_max integer, maximum number of lines to read within output_trips +#' @param input_path character string, path to the MATSim output directory or http link to the file. +#' @param n_max optional, integer, maximum number of lines to read, standard value is Inf #' @return tibble of trips_output #' #' @export @@ -2307,7 +2157,7 @@ read_output_trips <- function(input_path = ".", n_max = Inf) { ) ) # person is mostly integer, but contains also chars(see Hamburg 110813 observation) - # doesn't reads coordinates correctly + # doesn't read coordinates correctly trips_output_table <- trips_output_table %>% mutate( start_x = as.double(start_x), @@ -2324,34 +2174,34 @@ read_output_trips <- function(input_path = ".", n_max = Inf) { #####Plotting##### -#' Plot main_mode distribution as a Pie Chart +#' Plot the distribution of modes as a pie chart #' -#' Takes Table trips_output (from \link{readTripsTable}), -#' to plot pie chart with with values that represent -#' percentage of using transport modes from trips +#' Uses the dataframe trips_output (from \link{readTripsTable}), +#' to plot a pie chart of the modal split using the column main_mode #' -#' Function automatically detects transport_modes from table -#' and plots pie chart. -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' The function automatically detects the modes plots a pie chart. +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' @param trips_table tibble of trips_output (from \link{readTripsTable}) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' -#' @return Pie Chart plot of transport mode distribution, values given in percents +#' @return pie chart plot of transport mode distribution, values given in percent #' #' @export plot_mainmode_piechart <- function(trips_table, - unite.columns = character(0), united.name = "united", + unite.modes = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory) { - # If some columns should be united + # renaming/uniting of modes trips_table = process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) # processing - # tripsTableCount gives percentage representation out + # calculates the mode share and saves it as a tibble trips_table_count<-process_get_mainmode_distribution(trips_table, percentage= percentage) @@ -2366,35 +2216,37 @@ plot_mainmode_piechart <- function(trips_table, } -#' Plot main_mode distribution as a bar Chart +#' Plot the distribution of modes as a bar chart #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' percentage of using transport modes from trips +#' Takes the data frame trips_output (from \link{readTripsTable()}) +#' to plot a bar chart of the modal split using the column main_mode. #' -#' Function automatically detects transport_modes from table -#' and plots pie chart with percentage of distribution. -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' The modal shares are given in percentages. #' +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' -#' @param trips_table tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' +#' @param trips_table tibble of trips_output (from \link{readTripsTable()}) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' #' @return Bar Chart plot of transport mode distribution, values given in percents #' #' @export plot_mainmode_barchart <- function(trips_table, - unite.columns = character(0), + unite.modes = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, percentage = FALSE) { - # If some columns should be united + # renaming/uniting of modes trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) # processing + # calculates the mode share and saves it as a tibble trips_table_count <- process_get_mainmode_distribution(trips_table, percentage = percentage) @@ -2408,32 +2260,33 @@ plot_mainmode_barchart <- function(trips_table, return(fig) } -#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis +#' Plot travel and wait time for each mode as a bar chart #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' time spent on traveling/waiting -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes the data frame trips_output (from \links{readTripsTable()}), +#' to plot a bar chart of travel and wait times. +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param trips_table tibble of trips_output (from \links{readTripsTable()}) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' #' @return Bar Chart plot of average time spent on travel/wait #' #' @export plot_travelwaittime_mean_barchart <- function(trips_table, - unite.columns = character(0), + unite.modes = character(0), united.name = "united", time_format = "minute") { - # If some columns should be united + # renaming/uniting of modes trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) - #processing of result table + #processing avg_time = process_get_travelwaittime_by_mainmode(trips_table,time_format = time_format) #plotting @@ -2453,31 +2306,97 @@ plot_travelwaittime_mean_barchart <- function(trips_table, +#' Bar Chart comparing two runs with main_mode on x-axis and average travel/wait time on y-axis +#' +#' Takes two data frames (from \link{readTripsTable()}), +#' to plot a comparison bar chart of travel and wait times. +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' +#' +#' @param tripsTable1 tibble of trips_output (from readTripsTable()) +#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode +#' +#' @return Bar chart plot comparing average time spent on travel/wait of two runs +#' +#' @export +plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, + unite.modes = character(0), + united.name = "united", + time_format = "minute") { + + #TODO: + # . Document and add title to show what means positive/negative value + # . think about comparing processing functions they can appear in future often + -#' Bar Chart with distance travelled on x-axis and number of trips on y-axis + # renaming/uniting of modes + trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, + unite.modes = unite.modes, + united.name = united.name) + + trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, + unite.modes = unite.modes, + united.name = united.name) + + #processing + avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) + + + + avg_time2 = process_get_travelwaittime_by_mainmode(trips_table2,time_format = time_format) + + + avg_time = full_join(avg_time1, avg_time2, by = "main_mode") %>% + replace_na(list(trav_time_avg.x = 0,wait_time_avg.x = 0,trav_time_avg.y = 0,wait_time_avg.y = 0)) + + + + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg.x - trav_time_avg.y, + wait_time_avg =wait_time_avg.x - wait_time_avg.y )%>% + select(-wait_time_avg.x,-wait_time_avg.y, -trav_time_avg.x,-trav_time_avg.y) + + + + #plotting + fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") + fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") + fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)")),barmode = "group") + + + fig + return(fig) + +} + +#' Bar Chart with distance traveled on x-axis and number of trips on y-axis #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' number of trips ~ distance travelled -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes the data frame trips_output (from \link{readTripsTable()}) and categorizes the traveled distances into pre-defined bins +#' to plot a histogram of the traveled distances. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param trips_table tibble of trips_output (from readTripsTable()) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' @return Bar Chart plot of count of trips among distance travelled #' #' @export plot_distcat_by_mainmode_barchart <- function(trips_table, - unite.columns = character(0), + unite.modes = character(0), united.name = "united", dist_column = "dist_cat", distances_array = c(1000,2000,5000,10000,20000,50000,100000)) { - # If some columns should be united + # renaming/uniting of modes trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) #processing @@ -2496,17 +2415,18 @@ plot_distcat_by_mainmode_barchart <- function(trips_table, } -#' Bar Chart with distance travelled on x-axis and number of trips on y-axis +#' Bar chart with average distance traveled for each mode on x-axis and number of trips on y-axis #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' average distance traveled ~ main mode used -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes the data frame trips_output (from \link{readTripsTable()}), +#' to plot a bar chart of the average distance traveled for each main mode, +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart#' +#' @param trips_table tibble of trips_output (from readTripsTable()) +#'@param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' @return Bar Chart plot of distance traveled per mode #' #' @export @@ -2515,9 +2435,9 @@ plot_distance_by_mainmode_barchart <- function(trips_table, euclidean = FALSE) { - # If some columns should be united + # renaming/uniting of modes trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) #processing @@ -2541,137 +2461,35 @@ plot_distance_by_mainmode_barchart <- function(trips_table, return(fig) } -#' Line plot with departure time x-axis and number of trips on y-axis -#' -#' Takes Table trips_output (from readTripsTable()), -#' to make line plot with with values that represent -#' count of trips for a specific departure time by main_mode -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -#' -#' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @return Line Chart plot of trips count by departure mode per mode -#' -#' @export -plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, - unite.columns = character(0), - united.name = "united") { - - - # If some columns should be united - trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, - united.name = united.name) - - - #processing - tripsTable = tripsTable %>% - mutate(dep_time = hour(dep_time)) %>% - count(dep_time,main_mode) - - #plotting - fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) - fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") - - fig - return(fig) -} - -#' Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart -#' -#' -#' -#' @param table tibble of trips_output (from readTripsTable()) -#' -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) -#' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation -#' -#' -#' -#' @return plot with percentage of each type of trips -#' -#' @export -plot_spatialtype_by_shape_piechart <- function(trips_table, shape_table, crs) { - - trips_table <- process_append_spatialcat(trips_table,shape_table = shape_table,crs = crs) - - #print(trips_table) - - - trips_table_distribution <- trips_table %>% count(spatial_category) - - #print(trips_table_distribution) - - fig <- plot_ly(trips_table_distribution, labels = ~spatial_category, values = ~n, type = 'pie') - fig <- fig %>% layout(title = 'Spatial type distribution', - xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE), - yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE)) - fig - -} +#' Bar chart comparing distance traveled on x-axis and number of trips on y-axis for two different runs -#' Bar Chart with tripType on x-axis and travelled distance on y-axis -#' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' travelled distance of each tripType related to the shapeTable -#' -#' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' Takes two data frames (from \link{readTripsTable()}), categorizes the traveled distances into pre-defined bins +#' and plots the difference in number of trips for each bin. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' -#' @return Bar Chart plot of distance traveled by spatial type #' -#' @export -plot_distance_by_spatialcat <- function(trips_table, shape_table, crs, euclidian = FALSE) { - - #processing - - trips_table<- process_append_spatialcat(trips_table,shape_table, crs = crs) - travelled = trips_table %>% group_by(spatial_category) %>% summarize(travelled = sum(traveled_distance)/1000) - - #For plotting - fig = plot_ly(data = travelled,x = ~spatial_category,y = ~travelled,type = 'bar',name = "Distance travelled by trip Type") - fig = fig %>% layout(yaxis = list(title = "Distance travelled (in kms)"),barmode = "group") - fig - return(fig) -} - -###### Compare ###### -#' Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis -#' -#' Takes 2 Tables trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -#' -#' -#' @param trips_table1 tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 -#' @param trips_table2 tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' @param tripsTable1 tibble of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 +#' @param tripsTable2 tibble of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' @return Bar Chart plot of count of trips among distance travelled #' #' @export plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, - unite.columns = character(0), united.name = "united", + unite.modes = character(0), united.name = "united", dist_column = "dist_cat", distances_array = c(1000,2000,5000,10000,20000,50000,100000)) { trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) modes = unique(c(unique(trips_table1$main_mode),unique(trips_table2$main_mode))) @@ -2706,1136 +2524,637 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, } - - -#' Plot bar chart diagram of transport mode changes -#' -#' Takes two trips_table (from readTripsTable), and collects -#' changes between transport mode distribution of these tables -#' to make bar chart diagram with dodging positioning from this data +#' Line plot with departure time on x-axis and number of trips on y-axis #' -#' Function calculates number of each transport mode used in -#' first and second table, and draws plot that represent how -#' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) -#' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") -#' Using parameter show.onlyChanges +#' Takes data frame trips_output (from \link{readTripsTable()}), +#' to create a line plot of the number of trips for a specific departure time by main_mode +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name if columns were united, you can specify name for the resulting column in plot #' -#' @return plots Bar Chart of transport mode changes with additional files for simwrapper +#' @param tripsTable tibble of trips_output (from readTripsTable()) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode +#' @return Line plot of trips count by departure time per mode #' #' @export -plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, - unite.columns = character(0), - united.name = "united") { - # If the unite.columns is specified, then - #print(dump.output.to) - trips_table1 <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, - united.name = united.name) +plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, + unite.modes = character(0), + united.name = "united") { - trips_table2 <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, - united.name = united.name) - trips_table1 = trips_table1 %>% mutate(type = "base") - trips_table2 = trips_table2 %>% mutate(type = "policy") + # renaming/uniting of modes + trips_table <- process_rename_mainmodes(trips_table = trips_table, + unite.modes = unite.modes, + united.name = united.name) - total_trips = rbind(trips_table1,trips_table2) - plt = ggplot(total_trips, aes(x =main_mode,fill = factor(type)))+ - geom_bar(position = position_dodge())+ - coord_flip() - plotly::ggplotly(plt) + #processing + tripsTable = tripsTable %>% + mutate(dep_time = hour(dep_time)) %>% + count(dep_time,main_mode) - return(plotly::ggplotly(plt)) -} -#' Plot alluvial/sankey diagram of transport mode changes -#' -#' Takes two trips_table (from readTripsTable), and collects -#' changes between transport mode distribution of these tables -#' to make alluvial diagram from this data -#' -#' Function calculates number of each transport mode used in -#' first and second table, and draws plot that represent how -#' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) -#' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") -#' Using parameter show.onlyChanges -#' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param show.onlyChanges boolean, if it is set to TRUE => sankey diagram only contains changes on axes -#' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name if columns were united, you can specify name for the resulting column in plot -#' -#' @return Alluvial diagram that represents changes in transport mode distribution of trip tables -#' -#' @export -plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, - show.onlyChanges = FALSE, - unite.columns = character(0), - united.name = "united") { - #rename - trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.columns = unite.columns, - united.name = united.name) + #' Plot bar chart of changes in modal split + #' + #' Takes two data frames (from \link{readTripsTable()}), calculates the + #' changes in mode shares and plots them as a bar chart + #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') + #' + #' + #' + #' @param tripsTable1 tibble of trips_output (from readTripsTable()) + #' @param tripsTable2 tibble of trips_output (from readTripsTable()) + #'@param unite.modes vector of character strings, + #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), + #' using the function (\link{process_rename_mainmodes}) + #' @param united.name character string, specifies the name of the united mode + #' + #' @return plots bar chart of changes in modal split + #' + #' @export + plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, + unite.modes = character(0), + united.name = "united") { + # renaming/uniting of modes + trips_table1 <- process_rename_mainmodes(trips_table = trips_table, + unite.modes = unite.modes, + united.name = united.name) + + trips_table2 <- process_rename_mainmodes(trips_table = trips_table, + unite.modes = unite.modes, + united.name = united.name) + + trips_table1 = trips_table1 %>% mutate(type = "base") + trips_table2 = trips_table2 %>% mutate(type = "policy") + + total_trips = rbind(trips_table1,trips_table2) + + plt = ggplot(total_trips, aes(x =main_mode,fill = factor(type)))+ + geom_bar(position = position_dodge())+ + coord_flip() + plotly::ggplotly(plt) + + return(plotly::ggplotly(plt)) + } + + #' Plot alluvial/sankey diagram of transport mode changes + #' + #' Takes two data frames (from \link{readTripsTable()}) and compares the mode choice for each agent and summarizes the results, showing the modal shift. + #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') + #' The parameter show.onlyChanges allows the visualization of only the mode shift (excluding the trips that do not change mode). Standard value is FALSE. + #' + #' @param tripsTable1 tibble of trips_output (from readTripsTable()) + #' @param tripsTable2 tibble of trips_output (from readTripsTable()) + #' @param show.onlyChanges boolean, if it is set to TRUE the sankey diagram only shows the mode shift + #' @param unite.modes vector of character strings, + #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), + #' using the function (\link{process_rename_mainmodes}) + #' @param united.name character string, specifies the name of the united mode + #' + #' @return Alluvial diagram that represents changes in transport mode distribution + #' + #' @export + plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, + show.onlyChanges = FALSE, + unite.modes = character(0), + united.name = "united") { - trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.columns = unite.columns, - united.name = united.name) - #processing - joined <- as_tibble(inner_join(trips_table1, trips_table2 %>% - select(trip_id, main_mode), by = "trip_id") %>% - dplyr::rename(base_mode = main_mode.x, policy_mode = main_mode.y)) + # renaming/uniting of modes + trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, + unite.modes = unite.modes, + united.name = united.name) + + trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, + unite.modes = unite.modes, + united.name = united.name) + #processing + joined <- as_tibble(inner_join(trips_table1, trips_table2 %>% + select(trip_id, main_mode), by = "trip_id") %>% + dplyr::rename(base_mode = main_mode.x, policy_mode = main_mode.y)) + + #if onlychanges, then we should exclude base_mode=policy_mode + if (show.onlyChanges == TRUE) { + joined <- joined %>% + filter(base_mode != policy_mode) + } - #if onlychanges, then we should exclude base_mode=policy_mode - if (show.onlyChanges == TRUE) { joined <- joined %>% - filter(base_mode != policy_mode) - } + group_by(base_mode, policy_mode) %>% + count() - joined <- joined %>% - group_by(base_mode, policy_mode) %>% - count() + modes = unique(c(joined$base_mode,joined$policy_mode)) - modes = unique(c(joined$base_mode,joined$policy_mode)) + joined$base_mode <- as.numeric(factor(joined$base_mode,levels = modes)) + joined$policy_mode <- as.numeric(factor(joined$policy_mode,levels = modes)) - joined$base_mode <- as.numeric(factor(joined$base_mode,levels = modes)) - joined$policy_mode <- as.numeric(factor(joined$policy_mode,levels = modes)) + #plotting + palette <- colorRampPalette( c( "blue", "red" ) )( 7 ) - #plotting - palette <- colorRampPalette( c( "blue", "red" ) )( 7 ) + fig <- plot_ly( + type = "sankey", + orientation = "h", - fig <- plot_ly( - type = "sankey", - orientation = "h", + node = list( + label = c(modes,modes), + color = c(palette,palette), + pad = 15, + thickness = 20, + line = list( + color = "black", + width = 0.5 + ) + ), - node = list( - label = c(modes,modes), - color = c(palette,palette), - pad = 15, - thickness = 20, - line = list( - color = "black", - width = 0.5 + link = list( + source = joined$base_mode-1, + target = joined$policy_mode+6, + value = joined$n ) - ), - - link = list( - source = joined$base_mode-1, - target = joined$policy_mode+6, - value = joined$n ) - ) - fig <- fig %>% layout( - title = "Basic Sankey Diagram", - font = list( - size = 10 + fig <- fig %>% layout( + title = "Basic Sankey Diagram", + font = list( + size = 10 + ) ) - ) - fig - return(fig) -} + fig + return(fig) + } -#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis -#' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' time spent on traveling/waiting -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -#' -#' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' -#' @return Bar Chart plot of average time spent on travel/wait -#' -#' @export -plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_table2, - unite.columns = character(0), - united.name = "united", - time_format = "minute") { + #' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis + #' + #' Takes the data frame trips_output (from \link{readTripsTable()}), + #' to plot a bar chart of the traveling/waiting time + #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') + #' + #' + #' @param tripsTable1 tibble of trips_output (from readTripsTable()) + #' @param tripsTable2 tibble of trips_output (from readTripsTable()) + #' @param unite.modes vector of character strings, + #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), + #' using the function (\link{process_rename_mainmodes}) + #' @param united.name character string, specifies the name of the united mode + #' + #' @return Bar Chart plot of average time spent on travel/wait + #' + #' @export + plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_table2, + unite.modes = character(0), + united.name = "united", + time_format = "minute") { - #TODO: - # . Document and add title to show what means positive/negative value - # . think about comparing processing functions they can appear in future often + #TODO: + # . Document and add title to show what means positive/negative value + # . think about comparing processing functions they can appear in future often - # If some columns should be united - trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.columns = unite.columns, - united.name = united.name) + # If some columns should be united + trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, + unite.modes = unite.modes, + united.name = united.name) - trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.columns = unite.columns, - united.name = united.name) + trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, + unite.modes = unite.modes, + united.name = united.name) - #processing - avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) + #processing + avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) - avg_time2 = process_get_travelwaittime_by_mainmode(trips_table2,time_format = time_format) + avg_time2 = process_get_travelwaittime_by_mainmode(trips_table2,time_format = time_format) - avg_time = full_join(avg_time1, avg_time2, by = "main_mode") %>% - replace_na(list(trav_time_avg.x = 0,wait_time_avg.x = 0,trav_time_avg.y = 0,wait_time_avg.y = 0)) + avg_time = full_join(avg_time1, avg_time2, by = "main_mode") %>% + replace_na(list(trav_time_avg.x = 0,wait_time_avg.x = 0,trav_time_avg.y = 0,wait_time_avg.y = 0)) - avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg.x - trav_time_avg.y, - wait_time_avg =wait_time_avg.x - wait_time_avg.y )%>% - select(-wait_time_avg.x,-wait_time_avg.y, -trav_time_avg.x,-trav_time_avg.y) + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg.x - trav_time_avg.y, + wait_time_avg =wait_time_avg.x - wait_time_avg.y )%>% + select(-wait_time_avg.x,-wait_time_avg.y, -trav_time_avg.x,-trav_time_avg.y) - #plotting - fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") - fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") - fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)")),barmode = "group") + #plotting + fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") + fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") + fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)")),barmode = "group") - fig - return(fig) + fig + return(fig) -} + } -#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis -#' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' time spent on traveling/waiting -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') -#' -#' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' -#' @return Bar Chart plot of average time spent on travel/wait -#' -#' @export -plot_compare_count_by_spatialcat <- function(trips_table1,trips_table2, shape_table ,crs,dump.output.to = matsimDumpOutputDirectory) { + ###### Mapping ###### - spatial_table1 <- process_append_spatialcat(trips_table = trips_table1, - shape_table = shape_table, - crs = crs) + #####Processing##### - spatial_table2 <- process_append_spatialcat(trips_table = trips_table2, - shape_table = shape_table, - crs = crs) + process_rename_mainmodes<-function(trips_table, + unite.modes = character(0), united.name = "united"){ + if (length(unite.modes) != 0) { + trips_table$main_mode[grep(paste0(unite.modes, collapse = "|") + , trips_table$main_mode)] <- united.name + } + return(trips_table) + } - plt = ggplot(result_table, aes(x =type,fill = factor(table_num)))+ - geom_bar(position = position_dodge())+ - coord_flip() - plotly::ggplotly(plt) + process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ + trips_table_count <- trips_table %>% + count(main_mode) + if(percentage){ + trips_table_count<- trips_table_count %>% mutate(n = n / sum(n) * 100) + } - return(plotly::ggplotly(plt)) + return(trips_table_count) + } -} + process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ + trips_table = trips_table %>% + group_by(main_mode) %>% + summarize(avg_dist = if_else(euclidian,mean(euclidean_distance),mean(traveled_distance))) + return(trips_table) + } + process_get_travelwaittime_by_mainmode_barchart<-function(trips_table, + time_format = "minute"){#also could be hours/seconds -###### Mapping ###### + #get 2 columns with mean travel time and mean wait time grouped by main_mode in seconds + avg_time = trips_table %>% group_by(main_mode)%>% + summarize(trav_time_avg = hms::hms(seconds_to_period(mean(trav_time))), + wait_time_avg = hms::hms(seconds_to_period(mean(wait_time)))) %>% + mutate(trav_time_avg = as.numeric(trav_time_avg),wait_time_avg = as.numeric(wait_time_avg)) + if(time_format == "minute"){ + #convert seconds to minutes + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/60, wait_time_avg = wait_time_avg/60) + return(avg_time) + }else if(time_format == "hour"){ + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/3600, wait_time_avg = wait_time_avg/3600) + return(avg_time) + } -#' Plots start and end coordinates of the given trips table on an osm map -#' -#' @param table tibble of trips_output (from readTripsTable()) -#' -#' -#' @param crs numeric representation of the EPSG code or proj4string for the corresponding coordinate system of the trip coordinates, can be found in network file from output directory of MATSim simulation -#' -#' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot -#' -#' -#' @return plot with trips -#' -#' @export -plot_map_trips <- function(trips_table, crs,optimized = FALSE, - shape_table = NULL ) { - - table_sf <- process_convert_table_to_sf(trips_table, crs = crs, geometry.type = st_point()) - st_geometry(table_sf) <- "start_wkt" - table_sf_start <- table_sf %>% select(-end_wkt) - st_geometry(table_sf) <- "end_wkt" - table_sf_end <- table_sf %>% select(-start_wkt) - - if(!is.null(shape_table)){ - - if (st_crs(shape_table) == NA) { - ct_crs(shape_table) <- crs - } - shape_table <- st_transform(shape_table, crs = "+proj=longlat +datum=WGS84 +no_defs") - - } - - table_sf_start <- st_transform(table_sf_start, "+proj=longlat +datum=WGS84 +no_defs") - table_sf_end <- st_transform(table_sf_end, "+proj=longlat +datum=WGS84 +no_defs") - - if (optimized) { - colors <- c("Start" = "blue", "End" = "red") - shapes <- c("Start" = 5, "End" = 3) - # ggplot2 isn't interactive! - plt <- ggplot() + - geom_sf(data = table_sf_start, aes(color = "Start"), size = 1, shape = 5) + - geom_sf(data = table_sf_end, aes(color = "End"), size = 1, shape = 3) + - labs(color = "Type") + - scale_colour_manual(values = colors) - - if(!is.null(shape_table)){ - plt <-ggplot() + - geom_sf(data = shape_table)+ - geom_sf(data = table_sf_start, aes(color = "Start"), size = 1, shape = 5) + - geom_sf(data = table_sf_end, aes(color = "End"), size = 1, shape = 3) + - labs(color = "Type") + - scale_colour_manual(values = colors) - } - plt - return(plt) - } - - - - - - - - - # If we need to change design - # css_fix <- "div.info.legend.leaflet-control br {clear: both;}" - # Convert CSS to HTML - # html_fix <- htmltools::tags$style(type = "text/css", css_fix) - - plt <- leaflet() %>% - addTiles() %>% - addProviderTiles( - "OpenStreetMap", - # give the layer a name - group = "OpenStreetMap" - ) %>% - addProviderTiles( - "Stamen.Toner", - group = "Stamen.Toner" - ) %>% - addProviderTiles( - "Stamen.Terrain", - group = "Stamen.Terrain" - ) %>% - addProviderTiles( - "Esri.WorldStreetMap", - group = "Esri.WorldStreetMap" - ) %>% - addProviderTiles( - "Wikimedia", - group = "Wikimedia" - ) %>% - addProviderTiles( - "CartoDB.Positron", - group = "CartoDB.Positron" - ) %>% - addProviderTiles( - "Esri.WorldImagery", - group = "Esri.WorldImagery" - ) %>% - addCircleMarkers(table_sf_start, - lng = st_coordinates(table_sf_start$start_wkt)[, 1], - lat = st_coordinates(table_sf_start$start_wkt)[, 2], radius = 3, color = "blue", - label = paste( - "Person_id:", - table_sf_start$person, "
", - "Trip_id:", - table_sf_start$trip_id, "
", - "main_mode:", table_sf_start$main_mode, "
", - "type:", "start", "
", - "Start activity:", - table_sf_start$start_activity_type, "
" - ) %>% lapply(htmltools::HTML) - ) %>% - addCircleMarkers(table_sf_end, - lng = st_coordinates(table_sf_end$end_wkt)[, 1], - lat = st_coordinates(table_sf_end$end_wkt)[, 2], radius = 0.15, color = "red", - label = paste( - "Person_id:", - table_sf_end$person, "
", - "Trip_id:", - table_sf_end$trip_id, "
", - "main_mode:", table_sf_end$main_mode, "
", - "type:", "end", "
", - "End activity:", - table_sf_end$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) - ) %>% - addLegend( - colors = c("blue", "red"), - labels = c("Start of trip", "End of trip"), - position = "bottomleft", - title = "Type of the point", - opacity = 0.9 - ) %>% - addMiniMap() %>% - addLayersControl( - baseGroups = c( - "OpenStreetMap", "Stamen.Toner", - "Stamen.Terrain", "Esri.WorldStreetMap", - "Wikimedia", "CartoDB.Positron", "Esri.WorldImagery" - ), - # position it on the topleft - position = "topleft" - ) - if(!is.null(shape_table)){ - plt = plt %>% addPolygons(data = shape_table, opacity = 0.1, color = "green") - - } - plt - return(plt) -} - - -#' Plots every type of trips(inside, outside, origin and destinating) on map -#' -#' -#' -#' @param table tibble of trips_output (from readTripsTable()) -#' -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) -#' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation -#' -#' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot -#' -#' @return plot that contains every trip with defined trip type -#' -#' @export -plot_map_trips_by_spatialcat <- function(trips_table, shape_table, - crs, optimized = FALSE) { - - - #processing - - spatial_table <- process_append_spatialcat(trips_table, shape_table = shape_table,crs = crs) - - filtered_sf_inside <- spatial_table %>% filter(spatial_category == "inside") %>% - process_convert_table_to_sf( crs = crs, geometry.type = st_multipoint()) - filtered_sf_origin <- spatial_table %>% filter(spatial_category == "originating") %>% - process_convert_table_to_sf( crs = crs, geometry.type = st_multipoint()) - filtered_sf_destination <- spatial_table %>% filter(spatial_category == "destinating") %>% - process_convert_table_to_sf( crs = crs, geometry.type = st_multipoint()) - filtered_sf_transit <- spatial_table %>% filter(spatial_category == "outside") %>% - process_convert_table_to_sf( crs = crs, geometry.type = st_multipoint()) - - if (st_crs(shape_table) == NA) { - ct_crs(shape_table) <- crs - } - - shape_table <- st_transform(shape_table, crs = "+proj=longlat +datum=WGS84 +no_defs") - - filtered_sf_inside <- st_transform(filtered_sf_inside, "+proj=longlat +datum=WGS84 +no_defs") - filtered_sf_origin <- st_transform(filtered_sf_origin, "+proj=longlat +datum=WGS84 +no_defs") - filtered_sf_destination <- st_transform(filtered_sf_destination, "+proj=longlat +datum=WGS84 +no_defs") - filtered_sf_transit <- st_transform(filtered_sf_transit, "+proj=longlat +datum=WGS84 +no_defs") - - - #plotting - if (optimized) { - colors <- c("inside" = "green", "origin" = "red", "destination" = "orange", "transit" = "blue") - shapes <- c("Start" = 5, "End" = 3) - plt <- ggplot() + - geom_sf(data = shape_table) + - # geom_sf(data = ) - geom_sf(data = filtered_sf_inside, aes(color = "inside"), size = 3, alpha = 0.5) + - geom_sf(data = filtered_sf_origin, aes(color = "origin"), size = 3, alpha = 0.4) + - geom_sf(data = filtered_sf_destination, aes(color = "destination"), size = 3, alpha = 0.3) + - geom_sf(data = filtered_sf_transit, aes(color = "transit"), size = 2, alpha = 0.1) + - labs(color = "Type") + - scale_colour_manual(values = colors) - plt - return((plt)) - } - - # If we need to adjust design - # css_fix <- "div.info.legend.leaflet-control br {clear: both;}" - # Convert CSS to HTML - # html_fix <- htmltools::tags$style(type = "text/css", css_fix) - - - plt <- leaflet() %>% - addTiles() %>% - addProviderTiles( - "OpenStreetMap", - # give the layer a name - group = "OpenStreetMap" - ) %>% - addProviderTiles( - "Stamen.Toner", - group = "Stamen.Toner" - ) %>% - addProviderTiles( - "Stamen.Terrain", - group = "Stamen.Terrain" - ) %>% - addProviderTiles( - "Esri.WorldStreetMap", - group = "Esri.WorldStreetMap" - ) %>% - addProviderTiles( - "Wikimedia", - group = "Wikimedia" - ) %>% - addProviderTiles( - "CartoDB.Positron", - group = "CartoDB.Positron" - ) %>% - addProviderTiles( - "Esri.WorldImagery", - group = "Esri.WorldImagery" - ) %>% - addPolygons(data = shape_table, opacity = 0.1, color = "green") %>% - addCircleMarkers(filtered_sf_inside, - lng = st_coordinates(filtered_sf_inside$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_inside$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 3, color = "blue", - label = paste( - "Person_id:", - filtered_sf_inside$person, "
", - "Trip_id:", - filtered_sf_inside$trip_id, "
", - "main_mode:", filtered_sf_inside$main_mode, "
", - "type:", "start", "
", - "Start activity:", - filtered_sf_inside$start_activity_type, "
" - ) %>% lapply(htmltools::HTML) - ) %>% - addCircleMarkers(filtered_sf_inside, - lng = st_coordinates(filtered_sf_inside$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_inside$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 3, color = "blue", - label = paste( - "Person_id:", - filtered_sf_inside$person, "
", - "Trip_id:", - filtered_sf_inside$trip_id, "
", - "main_mode:", filtered_sf_inside$main_mode, "
", - "type:", "end", "
", - "End activity:", - filtered_sf_inside$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) - ) %>% - addCircleMarkers(filtered_sf_origin, - lng = st_coordinates(filtered_sf_origin$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_origin$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 2, color = "red", - label = paste( - "Person_id:", - filtered_sf_origin$person, "
", - "Trip_id:", - filtered_sf_origin$trip_id, "
", - "main_mode:", filtered_sf_origin$main_mode, "
", - "type:", "start", "
", - "Start activity:", - filtered_sf_origin$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) - ) %>% - addCircleMarkers(filtered_sf_origin, - lng = st_coordinates(filtered_sf_origin$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_origin$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 2, color = "red", - label = paste( - "Person_id:", - filtered_sf_origin$person, "
", - "Trip_id:", - filtered_sf_origin$trip_id, "
", - "main_mode:", filtered_sf_origin$main_mode, "
", - "type:", "end", "
", - "End activity:", - filtered_sf_origin$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) - ) %>% - addCircleMarkers(filtered_sf_destination, - lng = st_coordinates(filtered_sf_destination$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_destination$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 1, color = "orange", - label = paste( - "Person_id:", - filtered_sf_destination$person, "
", - "Trip_id:", - filtered_sf_destination$trip_id, "
", - "main_mode:", filtered_sf_destination$main_mode, "
", - "type:", "start", "
", - "Start activity:", - filtered_sf_destination$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) - ) %>% - addCircleMarkers(filtered_sf_destination, - lng = st_coordinates(filtered_sf_destination$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_destination$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 1, color = "orange", - label = paste( - "Person_id:", - filtered_sf_destination$person, "
", - "Trip_id:", - filtered_sf_destination$trip_id, "
", - "main_mode:", filtered_sf_destination$main_mode, "
", - "type:", "end", "
", - "End activity:", - filtered_sf_destination$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) - ) %>% - addCircleMarkers(filtered_sf_transit, - lng = st_coordinates(filtered_sf_transit$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_transit$wkt)[seq(1, length(filtered_sf_inside$wkt), 2), 2], radius = 0.15, color = "black", - label = paste( - "Person_id:", - filtered_sf_transit$person, "
", - "Trip_id:", - filtered_sf_transit$trip_id, "
", - "main_mode:", filtered_sf_transit$main_mode, "
", - "type:", "start", "
", - "Start activity:", - filtered_sf_transit$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) - ) %>% - addCircleMarkers(filtered_sf_transit, - lng = st_coordinates(filtered_sf_transit$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 1], - lat = st_coordinates(filtered_sf_transit$wkt)[seq(2, length(filtered_sf_inside$wkt), 2), 2], radius = 0.15, color = "black", - label = paste( - "Person_id:", - filtered_sf_transit$person, "
", - "Trip_id:", - filtered_sf_transit$trip_id, "
", - "main_mode:", filtered_sf_transit$main_mode, "
", - "type:", "end", "
", - "End activity:", - filtered_sf_transit$end_activity_type, "
" - ) %>% lapply(htmltools::HTML) - ) %>% - addLegend( - colors = c("blue", "red", "orange", "black"), - labels = c( - "Trips inside of region", - "Trips with the end outside region", - "Trips with the start outside region", - "Trips that start and end outside region" - ), - position = "bottomleft", - title = "Type of the point", - opacity = 0.9 - ) %>% - addMiniMap() %>% - addLayersControl( - baseGroups = c( - "OpenStreetMap", "Stamen.Toner", - "Stamen.Terrain", "Esri.WorldStreetMap", - "Wikimedia", "CartoDB.Positron", "Esri.WorldImagery" - ), - # position it on the topleft - position = "topleft" - ) - - plt - return(plt) -} - -#####Processing##### -#' @export -process_rename_mainmodes<-function(trips_table, - unite.columns = character(0), united.name = "united"){ - - if (length(unite.columns) != 0) { - trips_table$main_mode[grep(paste0(unite.columns, collapse = "|") - , trips_table$main_mode)] <- united.name - } - return(trips_table) -} -#' @export -process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ - - trips_table_count <- trips_table %>% - count(main_mode) - if(percentage){ - trips_table_count<- trips_table_count %>% mutate(n = n / sum(n) * 100) - } - - return(trips_table_count) -} - -process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ - - trips_table = trips_table %>% - group_by(main_mode) %>% - summarize(avg_dist = if_else(euclidian,mean(euclidean_distance),mean(traveled_distance))) - - return(trips_table) -} -#' @export -process_get_travelwaittime_by_mainmode_barchart<-function(trips_table, - time_format = "minute"){#also could be hours/seconds - - #get 2 columns with mean travel time and mean wait time grouped by main_mode in seconds - avg_time = trips_table %>% group_by(main_mode)%>% - summarize(trav_time_avg = hms::hms(seconds_to_period(mean(trav_time))), - wait_time_avg = hms::hms(seconds_to_period(mean(wait_time)))) %>% - mutate(trav_time_avg = as.numeric(trav_time_avg),wait_time_avg = as.numeric(wait_time_avg)) - - if(time_format == "minute"){ - #convert seconds to minutes - avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/60, wait_time_avg = wait_time_avg/60) return(avg_time) - }else if(time_format == "hour"){ - avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/3600, wait_time_avg = wait_time_avg/3600) - return(avg_time) - } - - return(avg_time) -} - - -#' @export -process_append_distcat <- function(trips_table,distances_array = c(1000,2000,5000,10000,20000,50000,100000)){ - - distances_array = sort(c(distances_array,c(0,Inf))) - modes = levels(factor(trips_table$main_mode)) - - #Also filtering table into a new doesn't creates new objects in memory, so it works fast - #Upd: it creates copy of dataframe on each mutate :/ - - result_table <- c(NULL) - - str_factors<-c(NULL) - for(i in 1:(length(distances_array)-1)){ - part_table <- trips_table %>% - filter(traveled_distance>=distances_array[i] & traveled_distance% - mutate(dist_cat = paste0(distances_array[i],"-",distances_array[i+1])) - str_factors<- c(str_factors,paste0(distances_array[i],"-",distances_array[i+1])) - result_table <- rbind(result_table,part_table) - } - - result_table$dist_cat = factor(result_table$dist_cat,levels = str_factors) - return(result_table) -} - -######Spatial###### - -#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape -#' -#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) -#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -#' and filters the trips from table depending on *.inshape flags: -#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips \strong{inside} of the given shape -#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which \strong{originating} in the shape -#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which \strong{destinating} in the shape -#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which \strong{outside} of the given shape -#' -#' @param trips_table tibble of trips_output (from readTripsTable()) -#' -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) -#' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation -#' -#' @param spatial_type character parameter,categories of spatial information used to specify which kind of trips should be filtered. Takes as input 4 templates: inside, outside, originating, destinating -#' -#' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) -#' -#' @export -process_filter_by_shape <- function(trips_table, - shape_table, - crs, - spatial_type = "inside") { - - start.inshape <- TRUE - end.inshape <- TRUE - - if(spatial_type == "inside"){ - start.inshape <- TRUE - end.inshape <- TRUE - }else if(spatial_type == "outside"){ - start.inshape <- FALSE - end.inshape <- FALSE - }else if(spatial_type == "originating"){ - start.inshape <- TRUE - end.inshape <- FALSE - }else if(spatial_type == "destinating"){ - start.inshape <- FALSE - end.inshape <- TRUE - }else{ - stop("There are only 4 possible spatial_types: inside, outside, originating, destinating") - } - # shape_table <- st_read(shapeFile) - if (st_crs(shape_table) == NA) { - st_crs(shape_table) <- crs } - sf_table <- process_convert_table_to_sf(trips_table, crs = crs, geometry.type = st_point()) - shape_table <- st_transform(shape_table, crs = crs) - # shape_table isn't table - shape - union_shape <- st_union(shape_table) # transforms the crs back to the previous in the file - union_shape <- st_transform(union_shape, crs = st_crs(shape_table)) + process_append_distcat <- function(trips_table,distances_array = c(1000,2000,5000,10000,20000,50000,100000)){ - st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry - cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile + distances_array = sort(c(distances_array,c(0,Inf))) + modes = levels(factor(trips_table$main_mode)) - st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry - cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile + #Also filtering table into a new doesn't creates new objects in memory, so it works fast + #Upd: it creates copy of dataframe on each mutate :/ - # get trips that ended outside of shape - cont_end_outside <- setdiff(1:nrow(sf_table), cont2) + result_table <- c(NULL) - # get trips that started outside of shape - cont_start_outside <- setdiff(1:nrow(sf_table), cont1) + str_factors<-c(NULL) + for(i in 1:(length(distances_array)-1)){ + part_table <- trips_table %>% + filter(traveled_distance>=distances_array[i] & traveled_distance% + mutate(dist_cat = paste0(distances_array[i],"-",distances_array[i+1])) + str_factors<- c(str_factors,paste0(distances_array[i],"-",distances_array[i+1])) + result_table <- rbind(result_table,part_table) + } - if (start.inshape == TRUE && end.inshape == TRUE) { - cont_union <- intersect(cont1, cont2) - } else if (start.inshape == TRUE && end.inshape == FALSE) { - cont_union <- intersect(cont1, cont_end_outside) - } else if (start.inshape == FALSE && end.inshape == TRUE) { - cont_union <- intersect(cont2, cont_start_outside) - } else { - cont_union <- intersect(cont_start_outside, cont_end_outside) # Give back trips that are neither starting and ending outside the area + result_table$dist_cat = factor(result_table$dist_cat,levels = str_factors) + return(result_table) } - - return(trips_table[cont_union, ]) -} - -#' Appending spatial category as additional column to output_trips tibble -#' -#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) -#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -#' and adds to the output_trips from table spatial category depending on postition related to shape file: -#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips \strong{inside} of the given shape -#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which \strong{originating} in the shape -#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which \strong{destinating} in the shape -#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which \strong{outside} of the given shape -#' -#' @param trips_table tibble of trips_output (from readTripsTable()) -#' -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) -#' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation -#' -#' @return tibble, with additional spatial column related to given shape -#' -#' @export -process_append_spatialcat <- function(trips_table, + ######Spatial###### + #' XXXX trips_table but shapeTable - fix naming + #' XXXX finish when code revision is done + #' Filters trips_table(from ,\link{readTripsTable}) depending by location using a shapefile + #' + #' Uses trips_table and an sf object (can be created using the function st_read()), + #' transforms both objects to match a mutual coordinate system (crs) + #' and filters the trips from trips_table depending on *.inshape flags: + #' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape + #' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape + #' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape + #' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape + #' + #' @param trips_table tibble of trips_output (from readTripsTable()) + #' + #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) + #' + #' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file + #' + #' @param start.inshape bool, defines trips to conclude (see Description) + #' + #' @param end.inshape bool, defines trips to conclude (see Description) + #' + #' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) + #' + #' @export + process_filter_by_shape <- function(trips_table, shape_table, - crs) { - - start.inshape <- TRUE - end.inshape <- TRUE - - # shape_table <- st_read(shapeFile) - if (st_crs(shape_table) == NA) { - st_crs(shape_table) <- crs - } - - sf_table <- process_convert_table_to_sf(trips_table, crs = crs, geometry.type = st_point()) - shape_table <- st_transform(shape_table, crs = crs) - # shape_table isn't table - shape - - union_shape <- st_union(shape_table) # transforms the crs back to the previous in the file - union_shape <- st_transform(union_shape, crs = st_crs(shape_table)) - - - st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry - cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile - - st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry - cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile - - # get trips that ended outside of shape - cont_end_outside <- setdiff(1:nrow(sf_table), cont2) - - # get trips that started outside of shape - cont_start_outside <- setdiff(1:nrow(sf_table), cont1) + crs, + start.inshape = TRUE, end.inshape = TRUE) { - cont_union_inside <- intersect(cont1,cont2) - cont_union_outside <- intersect(cont_start_outside,cont_end_outside) - cont_union_originating <- intersect(cont1,cont_end_outside) - cont_union_destinating <- intersect(cont2, cont_start_outside) + # shape_table <- st_read(shapeFile) + if (st_crs(shape_table) == NA) { + st_crs(shape_table) <- crs + } - trips_table$spatial_category = NA + sf_table <- transformToSf(trips_table, crs = crs, geometry.type = st_point()) + shape_table <- st_transform(shape_table, crs = crs) + # shape_table isn't table - shape - trips_table[cont_union_inside, ]$spatial_category <- "inside" - trips_table[cont_union_outside, ]$spatial_category <- "outside" - trips_table[cont_union_originating, ]$spatial_category <- "originating" - trips_table[cont_union_destinating, ]$spatial_category <- "destinating" + union_shape <- st_union(shape_table) # transforms the crs back to the previous in the file + union_shape <- st_transform(union_shape, crs = st_crs(shape_table)) - return(trips_table) -} + st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry + cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile + st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry + cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile -#' Reads an coordinate referenec system of MATSim output directory -#' from output_config.xml -#' -#' @param config_path specifies path to find config -#' -#' -#' @return code of coordinate reference system -#' -#' @export -process_get_crs_from_config <- function(config_path) { + # get trips that ended outside of shape + cont_end_outside <- setdiff(1:nrow(sf_table), cont2) - if (grepl("output_config.xml$", config_path) == TRUE) - { - config <- read_xml(folder) + # get trips that started outside of shape + cont_start_outside <- setdiff(1:nrow(sf_table), cont1) - param_nodes = xml_find_all(config,"//param") + if (start.inshape == TRUE && end.inshape == TRUE) { + cont_union <- intersect(cont1, cont2) + } else if (start.inshape == TRUE && end.inshape == FALSE) { + cont_union <- intersect(cont1, cont_end_outside) + } else if (start.inshape == FALSE && end.inshape == TRUE) { + cont_union <- intersect(cont2, cont_start_outside) + } else { + cont_union <- intersect(cont_start_outside, cont_end_outside) # Give back trips that are neither starting and ending outside the area + } - coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] - coord_system = xml_attr(coord_node,"value") - return(coord_system) + return(trips_table[cont_union, ]) } - files <- list.files(config_path, full.names = TRUE) - # Read from global/local directory - # output_config.xml is contained as output_trips.csv.gz - if (length(grep("output_config.xml$", files)) != 0) { - config <- read_xml(files[grep("output_config.xml$", files)]) - - param_nodes = xml_find_all(config,"//param") + #' Reads the coordinate reference system from an MATSim output directory + #' (output_config.xml) + #' + #' @param config_path specifies path to configuration file + #' + #' + #' @return code of coordinate reference system + #' + #' @export + process_get_crs_from_config <- function(config_path) { - coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] + if (grepl("output_config.xml$", config_path) == TRUE) + { + config <- read_xml(folder) - coord_system = xml_attr(coord_node,"value") - return(coord_system) - } - return(NA) -} + param_nodes = xml_find_all(config,"//param") -#' Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper -#' -#' -#' -#' @param tripsTable table of output trips(from readTripsTable) or path to trips_output file -#' -#' @param shapePath full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name) -#' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation -#' -#' @param dump.output.to path to a folder to save csv file of ODMatrix -#' -#' @param colnames if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values -#' -#' @param simwrapper create output in a simwrapper form if set to path of the shapefile -#' -#' @param outer logical that represent if the table should contain outside flow of the shape, it isn't -#' -#' @return tibble of origin/destination matrix -#' -#' @export -process_get_od_matrix<- function(tripsTable, - shapePath, - crs, - dump.output.to = matsimDumpOutputDirectory, - simwrapper = FALSE, - colnames = "numeric", - outer = FALSE){ + coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] - defaultW <- getOption("warn") - options(warn = -1) + coord_system = xml_attr(coord_node,"value") + return(coord_system) + } - #if tripstable given as folder/file - if(sum(class(tripsTable) %in% c("tbl_df","tbl","data.frame"))<1){ - tripsTable <- readTripsTable(tripsTable) - } + files <- list.files(config_path, full.names = TRUE) + # Read from global/local directory + # output_config.xml is contained as output_trips.csv.gz + if (length(grep("output_config.xml$", files)) != 0) { + config <- read_xml(files[grep("output_config.xml$", files)]) - sfTable <- transformToSf(tripsTable,crs,geometry.type = st_point()) + param_nodes = xml_find_all(config,"//param") - shape = st_read(shapePath) + coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] - if (st_crs(shape) == NA) { - st_crs(shape) <- crs + coord_system = xml_attr(coord_node,"value") + return(coord_system) + } + return(NA) } - shape = st_transform(shape,crs = crs) - sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) + #' Creates an origin/destination matrix either in conventional form (row names = origin, column names = destination) + #' or for simwrapper (origin and destination as columns) + #' + #' + #' @param tripsTable tibble of trips_output (from \link{readTripsTable}) + #' + #' @param shapePath string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file) + #' + #' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file + #' + #' @param dump.output.to string, path to a folder to save the .csv file + #' + #' @param colnames string, column names can be specified (i.e. to fit the shape file), if not they are numbered + #' + #' @param simwrapper boolean, creates output in the format used for simwrapper if the path for the shapefile is specified + #' + #' @param outer boolean, determines if flows outside of the shapefile are used, standard value is FALSE + #' + #' @return tibble of origin/destination matrix + #' + #' @export + process_get_od_matrix<- function(tripsTable, + shapePath, + crs, + dump.output.to = matsimDumpOutputDirectory, + simwrapper = FALSE, + colnames = "numeric", + outer = FALSE){ - sf_start = sfTable %>% select(trip_id,start_wkt) - st_geometry(sfTable) = "end_wkt" - sf_end = sfTable %>% select(trip_id,end_wkt) + defaultW <- getOption("warn") + options(warn = -1) - #Get all inner intersects - sf_intersect_start = st_contains(shape,sf_start) - sf_intersect_end = st_contains(shape,sf_end) + #if tripstable given as folder/file + if(sum(class(tripsTable) %in% c("tbl_df","tbl","data.frame"))<1){ + tripsTable <- readTripsTable(tripsTable) + } + sfTable <- transformToSf(tripsTable,crs,geometry.type = st_point()) - if(outer == TRUE){ - #Get all outer intersects - joined_shape = st_union(shape) + shape = st_read(shapePath) - start_inside = st_contains(joined_shape,sf_start) - end_inside = st_contains(joined_shape,sf_end) + if (st_crs(shape) == NA) { + st_crs(shape) <- crs + } + shape = st_transform(shape,crs = crs) - start_outside = 1:nrow(sf_start) - end_outside = 1:nrow(sf_end) + sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) - start_outside = start_outside[! start_outside %in% start_inside[[1]]] + sf_start = sfTable %>% select(trip_id,start_wkt) + st_geometry(sfTable) = "end_wkt" + sf_end = sfTable %>% select(trip_id,end_wkt) - end_outside = end_outside[! end_outside %in% end_inside[[1]]] + #Get all inner intersects + sf_intersect_start = st_contains(shape,sf_start) + sf_intersect_end = st_contains(shape,sf_end) - sf_intersect_start = append(sf_intersect_start,list(start_outside)) - sf_intersect_end = append(sf_intersect_end,list(end_outside)) - } - # Create matrix out of it - result_tibble = as_tibble(data.frame(matrix(nrow=0,ncol=nrow(shape)))) - colnames(result_tibble) = 1:nrow(shape) + if(outer == TRUE){ + #Get all outer intersects + joined_shape = st_union(shape) - for(i in 1:length(sf_intersect_start)){ - temp = c() - for(j in 1:length(sf_intersect_start)){ - start_i = sf_intersect_start[[i]] - end_j = sf_intersect_end[[j]] + start_inside = st_contains(joined_shape,sf_start) + end_inside = st_contains(joined_shape,sf_end) - number_of_trips = length(intersect(start_i,end_j)) + start_outside = 1:nrow(sf_start) + end_outside = 1:nrow(sf_end) - temp = append(temp,number_of_trips) + start_outside = start_outside[! start_outside %in% start_inside[[1]]] - } - result_tibble = rbind(result_tibble,temp) - } + end_outside = end_outside[! end_outside %in% end_inside[[1]]] - if(colnames!="numeric" & colnames %in% colnames(shape)){ - colnames(result_tibble) = shape[[colnames]] - if(outer == TRUE){ - rownames(result_tibble) = c(shape[[colnames]],"outer") - colnames(result_tibble)[length(colnames(result_tibble))] = "outer" - }else{ - rownames(result_tibble) = shape[[colnames]] + sf_intersect_start = append(sf_intersect_start,list(start_outside)) + sf_intersect_end = append(sf_intersect_end,list(end_outside)) } - }else{ - colnames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) - rownames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) - } - - - result_melt = melt(as.matrix(result_tibble)) - colnames(result_melt) = c("origin","destination",1) + # Create matrix out of it + result_tibble = as_tibble(data.frame(matrix(nrow=0,ncol=nrow(shape)))) + colnames(result_tibble) = 1:nrow(shape) + for(i in 1:length(sf_intersect_start)){ + temp = c() + for(j in 1:length(sf_intersect_start)){ + start_i = sf_intersect_start[[i]] + end_j = sf_intersect_end[[j]] - # Generating yaml and output_files - # We remove it from new version, but still we are gonna use it in generate simwrapper of new version + number_of_trips = length(intersect(start_i,end_j)) - # if (file.exists(dump.output.to) & simwrapper == TRUE) { - # write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") - # } else if(!file.exists(dump.output.to) & simwrapper == TRUE) { - # dir.create(dump.output.to) - # write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") - # } else if (file.exists(dump.output.to) & simwrapper == FALSE) { - # write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) - # } else { - # dir.create(dump.output.to) - # write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) - # } - # - # yaml_list <- list( - # title = "OD Flow", - # description = "generated by deriveODMatrix", - # projection = st_crs(shape)$input, - # shpFile = paste0("../",shapePath), - # dbfFile = paste0("../",substr(shapePath,start = 1,stop = nchar(shapePath)-3),"dbf"), - # scaleFactor = 1, - # lineWidth = 50, - # csvFile = "ODMatrix.csv", - # idColumn = colnames(shape)[1] # at the moment idColumn of shapefile should be the first column - # - # ) - # write_yaml(yaml_list, paste0(dump.output.to, "/viz-od-flow.yaml")) + temp = append(temp,number_of_trips) - options(warn = defaultW) - return(result_tibble) -} + } + result_tibble = rbind(result_tibble,temp) + } + if(colnames!="numeric" & colnames %in% colnames(shape)){ + colnames(result_tibble) = shape[[colnames]] + if(outer == TRUE){ + rownames(result_tibble) = c(shape[[colnames]],"outer") + colnames(result_tibble)[length(colnames(result_tibble))] = "outer" + }else{ + rownames(result_tibble) = shape[[colnames]] + } + }else{ + colnames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) + rownames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) + } -#' Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature) -#' -#' Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features -#' deletes from resulting data.frame start_x, end_x, start_y, end_y. -#' And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring() -#' Or adds start_wkt and end_wkt, if geometry.type = st_point() -#' Added column/columns projected to given CRS (coordinate reference system), -#' that can be taken from network file of MATSimOutputDirectory -#' -#' Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" -#' to get which type of table was generated, if it is needed -#' -#' @param table tibble of trips_output (from readTripsTable()) -#' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation -#' -#' @param geometry.type function of sf transformation, geometry.type can be (by default is st_multipoint()) -#' !!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or -#' !!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or -#' !!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!! -#' -#' @return sf object (data.frame with geometries depending to geometry.type) -#' -#' @export -process_convert_table_to_sf <- function(table, - crs, - geometry.type = st_multipoint()) { - if (class(geometry.type)[2] == "POINT") { - table1 <- table %>% - # mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep ="")) - mutate(start_wkt = paste("POINT(", start_x, " ", start_y, ")", sep = "")) - table2 <- table %>% - mutate(end_wkt = paste("POINT(", end_x, " ", end_y, ")", sep = "")) - attr(table, "geometry.type") <- "POINT" - - - table1_wkt <- st_as_sf(table1, wkt = "start_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - table2_wkt <- st_as_sf(table2, wkt = "end_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - - - result_table <- table1_wkt %>% mutate(end_wkt = table2_wkt$end_wkt) - st_geometry(result_table) <- "start_wkt" - st_crs(result_table) <- crs - st_geometry(result_table) <- "end_wkt" - st_crs(result_table) <- crs - st_geometry(result_table) <- "start_wkt" - return(result_table) - } else if (class(geometry.type)[2] == "MULTIPOINT") { - table <- table %>% - mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) - attr(table, "geometry.type") <- "MULTIPOINT" + result_melt = melt(as.matrix(result_tibble)) + colnames(result_melt) = c("origin","destination",1) + # Generating yaml and output_files - result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - st_crs(result_table) <- crs - return(result_table) - } else if (class(geometry.type)[2] == "LINESTRING") { - table <- table %>% - mutate(wkt = paste("LINESTRING(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) - attr(table, "geometry.type") <- "LINESTRING" + if (file.exists(dump.output.to) & simwrapper == TRUE) { + write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") + } else if(!file.exists(dump.output.to) & simwrapper == TRUE) { + dir.create(dump.output.to) + write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") + } else if (file.exists(dump.output.to) & simwrapper == FALSE) { + write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) + } else { + dir.create(dump.output.to) + write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) + } - result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + yaml_list <- list( + title = "OD Flow", + description = "generated by deriveODMatrix", + projection = st_crs(shape)$input, + shpFile = paste0("../",shapePath), + dbfFile = paste0("../",substr(shapePath,start = 1,stop = nchar(shapePath)-3),"dbf"), + scaleFactor = 1, + lineWidth = 50, + csvFile = "ODMatrix.csv", + idColumn = colnames(shape)[1] # at the moment idColumn of shapefile should be the first column - st_crs(result_table) <- crs - return(result_table) - } else { - return(NA) + ) + write_yaml(yaml_list, paste0(dump.output.to, "/viz-od-flow.yaml")) + + options(warn = defaultW) + return(result_tibble) + } + + + + #' Transforms the data frame trips_output (from \links{readTripsTable}) from tibble to sf (table with geometry features) + #' + #' Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features. + #' If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format), + #' if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt. + #' Added column/columns are projected to given CRS (coordinate reference system). + #' The columns start_x, end_x, start_y, end_y are deleted from the resulting data frame. + #' + #' @param table tibble trips_output (from readTripsTable()) + #' + #' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file + #' + #' @param geometry.type type of sf transformation, default is st_multipoint(), geometry.type can be: + #' !!!st_point()- resulting table contains two geometry columns: start_wkt and end_wkt, representing start and end points as POINTS!!! or + #' !!!st_multipoint()- resulting table contains one geometry column, representing start and end points as MULTIPOINT!!! or + #' !!!st_linestring() - resulting table contains one geometry column, representing the line between start and end points as LINESTRING!!! + #' + #' @return sf object (data frame with geometries depending on geometry.type) + #' + #' @export + transformToSf <- function(table, + crs, + geometry.type = st_multipoint()) { + if (class(geometry.type)[2] == "POINT") { + table1 <- table %>% + # mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep ="")) + mutate(start_wkt = paste("POINT(", start_x, " ", start_y, ")", sep = "")) + table2 <- table %>% + mutate(end_wkt = paste("POINT(", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "POINT" + + + table1_wkt <- st_as_sf(table1, wkt = "start_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + table2_wkt <- st_as_sf(table2, wkt = "end_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + + result_table <- table1_wkt %>% mutate(end_wkt = table2_wkt$end_wkt) + st_geometry(result_table) <- "start_wkt" + st_crs(result_table) <- crs + st_geometry(result_table) <- "end_wkt" + st_crs(result_table) <- crs + st_geometry(result_table) <- "start_wkt" + return(result_table) + } else if (class(geometry.type)[2] == "MULTIPOINT") { + table <- table %>% + mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "MULTIPOINT" + + + result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + st_crs(result_table) <- crs + return(result_table) + } else if (class(geometry.type)[2] == "LINESTRING") { + table <- table %>% + mutate(wkt = paste("LINESTRING(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "LINESTRING" + + + result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + st_crs(result_table) <- crs + return(result_table) + } else { + return(NA) + } } -} - - -#####Helping functions#### + #####Helping functions#### From ab6fc62f0353148e4303ed8be521c045980440ba Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 28 Jun 2023 15:04:20 +0200 Subject: [PATCH 40/87] added plot_deptime and plot_arrtime --- NAMESPACE | 7 +- R/network.R | 1 + R/output_trips.R | 170 ++++++++++++++++++++++++---- R/personsOutput.R | 1 + man/compareBasePolicyOutput.Rd | 28 ----- man/compareBasePolicyShapeOutput.Rd | 34 ------ man/deriveODMatrix.Rd | 37 ------ man/filterByRegion.Rd | 38 ------- man/getCrsFromConfig.Rd | 19 ---- man/matsimr-deprecated.Rd | 132 ++++++++++++++++++++- man/plot_arrtime_by_act.Rd | 32 ++++++ man/transformToSf.Rd | 33 ------ 12 files changed, 316 insertions(+), 216 deletions(-) delete mode 100644 man/compareBasePolicyOutput.Rd delete mode 100644 man/compareBasePolicyShapeOutput.Rd delete mode 100644 man/deriveODMatrix.Rd delete mode 100644 man/filterByRegion.Rd delete mode 100644 man/getCrsFromConfig.Rd create mode 100644 man/plot_arrtime_by_act.Rd delete mode 100644 man/transformToSf.Rd diff --git a/NAMESPACE b/NAMESPACE index 2ef9525..a734413 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ # Generated by roxygen2: do not edit by hand +export(appendDistanceCategory) export(boxplotScoreDifferences) export(compareAverageTravelWait) export(compareBasePolicyOutput) @@ -29,11 +30,13 @@ export(plotTripCountByDepTime) export(plotTripDistanceByMode) export(plotTripDistancedByType) export(plotTripTypesPieChart) +export(plot_arrtime_by_act) export(plot_compare_count_by_spatialcat) export(plot_compare_distcat_by_mainmode_barchart) export(plot_compare_mainmode_barchart) export(plot_compare_mainmode_sankey) export(plot_compare_travelwaittime_by_mainmode_barchart) +export(plot_deptime_by_act) export(plot_distance_by_mainmode_barchart) export(plot_distance_by_spatialcat) export(plot_distcat_by_mainmode_barchart) @@ -52,11 +55,13 @@ export(processLinkStatsDtvDistribution) export(process_append_distcat) export(process_append_spatialcat) export(process_convert_table_to_sf) +export(process_convert_time) export(process_filter_by_shape) export(process_get_crs_from_config) export(process_get_mainmode_distribution) export(process_get_od_matrix) -export(process_get_travelwaittime_by_mainmode_barchart) +export(process_get_travelwaittime_by_mainmode) +export(process_rename_category) export(process_rename_mainmodes) export(readCounts) export(readLinkStats) diff --git a/R/network.R b/R/network.R index f2313de..f7fcb2b 100644 --- a/R/network.R +++ b/R/network.R @@ -54,6 +54,7 @@ utils::globalVariables(c("name")) #' #' @export read_network <- function(filename) { + cat(filename, ": ") network <- read_xml(filename) diff --git a/R/output_trips.R b/R/output_trips.R index 5a777c1..ed8e0c5 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -798,7 +798,7 @@ plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character for(dtime in diff){ newColumn = rbind(newColumn,c(dtime,0)) } - newColumn = newColumn %>%arrange(arr_time) %>% select(-arr_time) %>% mutate(act = as.numeric(act)) + newColumn = newColumn %>%arrange(arr_time) %>% select(-arr_time) %>% mutate(act = as.ncheumeric(act)) colnames(newColumn)[1] = act #print(newColumn) tableToWrite = cbind(tableToWrite,newColumn) @@ -1930,12 +1930,14 @@ appendDistanceCategory <- function(tripsTable){ #' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). #' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) #' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -#' and filters the trips from table depending on *.inshape flags: -#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +#' and filters the trips from table depending on *.inshape flags: \cr +#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape\cr +#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape\cr +#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape\cr #' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape #' +#' @rdname matsimr-deprecated +#' #' @param tripsTable tibble of trips_output (from readTripsTable()) #' #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) @@ -2197,13 +2199,15 @@ getCrsFromConfig <- function(folder) { #' Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" #' to get which type of table was generated, if it is needed #' +#' @rdname matsimr-deprecated +#' #' @param table tibble of trips_output (from readTripsTable()) #' #' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' -#' @param geometry.type function of sf transformation, geometry.type can be (by default is st_multipoint()) -#' !!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or -#' !!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or +#' @param geometry.type function of sf transformation, geometry.type can be (by default is st_multipoint())\cr +#' !!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or \cr +#' !!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or \cr #' !!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!! #' #' @return \strong{transformToSf} - sf object (data.frame with geometries depending to geometry.type) @@ -2641,6 +2645,104 @@ plot_distance_by_spatialcat <- function(trips_table, shape_table, crs, euclidian return(fig) } + +#' Deprecated function(s) in the matsimr package +#' +#' \strong{plot_arrtime_by_act} - Takes Table trips_output (from readTripsTable()), +#' to make line plot with with values that represent +#' count of destination activities for a specific arrival time +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' +#' @param trips_table tibble of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in plot +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' +#' @return \strong{plot_arrtime_by_act} - Line plot with arrival time x-axis and number end activities on y-axis +#' +#' @export +plot_arrtime_by_act <- function(trips_table, unite_activities = character(0), united_name = "united") { + + + + # If some columns should be united + trips_table <- process_rename_category(trips_table = trips_table, + unite_template = unite_activities, + united_name = united_name, + column = "end_activity_type") + + + trips_table = trips_table %>% + mutate(arr_time = hour(hms(trips_table$dep_time)+hms(trips_table$trav_time))) %>% + mutate(end_activity_type = sapply(strsplit(end_activity_type,"_"),"[[",1)) %>% + count(arr_time,end_activity_type) + + + activities = levels(factor(trips_table$end_activity_type)) + + + + fig = plot_ly(trips_table,x = ~arr_time,y = ~n,type = "scatter",mode = "line",linetype = ~end_activity_type) + fig = fig %>% layout(yaxis = list(title = "Number of trips ending per trip purpose / Count of activities starting"), + xaxis = list(title = "Time [h]"), + barmode = "group") + + + fig + return(fig) + +} + +#' Deprecated function(s) in the matsimr package +#' +#' \strong{plotDepartureTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), +#' to make line plot with with values that represent +#' count of destination activities for a specific arrival time +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' +#' @rdname matsimr-deprecated +#' +#' @param tripsTable tibble of trips_output (from readTripsTable()) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param united.name character string, if columns were united, you can specify name for the resulting column in plot +#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored +#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' +#' @return \strong{plotDepartureTimesPerTripPurpose} - Line plot with arrival time x-axis and number end activities on y-axis +#' +#' @export +plot_deptime_by_act <- function(trips_table, unite_activities = character(0), united_name = "united") { + + + # If some columns should be united + trips_table <- process_rename_category(trips_table = trips_table, + unite_template = unite_activities, + united_name = united_name, + column = "end_activity_type") + + + trips_table = trips_table %>% + mutate(dep_time = hour(dep_time)) %>% + mutate(end_activity_type = sapply(strsplit(end_activity_type,"_"),"[[",1)) %>% + count(dep_time,end_activity_type) + + + + + fig = plot_ly(trips_table,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~end_activity_type) + fig = fig %>% layout(yaxis = list(title = "Number of trips ending per trip purpose / Count of activities starting"), + xaxis = list(title = "Time [h]"), + barmode = "group") + + + fig + return(fig) + +} + + ###### Compare ###### #' Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis @@ -3344,6 +3446,7 @@ plot_map_trips_by_spatialcat <- function(trips_table, shape_table, } #####Processing##### + #' @export process_rename_mainmodes<-function(trips_table, unite.columns = character(0), united.name = "united"){ @@ -3354,6 +3457,17 @@ process_rename_mainmodes<-function(trips_table, } return(trips_table) } + +#' @export +process_rename_category<-function(trips_table, + unite_template= character(0), united_name = "united",column = "main_mode"){ + + if (length(unite_template) != 0) { + trips_table[[column]][grep(paste0(unite_template, collapse = "|"), trips_table[[column]])] <- united_name + } + return(trips_table) +} + #' @export process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ @@ -3375,23 +3489,18 @@ process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ return(trips_table) } #' @export -process_get_travelwaittime_by_mainmode_barchart<-function(trips_table, +process_get_travelwaittime_by_mainmode<-function(trips_table, time_format = "minute"){#also could be hours/seconds #get 2 columns with mean travel time and mean wait time grouped by main_mode in seconds - avg_time = trips_table %>% group_by(main_mode)%>% - summarize(trav_time_avg = hms::hms(seconds_to_period(mean(trav_time))), - wait_time_avg = hms::hms(seconds_to_period(mean(wait_time)))) %>% - mutate(trav_time_avg = as.numeric(trav_time_avg),wait_time_avg = as.numeric(wait_time_avg)) - if(time_format == "minute"){ - #convert seconds to minutes - avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/60, wait_time_avg = wait_time_avg/60) - return(avg_time) - }else if(time_format == "hour"){ - avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/3600, wait_time_avg = wait_time_avg/3600) - return(avg_time) - } + trips_table <-trips_table %>% + process_convert_time(time_format = time_format, time_column = "trav_time") %>% + process_convert_time(time_format = time_format, time_column = "wait_time") + + avg_time = trips_table %>% group_by(main_mode)%>% + summarize(trav_time_avg = mean(trav_time), + wait_time_avg = mean(wait_time)) return(avg_time) } @@ -3421,8 +3530,25 @@ process_append_distcat <- function(trips_table,distances_array = c(1000,2000,500 return(result_table) } -######Spatial###### +#' @export +process_convert_time <- function(trips_table,time_format = "hour",time_column = "dep_time"){ + + #get 2 columns with mean travel time and mean wait time grouped by main_mode in seconds + trips_table[[time_column]] = as.numeric(hms::hms(seconds_to_period(trips_table[[time_column]]))) + + if(time_format == "minute"){ + #convert seconds to minutes + trips_table[[time_column]] = trips_table[[time_column]]/60 + return(trips_table) + }else if(time_format == "hour"){ + trips_table[[time_column]] = trips_table[[time_column]]/3600 + return(trips_table) + } + return(trips_table) +} + +######Spatial###### #' Filtering of trips_table(from readTripsTable) depending on how they located in given shape #' #' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). diff --git a/R/personsOutput.R b/R/personsOutput.R index c9b9e40..539595e 100644 --- a/R/personsOutput.R +++ b/R/personsOutput.R @@ -63,6 +63,7 @@ readPersonsTable <- function(input_path = ".", n_max = Inf) { #' #' @export boxplotScoreDifferences <- function(personTibble_base, personTibble_policy){ + s joined <- inner_join(personTibble_base, personTibble_policy, by = "person", suffix = c("_base", "_policy")) %>% select(person, executed_score_base, diff --git a/man/compareBasePolicyOutput.Rd b/man/compareBasePolicyOutput.Rd deleted file mode 100644 index 16a1b0f..0000000 --- a/man/compareBasePolicyOutput.Rd +++ /dev/null @@ -1,28 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{compareBasePolicyOutput} -\alias{compareBasePolicyOutput} -\title{Chooses a function to compare output_trips from the folders. -baseFolder contains all base outputs, policyFolder contains all policy outputs.} -\usage{ -compareBasePolicyOutput( - baseFolder, - policyFolder, - dump.output.to = matsimDumpOutputDirectory -) -} -\arguments{ -\item{baseFolder}{specifies data source folder with multiple base output_trips} - -\item{policyFolder}{specifies data source folder with multiple policy output_trips} - -\item{dump.output.to}{that saves result of all comparisons between each base and each policy. -For now it creates plotModalShiftBar() for the output_trips} -} -\value{ -list of tibbles, list of all base and policy output_trips as tibble -} -\description{ -Chooses a function to compare output_trips from the folders. -baseFolder contains all base outputs, policyFolder contains all policy outputs. -} diff --git a/man/compareBasePolicyShapeOutput.Rd b/man/compareBasePolicyShapeOutput.Rd deleted file mode 100644 index a2afee6..0000000 --- a/man/compareBasePolicyShapeOutput.Rd +++ /dev/null @@ -1,34 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{compareBasePolicyShapeOutput} -\alias{compareBasePolicyShapeOutput} -\title{Chooses a function to compare output_trips from the folders. -baseFolder contains all base outputs, policyFolder contains all policy outputs.} -\usage{ -compareBasePolicyShapeOutput( - baseFolder, - policyFolder, - shapeFilePath, - crs, - dump.output.to = matsimDumpOutputDirectory -) -} -\arguments{ -\item{baseFolder}{specifies data source folder with multiple base output_trips} - -\item{policyFolder}{specifies data source folder with multiple policy output_trips} - -\item{shapeFilePath}{specifies shapeFile used for comparison} - -\item{crs}{numeric of EPSG code or proj4string, can be found in network/config file from output directory of MATSim simulation} - -\item{dump.output.to}{that saves result of all comparisons between each base and each policy. -For now it creates plotModalShiftBar() for the output_trips} -} -\value{ -list of tibbles, list of all base and policy output_trips as tibble -} -\description{ -Chooses a function to compare output_trips from the folders. -baseFolder contains all base outputs, policyFolder contains all policy outputs. -} diff --git a/man/deriveODMatrix.Rd b/man/deriveODMatrix.Rd deleted file mode 100644 index ef9f9fe..0000000 --- a/man/deriveODMatrix.Rd +++ /dev/null @@ -1,37 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{deriveODMatrix} -\alias{deriveODMatrix} -\title{Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper} -\usage{ -deriveODMatrix( - tripsTable, - shapePath, - crs, - dump.output.to = matsimDumpOutputDirectory, - simwrapper = FALSE, - colnames = "numeric", - outer = FALSE -) -} -\arguments{ -\item{tripsTable}{table of output trips(from readTripsTable) or path to trips_output file} - -\item{shapePath}{full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name)} - -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} - -\item{dump.output.to}{path to a folder to save csv file of ODMatrix} - -\item{simwrapper}{create output in a simwrapper form if set to path of the shapefile} - -\item{colnames}{if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values} - -\item{outer}{logical that represent if the table should contain outside flow of the shape, it isn't} -} -\value{ -tibble of origin/destination matrix -} -\description{ -Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper -} diff --git a/man/filterByRegion.Rd b/man/filterByRegion.Rd deleted file mode 100644 index d8677a3..0000000 --- a/man/filterByRegion.Rd +++ /dev/null @@ -1,38 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{filterByRegion} -\alias{filterByRegion} -\title{Filtering of trips_table(from readTripsTable) depending on how they located in given shape} -\usage{ -filterByRegion( - tripsTable, - shapeTable, - crs, - start.inshape = TRUE, - end.inshape = TRUE -) -} -\arguments{ -\item{tripsTable}{tibble of trips_output (from readTripsTable())} - -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} - -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} - -\item{start.inshape}{bool, defines trips to conclude (see Description)} - -\item{end.inshape}{bool, defines trips to conclude (see Description)} -} -\value{ -tibble, with filtered trips depending on shapeTable and special flags (see Description) -} -\description{ -Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -Please be aware that this filterByRegion currently only works, when one geometry is loaded.) -transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -and filters the trips from table depending on *.inshape flags: -if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape -} diff --git a/man/getCrsFromConfig.Rd b/man/getCrsFromConfig.Rd deleted file mode 100644 index 2401be7..0000000 --- a/man/getCrsFromConfig.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{getCrsFromConfig} -\alias{getCrsFromConfig} -\title{Reads an coordinate referenec system of MATSim output directory -from output_config.xml} -\usage{ -getCrsFromConfig(folder) -} -\arguments{ -\item{folder}{specifies path to find config} -} -\value{ -code of coordinate reference system -} -\description{ -Reads an coordinate referenec system of MATSim output directory -from output_config.xml -} diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 1700b52..8233581 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -23,7 +23,14 @@ \alias{plotTripTypesPieChart} \alias{compareTripTypesBarChart} \alias{plotMapWithTripsType} +\alias{compareBasePolicyOutput} +\alias{compareBasePolicyShapeOutput} \alias{appendDistanceCategory} +\alias{filterByRegion} +\alias{deriveODMatrix} +\alias{getCrsFromConfig} +\alias{transformToSf} +\alias{plot_deptime_by_act} \title{Deprecated function(s) in the matsimr package} \usage{ plotModalSplitPieChart( @@ -166,16 +173,58 @@ compareTripTypesBarChart( plotMapWithTripsType(table, shapeTable, crs, optimized = FALSE) +compareBasePolicyOutput( + baseFolder, + policyFolder, + dump.output.to = matsimDumpOutputDirectory +) + +compareBasePolicyShapeOutput( + baseFolder, + policyFolder, + shapeFilePath, + crs, + dump.output.to = matsimDumpOutputDirectory +) + appendDistanceCategory(tripsTable) + +filterByRegion( + tripsTable, + shapeTable, + crs, + start.inshape = TRUE, + end.inshape = TRUE +) + +deriveODMatrix( + tripsTable, + shapePath, + crs, + dump.output.to = matsimDumpOutputDirectory, + simwrapper = FALSE, + colnames = "numeric", + outer = FALSE +) + +getCrsFromConfig(folder) + +transformToSf(table, crs, geometry.type = st_multipoint()) + +plot_deptime_by_act( + trips_table, + unite_activities = character(0), + united_name = "united" +) } \arguments{ -\item{tripsTable}{tible of trips_output (from readTripsTable())} +\item{tripsTable}{tibble of trips_output (from readTripsTable())} -\item{unite.columns}{vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} -\item{united.name}{if columns were united, you can specify name for the resulting column in plot} +\item{united.name}{character string, if columns were united, you can specify name for the resulting column in plot} -\item{dump.output.to}{folder that saves resulting image of BarChart} +\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} \item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} @@ -200,6 +249,27 @@ appendDistanceCategory(tripsTable) \item{end.inshape}{bool, defines trips to conclude (see Description)} \item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot} + +\item{baseFolder}{specifies data source folder with multiple base output_trips} + +\item{policyFolder}{specifies data source folder with multiple policy output_trips} + +\item{shapeFilePath}{specifies shapeFile used for comparison} + +\item{shapePath}{full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name)} + +\item{simwrapper}{create output in a simwrapper form if set to path of the shapefile} + +\item{colnames}{if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values} + +\item{outer}{logical that represent if the table should contain outside flow of the shape, it isn't} + +\item{folder}{specifies path to find config} + +\item{geometry.type}{function of sf transformation, geometry.type can be (by default is st_multipoint())\cr +!!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or \cr +!!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or \cr +!!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!!} } \value{ \strong{plotModalSplitPieChart} - Pie Chart plot of transport mode distribution, values given in percents @@ -239,6 +309,22 @@ appendDistanceCategory(tripsTable) \strong{compareTripTypesBarChart} - plot with percentage of each type of trips between 2 tables \strong{plotMapWithTripsType} - plot that contains every trip with defined trip type + +\strong{compareBasePolicyOutput} - list of tibbles, list of all base and policy output_trips as tibble + +\strong{compareBasePolicyShapeOutput} - list of tibbles, list of all base and policy output_trips as tibble + +tibble of output_trips with distance category column + +\strong{filterByRegion} - tibble, with filtered trips depending on shapeTable and special flags (see Description) + +\strong{deriveODMatrix} - tibble of origin/destination matrix + +\strong{getCrsFromConfig} - code of coordinate reference system + +\strong{transformToSf} - sf object (data.frame with geometries depending to geometry.type) + +\strong{plotDepartureTimesPerTripPurpose} - Line plot with arrival time x-axis and number end activities on y-axis } \description{ These functions are provided for compatibility with older version of @@ -335,6 +421,44 @@ if start.inshape = TRUE & end.inshape = TRUE return table that contains trips in and saves output to dump.output.to \strong{plotMapWithTripsType} - plots every type of trips(inside, outside, origin and destinating) on map + +\strong{compareBasePolicyOutput} - Chooses a function to compare output_trips from the folders. +baseFolder contains all base outputs, policyFolder contains all policy outputs. + +\strong{compareBasePolicyShapeOutput} - Chooses a function to compare output_trips from the folders. +baseFolder contains all base outputs, policyFolder contains all policy outputs. + +\strong{appendDistanceCategory} - adds to trips output tibble additional column that represent distance as category + +\strong{filterByRegion} - Filtering of trips_table(from readTripsTable) depending on how they located in given shape\cr +Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +and filters the trips from table depending on *.inshape flags: \cr +if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape\cr +if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape\cr +if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape\cr +if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape + +\strong{deriveODMatrix} - Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper + +\strong{getCrsFromConfig} - Reads an coordinate referenec system of MATSim output directory +from output_config.xml + +\strong{transformToSf} - Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature)\cr +Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features +deletes from resulting data.frame start_x, end_x, start_y, end_y.\cr +And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring()\cr +Or adds start_wkt and end_wkt, if geometry.type = st_point()\cr +Added column/columns projected to given CRS (coordinate reference system), +that can be taken from network file of MATSimOutputDirectory\cr +Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" +to get which type of table was generated, if it is needed + +\strong{plotDepartureTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), +to make line plot with with values that represent +count of destination activities for a specific arrival time +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') } \section{Details}{ diff --git a/man/plot_arrtime_by_act.Rd b/man/plot_arrtime_by_act.Rd new file mode 100644 index 0000000..8c1bd52 --- /dev/null +++ b/man/plot_arrtime_by_act.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{plot_arrtime_by_act} +\alias{plot_arrtime_by_act} +\title{Deprecated function(s) in the matsimr package} +\usage{ +plot_arrtime_by_act( + trips_table, + unite_activities = character(0), + united_name = "united" +) +} +\arguments{ +\item{trips_table}{tibble of trips_output (from readTripsTable())} + +\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} + +\item{united.name}{character string, if columns were united, you can specify name for the resulting column in plot} + +\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} + +\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} +} +\value{ +\strong{plot_arrtime_by_act} - Line plot with arrival time x-axis and number end activities on y-axis +} +\description{ +\strong{plot_arrtime_by_act} - Takes Table trips_output (from readTripsTable()), +to make line plot with with values that represent +count of destination activities for a specific arrival time +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +} diff --git a/man/transformToSf.Rd b/man/transformToSf.Rd deleted file mode 100644 index 3a4f6c6..0000000 --- a/man/transformToSf.Rd +++ /dev/null @@ -1,33 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{transformToSf} -\alias{transformToSf} -\title{Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature)} -\usage{ -transformToSf(table, crs, geometry.type = st_multipoint()) -} -\arguments{ -\item{table}{tibble of trips_output (from readTripsTable())} - -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} - -\item{geometry.type}{function of sf transformation, geometry.type can be (by default is st_multipoint()) -!!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or -!!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or -!!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!!} -} -\value{ -sf object (data.frame with geometries depending to geometry.type) -} -\description{ -Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features -deletes from resulting data.frame start_x, end_x, start_y, end_y. -And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring() -Or adds start_wkt and end_wkt, if geometry.type = st_point() -Added column/columns projected to given CRS (coordinate reference system), -that can be taken from network file of MATSimOutputDirectory -} -\details{ -Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" -to get which type of table was generated, if it is needed -} From 329e1791715fa6d3236f383905a42d13447ace8c Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 29 Jun 2023 12:17:17 +0200 Subject: [PATCH 41/87] push after document() --- man/filterByRegion.Rd | 39 --------------------------------------- man/matsimr-deprecated.Rd | 9 +-------- man/transformToSf.Rd | 32 -------------------------------- 3 files changed, 1 insertion(+), 79 deletions(-) delete mode 100644 man/filterByRegion.Rd delete mode 100644 man/transformToSf.Rd diff --git a/man/filterByRegion.Rd b/man/filterByRegion.Rd deleted file mode 100644 index 9fc7348..0000000 --- a/man/filterByRegion.Rd +++ /dev/null @@ -1,39 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{filterByRegion} -\alias{filterByRegion} -\title{Deprecated function(s) in the matsimr package} -\usage{ -filterByRegion( - tripsTable, - shapeTable, - crs, - start.inshape = TRUE, - end.inshape = TRUE -) -} -\arguments{ -\item{tripsTable}{tibble of trips_output (from readTripsTable())} - -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} - -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} - -\item{start.inshape}{bool, defines trips to conclude (see Description)} - -\item{end.inshape}{bool, defines trips to conclude (see Description)} -} -\value{ -\strong{filterByRegion} - tibble, with filtered trips depending on shapeTable and special flags (see Description) -} -\description{ -\strong{filterByRegion} - Filtering of trips_table(from readTripsTable) depending on how they located in given shape\cr -Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -Please be aware that this filterByRegion currently only works, when one geometry is loaded.) -transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -and filters the trips from table depending on *.inshape flags: -if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape -} diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 93bf39a..8233581 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -31,7 +31,6 @@ \alias{getCrsFromConfig} \alias{transformToSf} \alias{plot_deptime_by_act} - \title{Deprecated function(s) in the matsimr package} \usage{ plotModalSplitPieChart( @@ -210,7 +209,6 @@ deriveODMatrix( getCrsFromConfig(folder) - transformToSf(table, crs, geometry.type = st_multipoint()) plot_deptime_by_act( @@ -220,7 +218,7 @@ plot_deptime_by_act( ) } \arguments{ -\item{tripsTable}{table of output trips(from readTripsTable) or path to trips_output file} +\item{tripsTable}{tibble of trips_output (from readTripsTable())} \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} @@ -228,7 +226,6 @@ plot_deptime_by_act( \item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} - \item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} \item{input_path}{character string, path to matsim output directory or http link to the file.} @@ -269,12 +266,10 @@ plot_deptime_by_act( \item{folder}{specifies path to find config} - \item{geometry.type}{function of sf transformation, geometry.type can be (by default is st_multipoint())\cr !!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or \cr !!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or \cr !!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!!} - } \value{ \strong{plotModalSplitPieChart} - Pie Chart plot of transport mode distribution, values given in percents @@ -330,7 +325,6 @@ tibble of output_trips with distance category column \strong{transformToSf} - sf object (data.frame with geometries depending to geometry.type) \strong{plotDepartureTimesPerTripPurpose} - Line plot with arrival time x-axis and number end activities on y-axis - } \description{ These functions are provided for compatibility with older version of @@ -465,7 +459,6 @@ to get which type of table was generated, if it is needed to make line plot with with values that represent count of destination activities for a specific arrival time Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') - } \section{Details}{ diff --git a/man/transformToSf.Rd b/man/transformToSf.Rd deleted file mode 100644 index 74eb5cf..0000000 --- a/man/transformToSf.Rd +++ /dev/null @@ -1,32 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R -\name{transformToSf} -\alias{transformToSf} -\title{Deprecated function(s) in the matsimr package} -\usage{ -transformToSf(table, crs, geometry.type = st_multipoint()) -} -\arguments{ -\item{table}{tibble of trips_output (from readTripsTable())} - -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} - -\item{geometry.type}{function of sf transformation, geometry.type can be (by default is st_multipoint()) -!!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or -!!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or -!!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!!} -} -\value{ -\strong{transformToSf} - sf object (data.frame with geometries depending to geometry.type) -} -\description{ -\strong{transformToSf} - Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature)\cr -Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features -deletes from resulting data.frame start_x, end_x, start_y, end_y.\cr -And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring()\cr -Or adds start_wkt and end_wkt, if geometry.type = st_point()\cr -Added column/columns projected to given CRS (coordinate reference system), -that can be taken from network file of MATSimOutputDirectory\cr -Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" -to get which type of table was generated, if it is needed -} From 8ddeedd24cb5a5c3733faac536746b481aa1535b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Thu, 29 Jun 2023 12:42:37 +0200 Subject: [PATCH 42/87] added documentation for merge --- R/output_trips.R | 308 +++++++++++++++++++++++------------------------ 1 file changed, 153 insertions(+), 155 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index ed8e0c5..3233078 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2268,13 +2268,13 @@ transformToSf <- function(table, #####Reading##### -#' Load MATSIM output_trips table into Memory +#' Load MATSIM output_trips table into memory #' #' Loads a MATSim CSV output_trips from file or archive, #' creating a tibble with columns as in csv file #' -#' @param input_path character string, path to matsim output directory or http link to the file. -#' @param n_max integer, maximum number of lines to read within output_trips +#' @param input_path character string, path to the MATSim output directory or http link to the file. +#' @param n_max optional, integer, maximum number of lines to read, standard value is Inf #' @return tibble of trips_output #' #' @export @@ -2327,21 +2327,21 @@ read_output_trips <- function(input_path = ".", n_max = Inf) { #####Plotting##### -#' Plot main_mode distribution as a Pie Chart +#' Plot the distribution of modes as a pie chart #' -#' Takes Table trips_output (from \link{readTripsTable}), -#' to plot pie chart with with values that represent -#' percentage of using transport modes from trips +#' Uses the dataframe trips_output (from \link{readTripsTable}), +#' to plot a pie chart of the modal split using the column main_mode #' -#' Function automatically detects transport_modes from table -#' and plots pie chart. -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' The function automatically detects the modes plots a pie chart. +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' @param trips_table tibble of trips_output (from \link{readTripsTable}) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' -#' @return Pie Chart plot of transport mode distribution, values given in percents +#' @return pie chart plot of transport mode distribution, values given in percent #' #' @export plot_mainmode_piechart <- function(trips_table, @@ -2369,20 +2369,21 @@ plot_mainmode_piechart <- function(trips_table, } -#' Plot main_mode distribution as a bar Chart +#' Plot the distribution of modes as a bar chart #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' percentage of using transport modes from trips +#' Takes the data frame trips_output (from \link{readTripsTable()}) +#' to plot a bar chart of the modal split using the column main_mode. #' -#' Function automatically detects transport_modes from table -#' and plots pie chart with percentage of distribution. -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' The modal shares are given in percentages. #' +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' -#' @param trips_table tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' +#' @param trips_table tibble of trips_output (from \link{readTripsTable()}) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' #' @return Bar Chart plot of transport mode distribution, values given in percents #' @@ -2411,17 +2412,18 @@ plot_mainmode_barchart <- function(trips_table, return(fig) } -#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis +#' Plot travel and wait time for each mode as a bar chart #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' time spent on traveling/waiting -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes the data frame trips_output (from \links{readTripsTable()}), +#' to plot a bar chart of travel and wait times. +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param trips_table tibble of trips_output (from \links{readTripsTable()}) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' #' @return Bar Chart plot of average time spent on travel/wait #' @@ -2457,17 +2459,18 @@ plot_travelwaittime_mean_barchart <- function(trips_table, -#' Bar Chart with distance travelled on x-axis and number of trips on y-axis +#' Bar Chart with distance traveled on x-axis and number of trips on y-axis #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' number of trips ~ distance travelled -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes the data frame trips_output (from \link{readTripsTable()}) and categorizes the traveled distances into pre-defined bins +#' to plot a histogram of the traveled distances. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param trips_table tibble of trips_output (from readTripsTable()) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' @return Bar Chart plot of count of trips among distance travelled #' #' @export @@ -2499,17 +2502,18 @@ plot_distcat_by_mainmode_barchart <- function(trips_table, } -#' Bar Chart with distance travelled on x-axis and number of trips on y-axis +#' Bar chart with average distance traveled for each mode on x-axis and number of trips on y-axis #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' average distance traveled ~ main mode used -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes the data frame trips_output (from \link{readTripsTable()}), +#' to plot a bar chart of the average distance traveled for each main mode, +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart#' +#' @param trips_table tibble of trips_output (from readTripsTable()) +#'@param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' @return Bar Chart plot of distance traveled per mode #' #' @export @@ -2544,18 +2548,19 @@ plot_distance_by_mainmode_barchart <- function(trips_table, return(fig) } -#' Line plot with departure time x-axis and number of trips on y-axis +#' Line plot with departure time on x-axis and number of trips on y-axis #' -#' Takes Table trips_output (from readTripsTable()), -#' to make line plot with with values that represent -#' count of trips for a specific departure time by main_mode -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes data frame trips_output (from \link{readTripsTable()}), +#' to create a line plot of the number of trips for a specific departure time by main_mode +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @return Line Chart plot of trips count by departure mode per mode +#' @param tripsTable tibble of trips_output (from readTripsTable()) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode +#' @return Line plot of trips count by departure time per mode #' #' @export plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, @@ -2583,7 +2588,7 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, } #' Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart -#' +#' XXXX #' #' #' @param table tibble of trips_output (from readTripsTable()) @@ -2618,7 +2623,7 @@ plot_spatialtype_by_shape_piechart <- function(trips_table, shape_table, crs) { } #' Bar Chart with tripType on x-axis and travelled distance on y-axis -#' +#' XXXX #' Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' travelled distance of each tripType related to the shapeTable @@ -2647,7 +2652,7 @@ plot_distance_by_spatialcat <- function(trips_table, shape_table, crs, euclidian #' Deprecated function(s) in the matsimr package -#' +#' XXXX #' \strong{plot_arrtime_by_act} - Takes Table trips_output (from readTripsTable()), #' to make line plot with with values that represent #' count of destination activities for a specific arrival time @@ -2696,7 +2701,7 @@ plot_arrtime_by_act <- function(trips_table, unite_activities = character(0), un } #' Deprecated function(s) in the matsimr package -#' +#' XXXX #' \strong{plotDepartureTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), #' to make line plot with with values that represent #' count of destination activities for a specific arrival time @@ -2745,20 +2750,20 @@ plot_deptime_by_act <- function(trips_table, unite_activities = character(0), un ###### Compare ###### -#' Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis -#' -#' Takes 2 Tables trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Bar chart comparing distance traveled on x-axis and number of trips on y-axis for two different runs + +#' Takes two data frames (from \link{readTripsTable()}), categorizes the traveled distances into pre-defined bins +#' and plots the difference in number of trips for each bin. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table1 tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 -#' @param trips_table2 tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly + +#' @param tripsTable1 tibble of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 +#' @param tripsTable2 tibble of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' @return Bar Chart plot of count of trips among distance travelled #' #' @export @@ -2808,25 +2813,22 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, - -#' Plot bar chart diagram of transport mode changes +#' Plot bar chart of changes in modal split #' -#' Takes two trips_table (from readTripsTable), and collects -#' changes between transport mode distribution of these tables -#' to make bar chart diagram with dodging positioning from this data +#' Takes two data frames (from \link{readTripsTable()}), calculates the +#' changes in mode shares and plots them as a bar chart +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' -#' Function calculates number of each transport mode used in -#' first and second table, and draws plot that represent how -#' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) -#' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") -#' Using parameter show.onlyChanges #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name if columns were united, you can specify name for the resulting column in plot #' -#' @return plots Bar Chart of transport mode changes with additional files for simwrapper +#' @param tripsTable1 tibble of trips_output (from readTripsTable()) +#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#'@param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode +#' +#' @return plots bar chart of changes in modal split #' #' @export plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, @@ -2857,23 +2859,19 @@ plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, #' Plot alluvial/sankey diagram of transport mode changes #' -#' Takes two trips_table (from readTripsTable), and collects -#' changes between transport mode distribution of these tables -#' to make alluvial diagram from this data +#' Takes two data frames (from \link{readTripsTable()}) and compares the mode choice for each agent and summarizes the results, showing the modal shift. +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' The parameter show.onlyChanges allows the visualization of only the mode shift (excluding the trips that do not change mode). Standard value is FALSE. #' -#' Function calculates number of each transport mode used in -#' first and second table, and draws plot that represent how -#' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) -#' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") -#' Using parameter show.onlyChanges +#' @param tripsTable1 tibble of trips_output (from readTripsTable()) +#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#' @param show.onlyChanges boolean, if it is set to TRUE the sankey diagram only shows the mode shift +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param show.onlyChanges boolean, if it is set to TRUE => sankey diagram only contains changes on axes -#' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name if columns were united, you can specify name for the resulting column in plot -#' -#' @return Alluvial diagram that represents changes in transport mode distribution of trip tables +#' @return Alluvial diagram that represents changes in transport mode distribution #' #' @export plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, @@ -2948,16 +2946,17 @@ plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, #' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis #' -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' time spent on traveling/waiting -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Takes the data frame trips_output (from \link{readTripsTable()}), +#' to plot a bar chart of the traveling/waiting time +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param tripsTable1 tibble of trips_output (from readTripsTable()) +#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode #' #' @return Bar Chart plot of average time spent on travel/wait #' @@ -3012,7 +3011,7 @@ plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_ } #' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis -#' +#' XXXX #' Takes Table trips_output (from readTripsTable()), #' to plot bar chart with with values that represent #' time spent on traveling/waiting @@ -3055,7 +3054,7 @@ plot_compare_count_by_spatialcat <- function(trips_table1,trips_table2, shape_ta #' Plots start and end coordinates of the given trips table on an osm map -#' +#' XXXX #' @param table tibble of trips_output (from readTripsTable()) #' #' @@ -3208,7 +3207,7 @@ plot_map_trips <- function(trips_table, crs,optimized = FALSE, #' Plots every type of trips(inside, outside, origin and destinating) on map -#' +#' XXXX #' #' #' @param table tibble of trips_output (from readTripsTable()) @@ -3446,7 +3445,7 @@ plot_map_trips_by_spatialcat <- function(trips_table, shape_table, } #####Processing##### - +#' XXXX #' @export process_rename_mainmodes<-function(trips_table, unite.columns = character(0), united.name = "united"){ @@ -3549,24 +3548,27 @@ process_convert_time <- function(trips_table,time_format = "hour",time_column = } ######Spatial###### -#' Filtering of trips_table(from readTripsTable) depending on how they located in given shape +#' XXXX trips_table but shapeTable - fix naming +#' XXXX finish when code revision is done +#' Filters trips_table(from ,\link{readTripsTable}) depending by location using a shapefile #' -#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) -#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -#' and filters the trips from table depending on *.inshape flags: -#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips \strong{inside} of the given shape -#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which \strong{originating} in the shape -#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which \strong{destinating} in the shape -#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which \strong{outside} of the given shape +#' Uses trips_table and an sf object (can be created using the function st_read()), +#' transforms both objects to match a mutual coordinate system (crs) +#' and filters the trips from trips_table depending on *.inshape flags: +#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape +#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape #' #' @param trips_table tibble of trips_output (from readTripsTable()) #' #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file +#' +#' @param start.inshape bool, defines trips to conclude (see Description) #' -#' @param spatial_type character parameter,categories of spatial information used to specify which kind of trips should be filtered. Takes as input 4 templates: inside, outside, originating, destinating +#' @param end.inshape bool, defines trips to conclude (see Description) #' #' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) #' @@ -3634,7 +3636,7 @@ process_filter_by_shape <- function(trips_table, } #' Appending spatial category as additional column to output_trips tibble -#' +#' XXXX #' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). #' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) #' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) @@ -3702,10 +3704,10 @@ process_append_spatialcat <- function(trips_table, } -#' Reads an coordinate referenec system of MATSim output directory -#' from output_config.xml +#' Reads the coordinate reference system from a MATSim output directory +#' (output_config.xml) #' -#' @param config_path specifies path to find config +#' @param config_path specifies path to configuration file #' #' #' @return code of coordinate reference system @@ -3741,23 +3743,23 @@ process_get_crs_from_config <- function(config_path) { return(NA) } -#' Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper -#' +#' Creates an origin/destination matrix either in conventional form (row names = origin, column names = destination) +#' or for simwrapper (origin and destination as columns) #' #' -#' @param tripsTable table of output trips(from readTripsTable) or path to trips_output file +#' @param tripsTable tibble of trips_output (from \link{readTripsTable}) #' -#' @param shapePath full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name) +#' @param shapePath string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file) #' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file #' -#' @param dump.output.to path to a folder to save csv file of ODMatrix +#' @param dump.output.to string, path to a folder to save the .csv file #' -#' @param colnames if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values +#' @param colnames string, column names can be specified (i.e. to fit the shape file), if not they are numbered #' -#' @param simwrapper create output in a simwrapper form if set to path of the shapefile +#' @param simwrapper boolean, creates output in the format used for simwrapper if the path for the shapefile is specified #' -#' @param outer logical that represent if the table should contain outside flow of the shape, it isn't +#' @param outer boolean, determines if flows outside of the shapefile are used, standard value is FALSE #' #' @return tibble of origin/destination matrix #' @@ -3888,28 +3890,24 @@ process_get_od_matrix<- function(tripsTable, -#' Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature) +#' Transforms the data frame trips_output (from \links{readTripsTable}) from tibble to sf (table with geometry features) #' -#' Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features -#' deletes from resulting data.frame start_x, end_x, start_y, end_y. -#' And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring() -#' Or adds start_wkt and end_wkt, if geometry.type = st_point() -#' Added column/columns projected to given CRS (coordinate reference system), -#' that can be taken from network file of MATSimOutputDirectory +#' Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features. +#' If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format), +#' if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt. +#' Added column/columns are projected to given CRS (coordinate reference system). +#' The columns start_x, end_x, start_y, end_y are deleted from the resulting data frame. #' -#' Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" -#' to get which type of table was generated, if it is needed +#' @param table tibble trips_output (from readTripsTable()) #' -#' @param table tibble of trips_output (from readTripsTable()) +#' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file #' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation -#' -#' @param geometry.type function of sf transformation, geometry.type can be (by default is st_multipoint()) -#' !!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or -#' !!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or -#' !!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!! +#' @param geometry.type type of sf transformation, default is st_multipoint(), geometry.type can be: +#' !!!st_point()- resulting table contains two geometry columns: start_wkt and end_wkt, representing start and end points as POINTS!!! or +#' !!!st_multipoint()- resulting table contains one geometry column, representing start and end points as MULTIPOINT!!! or +#' !!!st_linestring() - resulting table contains one geometry column, representing the line between start and end points as LINESTRING!!! #' -#' @return sf object (data.frame with geometries depending to geometry.type) +#' @return sf object (data frame with geometries depending on geometry.type) #' #' @export process_convert_table_to_sf <- function(table, From 868806b9e8a40cada319c8e5550a0e24faae2ccb Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 29 Jun 2023 14:24:41 +0200 Subject: [PATCH 43/87] fixed parenthesis in plot_trips_count_by_deptime... --- NAMESPACE | 1 + R/output_trips.R | 13 ++++++-- man/createCountScatterPlot.Rd | 6 ++-- man/generateXYHexagonYaml.Rd | 6 ++-- man/getCrsFromConfig.Rd | 4 +-- man/mergeCountsAndLinks.Rd | 18 +++++----- ...ot_compare_distcat_by_mainmode_barchart.Rd | 29 ++++++++-------- man/plot_compare_mainmode_barchart.Rd | 29 +++++++--------- man/plot_compare_mainmode_sankey.Rd | 29 +++++++--------- ...plot_compare_travelwaittime_by_mainmode.Rd | 33 +++++++++++++++++++ ...are_travelwaittime_by_mainmode_barchart.Rd | 19 ++++++----- man/plot_distance_by_mainmode_barchart.Rd | 17 +++++----- man/plot_distcat_by_mainmode_barchart.Rd | 19 ++++++----- man/plot_mainmode_barchart.Rd | 23 ++++++------- man/plot_mainmode_piechart.Rd | 22 ++++++------- man/plot_travelwaittime_mean_barchart.Rd | 19 ++++++----- ...count_by_deptime_and_mainmode_linechart.Rd | 19 ++++++----- ...eComparisonSimwrapperDashboardFromTable.Rd | 10 +++--- man/prepareSimwrapperDashboardFromFolder.Rd | 12 +++---- man/prepareSimwrapperDashboardFromTable.Rd | 8 ++--- man/processDtvEstimationQuality.Rd | 11 +++---- man/processLinkStatsDtvDistribution.Rd | 10 +++--- man/process_filter_by_shape.Rd | 13 ++++---- man/process_get_crs_from_config.Rd | 10 +++--- man/process_get_od_matrix.Rd | 20 ++++++----- man/readCounts.Rd | 4 +-- man/readLinkStats.Rd | 8 ++--- man/readTripsTable.Rd | 6 ++-- man/read_network.Rd | 2 +- man/read_output_trips.Rd | 6 ++-- man/transformToSf.Rd | 31 ++++++++--------- 31 files changed, 246 insertions(+), 211 deletions(-) create mode 100644 man/plot_compare_travelwaittime_by_mainmode.Rd diff --git a/NAMESPACE b/NAMESPACE index 9d846bf..f7b8484 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -32,6 +32,7 @@ export(plotTripTypesPieChart) export(plot_compare_distcat_by_mainmode_barchart) export(plot_compare_mainmode_barchart) export(plot_compare_mainmode_sankey) +export(plot_compare_travelwaittime_by_mainmode) export(plot_compare_travelwaittime_by_mainmode_barchart) export(plot_distance_by_mainmode_barchart) export(plot_distcat_by_mainmode_barchart) diff --git a/R/output_trips.R b/R/output_trips.R index 41a9faa..26ad106 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2540,13 +2540,13 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, #' #' @export plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, - unite.modes = character(0), + unite.columns = character(0), united.name = "united") { - # renaming/uniting of modes + # If some columns should be united trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, + unite.columns = unite.columns, united.name = united.name) @@ -2555,6 +2555,13 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, mutate(dep_time = hour(dep_time)) %>% count(dep_time,main_mode) + #plotting + fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) + fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") + + fig + return(fig) +} #' Plot bar chart of changes in modal split diff --git a/man/createCountScatterPlot.Rd b/man/createCountScatterPlot.Rd index c53ea42..5018913 100644 --- a/man/createCountScatterPlot.Rd +++ b/man/createCountScatterPlot.Rd @@ -25,11 +25,11 @@ A ggplot Scatterplotplot, which can be adjusted, if needed. } \description{ Takes a tibble from mergeCountsAndLinks. -A scatterplot with counts on the x axis and matsim dtv on the y axis is created and colored +A scatterplot with counts on the x axis and MATSim dtv on the y axis is created and colored by the road type. -Lower and upper Limits define the section which is considered as an 'exact' estimation. Limits +Lower and upper limits define the section which is considered an 'exact' estimation. Limits are defined by custom formulas. } \details{ -The function calls the matsim-r function processDtvEstimationQuality which is handeling the limits. +The function calls the matsim-r function processDtvEstimationQuality which is handling the limits. } diff --git a/man/generateXYHexagonYaml.Rd b/man/generateXYHexagonYaml.Rd index a28b5fb..cc56d90 100644 --- a/man/generateXYHexagonYaml.Rd +++ b/man/generateXYHexagonYaml.Rd @@ -11,11 +11,11 @@ generateXYHexagonYaml( ) } \arguments{ -\item{pathToOutputTrips}{specifies path to a data source of output_trips} +\item{pathToOutputTrips}{file path to output_trips.csv file} -\item{crs}{specifies an coordinate reference system of output_trips} +\item{crs}{specifies the coordinate reference system of output_trips} -\item{dump.output.to}{path to an folder with dashboard} +\item{dump.output.to}{path to a folder with simwrapper dashboard} } \value{ changed file diff --git a/man/getCrsFromConfig.Rd b/man/getCrsFromConfig.Rd index 2401be7..ab0ceb0 100644 --- a/man/getCrsFromConfig.Rd +++ b/man/getCrsFromConfig.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/output_trips.R \name{getCrsFromConfig} \alias{getCrsFromConfig} -\title{Reads an coordinate referenec system of MATSim output directory +\title{Reads an coordinate reference system of MATSim output directory from output_config.xml} \usage{ getCrsFromConfig(folder) @@ -14,6 +14,6 @@ getCrsFromConfig(folder) code of coordinate reference system } \description{ -Reads an coordinate referenec system of MATSim output directory +Reads an coordinate reference system of MATSim output directory from output_config.xml } diff --git a/man/mergeCountsAndLinks.Rd b/man/mergeCountsAndLinks.Rd index eb84435..f9cd926 100644 --- a/man/mergeCountsAndLinks.Rd +++ b/man/mergeCountsAndLinks.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/counts.R \name{mergeCountsAndLinks} \alias{mergeCountsAndLinks} -\title{Load Counts, a limited number of Linkstats and Network links as joined tibble into memory} +\title{Join counts and linkstats to the network, creating a tibble into memory} \usage{ mergeCountsAndLinks( counts, @@ -19,20 +19,20 @@ mergeCountsAndLinks( \item{network}{Tibble with network nodes and links} -\item{linkStats}{List with link stats tibbles} +\item{linkStats}{List with linkstats tibbles} -\item{networkModes}{a vector with network modes, which are needed for analysis} +\item{networkModes}{Vector with network modes that will be analyzed, default is "car".} -\item{aggr_to}{Determinates if data should be aggregated to hour values or DTV, can either be "day" or "hour"} +\item{aggr_to}{Determines if data should be aggregated into hourly bins or as daily traffic volume, can either be "day" or "hour"} -\item{earliest}{Lower limit to filter link stats by time, default is 0} +\item{earliest}{Integer. Lower limit to filter link stats by time, default = 0.} -\item{latest}{Upper limit to filter link stats by time, default is 86400 (midnight)} +\item{latest}{Integer. Upper limit to filter link stats by time, default = 86400 (midnight).} } \value{ -Long-format tibble with MATSim link id as key ("loc_id"), traffic volume from MATSim runs and link type +Long-format tibble with MATSim link id as key ("loc_id"), traffic volumes from MATSim runs and link type } \description{ -Function to join counts, network links and several matsim link stats. Data can be aggregated -and filtered by time or network mode. +Function to join counts, linkstats and network links. Data can be aggregated +and filtered by time or mode. } diff --git a/man/plot_compare_distcat_by_mainmode_barchart.Rd b/man/plot_compare_distcat_by_mainmode_barchart.Rd index 056ed61..807a64a 100644 --- a/man/plot_compare_distcat_by_mainmode_barchart.Rd +++ b/man/plot_compare_distcat_by_mainmode_barchart.Rd @@ -2,36 +2,37 @@ % Please edit documentation in R/output_trips.R \name{plot_compare_distcat_by_mainmode_barchart} \alias{plot_compare_distcat_by_mainmode_barchart} -\title{Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis} +\title{Bar chart comparing distance traveled on x-axis and number of trips on y-axis for two different runs +Takes two data frames (from \link{readTripsTable()}), categorizes the traveled distances into pre-defined bins +and plots the difference in number of trips for each bin. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) +Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united')} \usage{ plot_compare_distcat_by_mainmode_barchart( trips_table1, trips_table2, - unite.columns = character(0), + unite.modes = character(0), united.name = "united", dist_column = "dist_cat", distances_array = c(1000, 2000, 5000, 10000, 20000, 50000, 1e+05) ) } \arguments{ -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{unite.modes}{vector of character strings, +changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +using the function (\link{process_rename_mainmodes})} -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +\item{united.name}{character string, specifies the name of the united mode} -\item{tripsTable1}{tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1} +\item{tripsTable1}{tibble of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1} -\item{tripsTable2}{tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted} - -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} - -\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} +\item{tripsTable2}{tibble of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted} } \value{ Bar Chart plot of count of trips among distance travelled } \description{ -Takes 2 Tables trips_output (from readTripsTable()), -to plot bar chart with with values that represent -difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Bar chart comparing distance traveled on x-axis and number of trips on y-axis for two different runs +Takes two data frames (from \link{readTripsTable()}), categorizes the traveled distances into pre-defined bins +and plots the difference in number of trips for each bin. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) +Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_compare_mainmode_barchart.Rd b/man/plot_compare_mainmode_barchart.Rd index ecc40df..395491e 100644 --- a/man/plot_compare_mainmode_barchart.Rd +++ b/man/plot_compare_mainmode_barchart.Rd @@ -2,36 +2,31 @@ % Please edit documentation in R/output_trips.R \name{plot_compare_mainmode_barchart} \alias{plot_compare_mainmode_barchart} -\title{Plot bar chart diagram of transport mode changes} +\title{Plot bar chart of changes in modal split} \usage{ plot_compare_mainmode_barchart( trips_table1, trips_table2, - unite.columns = character(0), + unite.modes = character(0), united.name = "united" ) } \arguments{ -\item{unite.columns}{vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{unite.modes}{vector of character strings, +changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +using the function (\link{process_rename_mainmodes})} -\item{united.name}{if columns were united, you can specify name for the resulting column in plot} +\item{united.name}{character string, specifies the name of the united mode} -\item{tripsTable1}{tible of trips_output (from readTripsTable())} +\item{tripsTable1}{tibble of trips_output (from readTripsTable())} -\item{tripsTable2}{tible of trips_output (from readTripsTable())} +\item{tripsTable2}{tibble of trips_output (from readTripsTable())} } \value{ -plots Bar Chart of transport mode changes with additional files for simwrapper +plots bar chart of changes in modal split } \description{ -Takes two trips_table (from readTripsTable), and collects -changes between transport mode distribution of these tables -to make bar chart diagram with dodging positioning from this data -} -\details{ -Function calculates number of each transport mode used in -first and second table, and draws plot that represent how -distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) -Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") -Using parameter show.onlyChanges +Takes two data frames (from \link{readTripsTable()}), calculates the +changes in mode shares and plots them as a bar chart +Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_compare_mainmode_sankey.Rd b/man/plot_compare_mainmode_sankey.Rd index 6288d92..a144e4f 100644 --- a/man/plot_compare_mainmode_sankey.Rd +++ b/man/plot_compare_mainmode_sankey.Rd @@ -8,33 +8,28 @@ plot_compare_mainmode_sankey( trips_table1, trips_table2, show.onlyChanges = FALSE, - unite.columns = character(0), + unite.modes = character(0), united.name = "united" ) } \arguments{ -\item{show.onlyChanges}{boolean, if it is set to TRUE => sankey diagram only contains changes on axes} +\item{show.onlyChanges}{boolean, if it is set to TRUE the sankey diagram only shows the mode shift} -\item{unite.columns}{vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{unite.modes}{vector of character strings, +changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +using the function (\link{process_rename_mainmodes})} -\item{united.name}{if columns were united, you can specify name for the resulting column in plot} +\item{united.name}{character string, specifies the name of the united mode} -\item{tripsTable1}{tible of trips_output (from readTripsTable())} +\item{tripsTable1}{tibble of trips_output (from readTripsTable())} -\item{tripsTable2}{tible of trips_output (from readTripsTable())} +\item{tripsTable2}{tibble of trips_output (from readTripsTable())} } \value{ -Alluvial diagram that represents changes in transport mode distribution of trip tables +Alluvial diagram that represents changes in transport mode distribution } \description{ -Takes two trips_table (from readTripsTable), and collects -changes between transport mode distribution of these tables -to make alluvial diagram from this data -} -\details{ -Function calculates number of each transport mode used in -first and second table, and draws plot that represent how -distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) -Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") -Using parameter show.onlyChanges +Takes two data frames (from \link{readTripsTable()}) and compares the mode choice for each agent and summarizes the results, showing the modal shift. +Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +The parameter show.onlyChanges allows the visualization of only the mode shift (excluding the trips that do not change mode). Standard value is FALSE. } diff --git a/man/plot_compare_travelwaittime_by_mainmode.Rd b/man/plot_compare_travelwaittime_by_mainmode.Rd new file mode 100644 index 0000000..86ab86a --- /dev/null +++ b/man/plot_compare_travelwaittime_by_mainmode.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{plot_compare_travelwaittime_by_mainmode} +\alias{plot_compare_travelwaittime_by_mainmode} +\title{Bar Chart comparing two runs with main_mode on x-axis and average travel/wait time on y-axis} +\usage{ +plot_compare_travelwaittime_by_mainmode( + trips_table1, + trips_table2, + unite.modes = character(0), + united.name = "united", + time_format = "minute" +) +} +\arguments{ +\item{unite.modes}{vector of character strings, +changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +using the function (\link{process_rename_mainmodes})} + +\item{united.name}{character string, specifies the name of the united mode} + +\item{tripsTable1}{tibble of trips_output (from readTripsTable())} + +\item{tripsTable2}{tibble of trips_output (from readTripsTable())} +} +\value{ +Bar chart plot comparing average time spent on travel/wait of two runs +} +\description{ +Takes two data frames (from \link{readTripsTable()}), +to plot a comparison bar chart of travel and wait times. +Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +} diff --git a/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd b/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd index 351f164..3e8b5a4 100644 --- a/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd +++ b/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd @@ -7,26 +7,27 @@ plot_compare_travelwaittime_by_mainmode_barchart( trips_table1, trips_table2, - unite.columns = character(0), + unite.modes = character(0), united.name = "united", time_format = "minute" ) } \arguments{ -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{unite.modes}{vector of character strings, +changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +using the function (\link{process_rename_mainmodes})} -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +\item{united.name}{character string, specifies the name of the united mode} -\item{tripsTable1}{tible of trips_output (from readTripsTable())} +\item{tripsTable1}{tibble of trips_output (from readTripsTable())} -\item{tripsTable2}{tible of trips_output (from readTripsTable())} +\item{tripsTable2}{tibble of trips_output (from readTripsTable())} } \value{ Bar Chart plot of average time spent on travel/wait } \description{ -Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -time spent on traveling/waiting -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Takes the data frame trips_output (from \link{readTripsTable()}), +to plot a bar chart of the traveling/waiting time +Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_distance_by_mainmode_barchart.Rd b/man/plot_distance_by_mainmode_barchart.Rd index dc264f5..683cde9 100644 --- a/man/plot_distance_by_mainmode_barchart.Rd +++ b/man/plot_distance_by_mainmode_barchart.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/output_trips.R \name{plot_distance_by_mainmode_barchart} \alias{plot_distance_by_mainmode_barchart} -\title{Bar Chart with distance travelled on x-axis and number of trips on y-axis} +\title{Bar chart with average distance traveled for each mode on x-axis and number of trips on y-axis} \usage{ plot_distance_by_mainmode_barchart( trips_table, @@ -12,18 +12,19 @@ plot_distance_by_mainmode_barchart( ) } \arguments{ -\item{trips_table}{tible of trips_output (from readTripsTable())} +\item{trips_table}{tibble of trips_output (from readTripsTable())} -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{united.name}{character string, specifies the name of the united mode} -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart#'} +\item{unite.modes}{vector of character strings, +changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +using the function (\link{process_rename_mainmodes})} } \value{ Bar Chart plot of distance traveled per mode } \description{ -Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -average distance traveled ~ main mode used -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Takes the data frame trips_output (from \link{readTripsTable()}), +to plot a bar chart of the average distance traveled for each main mode, +Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_distcat_by_mainmode_barchart.Rd b/man/plot_distcat_by_mainmode_barchart.Rd index 2d1a03e..bcc8d0c 100644 --- a/man/plot_distcat_by_mainmode_barchart.Rd +++ b/man/plot_distcat_by_mainmode_barchart.Rd @@ -2,29 +2,30 @@ % Please edit documentation in R/output_trips.R \name{plot_distcat_by_mainmode_barchart} \alias{plot_distcat_by_mainmode_barchart} -\title{Bar Chart with distance travelled on x-axis and number of trips on y-axis} +\title{Bar Chart with distance traveled on x-axis and number of trips on y-axis} \usage{ plot_distcat_by_mainmode_barchart( trips_table, - unite.columns = character(0), + unite.modes = character(0), united.name = "united", dist_column = "dist_cat", distances_array = c(1000, 2000, 5000, 10000, 20000, 50000, 1e+05) ) } \arguments{ -\item{trips_table}{tible of trips_output (from readTripsTable())} +\item{trips_table}{tibble of trips_output (from readTripsTable())} -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{unite.modes}{vector of character strings, +changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +using the function (\link{process_rename_mainmodes})} -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +\item{united.name}{character string, specifies the name of the united mode} } \value{ Bar Chart plot of count of trips among distance travelled } \description{ -Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -number of trips ~ distance travelled -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Takes the data frame trips_output (from \link{readTripsTable()}) and categorizes the traveled distances into pre-defined bins +to plot a histogram of the traveled distances. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) +Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_mainmode_barchart.Rd b/man/plot_mainmode_barchart.Rd index 9a5a223..189f356 100644 --- a/man/plot_mainmode_barchart.Rd +++ b/man/plot_mainmode_barchart.Rd @@ -2,33 +2,34 @@ % Please edit documentation in R/output_trips.R \name{plot_mainmode_barchart} \alias{plot_mainmode_barchart} -\title{Plot main_mode distribution as a bar Chart} +\title{Plot the distribution of modes as a bar chart} \usage{ plot_mainmode_barchart( trips_table, - unite.columns = character(0), + unite.modes = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory, percentage = FALSE ) } \arguments{ -\item{trips_table}{tible of trips_output (from readTripsTable())} +\item{trips_table}{tibble of trips_output (from \link{readTripsTable()})} -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{unite.modes}{vector of character strings, +changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +using the function (\link{process_rename_mainmodes})} -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +\item{united.name}{character string, specifies the name of the united mode} } \value{ Bar Chart plot of transport mode distribution, values given in percents } \description{ -Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -percentage of using transport modes from trips +Takes the data frame trips_output (from \link{readTripsTable()}) +to plot a bar chart of the modal split using the column main_mode. } \details{ -Function automatically detects transport_modes from table -and plots pie chart with percentage of distribution. -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +The modal shares are given in percentages. + +Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_mainmode_piechart.Rd b/man/plot_mainmode_piechart.Rd index 82c8a67..9ec835d 100644 --- a/man/plot_mainmode_piechart.Rd +++ b/man/plot_mainmode_piechart.Rd @@ -2,11 +2,11 @@ % Please edit documentation in R/output_trips.R \name{plot_mainmode_piechart} \alias{plot_mainmode_piechart} -\title{Plot main_mode distribution as a Pie Chart} +\title{Plot the distribution of modes as a pie chart} \usage{ plot_mainmode_piechart( trips_table, - unite.columns = character(0), + unite.modes = character(0), united.name = "united", dump.output.to = matsimDumpOutputDirectory ) @@ -14,20 +14,20 @@ plot_mainmode_piechart( \arguments{ \item{trips_table}{tibble of trips_output (from \link{readTripsTable})} -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{unite.modes}{vector of character strings, +changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +using the function (\link{process_rename_mainmodes})} -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +\item{united.name}{character string, specifies the name of the united mode} } \value{ -Pie Chart plot of transport mode distribution, values given in percents +pie chart plot of transport mode distribution, values given in percent } \description{ -Takes Table trips_output (from \link{readTripsTable}), -to plot pie chart with with values that represent -percentage of using transport modes from trips +Uses the dataframe trips_output (from \link{readTripsTable}), +to plot a pie chart of the modal split using the column main_mode } \details{ -Function automatically detects transport_modes from table -and plots pie chart. -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +The function automatically detects the modes plots a pie chart. +Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_travelwaittime_mean_barchart.Rd b/man/plot_travelwaittime_mean_barchart.Rd index 175b743..310f71c 100644 --- a/man/plot_travelwaittime_mean_barchart.Rd +++ b/man/plot_travelwaittime_mean_barchart.Rd @@ -2,28 +2,29 @@ % Please edit documentation in R/output_trips.R \name{plot_travelwaittime_mean_barchart} \alias{plot_travelwaittime_mean_barchart} -\title{Bar Chart with main_mode on x-axis and average travel/wait time on y-axis} +\title{Plot travel and wait time for each mode as a bar chart} \usage{ plot_travelwaittime_mean_barchart( trips_table, - unite.columns = character(0), + unite.modes = character(0), united.name = "united", time_format = "minute" ) } \arguments{ -\item{trips_table}{tible of trips_output (from readTripsTable())} +\item{trips_table}{tibble of trips_output (from \links{readTripsTable()})} -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{unite.modes}{vector of character strings, +changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +using the function (\link{process_rename_mainmodes})} -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +\item{united.name}{character string, specifies the name of the united mode} } \value{ Bar Chart plot of average time spent on travel/wait } \description{ -Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -time spent on traveling/waiting -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Takes the data frame trips_output (from \links{readTripsTable()}), +to plot a bar chart of travel and wait times. +Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd b/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd index 6622b1b..8d2e12b 100644 --- a/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd +++ b/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/output_trips.R \name{plot_trips_count_by_deptime_and_mainmode_linechart} \alias{plot_trips_count_by_deptime_and_mainmode_linechart} -\title{Line plot with departure time x-axis and number of trips on y-axis} +\title{Line plot with departure time on x-axis and number of trips on y-axis} \usage{ plot_trips_count_by_deptime_and_mainmode_linechart( trips_table, @@ -11,18 +11,19 @@ plot_trips_count_by_deptime_and_mainmode_linechart( ) } \arguments{ -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{united.name}{character string, specifies the name of the united mode} -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +\item{tripsTable}{tibble of trips_output (from readTripsTable())} -\item{tripsTable}{tible of trips_output (from readTripsTable())} +\item{unite.modes}{vector of character strings, +changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +using the function (\link{process_rename_mainmodes})} } \value{ -Line Chart plot of trips count by departure mode per mode +Line plot of trips count by departure time per mode } \description{ -Takes Table trips_output (from readTripsTable()), -to make line plot with with values that represent -count of trips for a specific departure time by main_mode -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Takes data frame trips_output (from \link{readTripsTable()}), +to create a line plot of the number of trips for a specific departure time by main_mode +Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/prepareComparisonSimwrapperDashboardFromTable.Rd b/man/prepareComparisonSimwrapperDashboardFromTable.Rd index 49ebfdf..01a51a1 100644 --- a/man/prepareComparisonSimwrapperDashboardFromTable.Rd +++ b/man/prepareComparisonSimwrapperDashboardFromTable.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/simwrapper.R \name{prepareComparisonSimwrapperDashboardFromTable} \alias{prepareComparisonSimwrapperDashboardFromTable} -\title{Creates comparison dashboard for the 2 given tables or folder with data} +\title{Creates comparison dashboard for the two given tables or folders with data} \usage{ prepareComparisonSimwrapperDashboardFromTable( table1, @@ -16,14 +16,14 @@ prepareComparisonSimwrapperDashboardFromTable( \item{table2}{trips_output tibble from readTripsTable()} -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard and all plots using functions: +\item{dump.output.to}{output folder, yaml files and plots from the following functions are saved there: plotModalSplitBarChart(),plotModalSplitPieChart(),plotModalShift().} -\item{append}{specifies if the ouput folder should be erased before creating} +\item{append}{specifies if the output folder should be erased before creating, default = FALSE} } \value{ -generates folder with content for simwrapper out of trips table +generates folder with content for simwrapper from a trips table } \description{ -Creates comparison dashboard for the 2 given tables or folder with data +Creates comparison dashboard for the two given tables or folders with data } diff --git a/man/prepareSimwrapperDashboardFromFolder.Rd b/man/prepareSimwrapperDashboardFromFolder.Rd index 975129c..ff41bee 100644 --- a/man/prepareSimwrapperDashboardFromFolder.Rd +++ b/man/prepareSimwrapperDashboardFromFolder.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/simwrapper.R \name{prepareSimwrapperDashboardFromFolder} \alias{prepareSimwrapperDashboardFromFolder} -\title{Creates dashboard for the given table or folder with data} +\title{Creates dashboard for the given folder with data} \usage{ prepareSimwrapperDashboardFromFolder( folder, @@ -11,15 +11,15 @@ prepareSimwrapperDashboardFromFolder( ) } \arguments{ -\item{folder}{specifies data source folder with tripsOutput} +\item{folder}{file path, specifies data source folder that includes a output_trips.csv file} -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard and all plots} +\item{dump.output.to}{output folder, yaml files are saved there} -\item{append}{specifies if the ouput folder should be erased before creating} +\item{append}{specifies if the ouput folder should be erased before creating, default = FALSE} } \value{ -tibble of output_trips from folder. Generates content needed for Simwrapper +tibble of output_trips from folder and content needed for Simwrapper } \description{ -Creates dashboard for the given table or folder with data +Creates dashboard for the given folder with data } diff --git a/man/prepareSimwrapperDashboardFromTable.Rd b/man/prepareSimwrapperDashboardFromTable.Rd index 3389d54..221603c 100644 --- a/man/prepareSimwrapperDashboardFromTable.Rd +++ b/man/prepareSimwrapperDashboardFromTable.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/simwrapper.R \name{prepareSimwrapperDashboardFromTable} \alias{prepareSimwrapperDashboardFromTable} -\title{Creates dashboard for the given table or folder with data} +\title{Creates dashboard for the given table with data} \usage{ prepareSimwrapperDashboardFromTable( table, @@ -13,14 +13,14 @@ prepareSimwrapperDashboardFromTable( \arguments{ \item{table}{trips_output tibble from readTripsTable()} -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard and all plots using functions: +\item{dump.output.to}{output folder, yaml files and plots from the following functions are saved there: plotModalSplitBarChart(),plotModalSplitPieChart(),plotModalShift().} -\item{append}{specifies if the ouput folder should be erased before creating} +\item{append}{specifies if the ouput folder should be erased before creating, default = FALSE} } \value{ generates folder with content for simwrapper out of trips table } \description{ -Creates dashboard for the given table or folder with data +Creates dashboard for the given table with data } diff --git a/man/processDtvEstimationQuality.Rd b/man/processDtvEstimationQuality.Rd index 907796e..abae3ea 100644 --- a/man/processDtvEstimationQuality.Rd +++ b/man/processDtvEstimationQuality.Rd @@ -14,7 +14,7 @@ processDtvEstimationQuality( \arguments{ \item{joinedFrame}{A tibble from mergeCountsAndLinks} -\item{aggr}{Boolean, if categorized data should returned aggregated} +\item{aggr}{Boolean, if categorized data should returned aggregated, default is TRUE.} \item{ll}{Formula to calculate lower limit of the quality label 'exact', default = 0.8*x - 200} @@ -25,13 +25,12 @@ A long-format tibble, which contains share of estimation quality for each scenar } \description{ Takes a tibble from mergeCountsAndLinks. -Deviation between count volumes and Linkstats is calculated -(e.g. deviation of 1.2 means 20 percent more DTV in MATSim than in counts) and -categorized. +Deviation between count volumes and Linkstats is calculated and +categorized (i.e. deviation of 1.2 means 20 percent more DTV in MATSim than in counts). If parameter 'aggr' is set to TRUE, data will be aggregated for each run and link type. Can be used to visualize model quality by link type and to compare several runs. } \details{ -Estimation quality is determinated by the 'cut' function, limits for the label -'exact' can be adjusted by tuning the parameter 'll' and 'ul' +Estimation quality is determined by the 'cut' function, limits for the label +'exact' can be adjusted by tuning the parameters 'll' (lower limit) and 'ul' (upper limit) } diff --git a/man/processLinkStatsDtvDistribution.Rd b/man/processLinkStatsDtvDistribution.Rd index c4afcc3..9763c07 100644 --- a/man/processLinkStatsDtvDistribution.Rd +++ b/man/processLinkStatsDtvDistribution.Rd @@ -2,21 +2,21 @@ % Please edit documentation in R/counts.R \name{processLinkStatsDtvDistribution} \alias{processLinkStatsDtvDistribution} -\title{Categorize DTV and calculate DTV distribution} +\title{Categorize daily traffic volume (DTV) and calculate DTV for different link types.} \usage{ processLinkStatsDtvDistribution(joinedFrame, from = 0, to = 40000, by = 5000) } \arguments{ \item{joinedFrame}{A tibble from mergeCountsAndLinks} -\item{from}{Lower limit for count bin} +\item{from}{Integer. Lower limit for count bin, default = 0.} -\item{to}{Upper limit for count bins} +\item{to}{Integer. Upper limit for count bins, default = 40000.} -\item{by}{Size of each count bin} +\item{by}{Integer. Size of each count bin, default = 5000.} } \value{ -A long-format tibble which contains share of DTV Categories +A long-format tibble which contains share of DTV for link types } \description{ Takes a tibble from mergeCountsAndLinks. DTV is categorized into bins. Finally diff --git a/man/process_filter_by_shape.Rd b/man/process_filter_by_shape.Rd index 9f3a93f..01ac561 100644 --- a/man/process_filter_by_shape.Rd +++ b/man/process_filter_by_shape.Rd @@ -2,7 +2,9 @@ % Please edit documentation in R/output_trips.R \name{process_filter_by_shape} \alias{process_filter_by_shape} -\title{Filtering of trips_table(from readTripsTable) depending on how they located in given shape} +\title{XXXX trips_table but shapeTable - fix naming +XXXX finish when code revision is done +Filters trips_table(from ,\link{readTripsTable}) depending by location using a shapefile} \usage{ process_filter_by_shape( trips_table, @@ -15,7 +17,7 @@ process_filter_by_shape( \arguments{ \item{trips_table}{tibble of trips_output (from readTripsTable())} -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} +\item{crs}{numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file} \item{start.inshape}{bool, defines trips to conclude (see Description)} @@ -27,10 +29,9 @@ process_filter_by_shape( tibble, with filtered trips depending on shapeTable and special flags (see Description) } \description{ -Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -Please be aware that this filterByRegion currently only works, when one geometry is loaded.) -transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -and filters the trips from table depending on *.inshape flags: +Uses trips_table and an sf object (can be created using the function st_read()), +transforms both objects to match a mutual coordinate system (crs) +and filters the trips from trips_table depending on *.inshape flags: if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape diff --git a/man/process_get_crs_from_config.Rd b/man/process_get_crs_from_config.Rd index 10cdb61..8ea3032 100644 --- a/man/process_get_crs_from_config.Rd +++ b/man/process_get_crs_from_config.Rd @@ -2,18 +2,18 @@ % Please edit documentation in R/output_trips.R \name{process_get_crs_from_config} \alias{process_get_crs_from_config} -\title{Reads an coordinate referenec system of MATSim output directory -from output_config.xml} +\title{Reads the coordinate reference system from an MATSim output directory +(output_config.xml)} \usage{ process_get_crs_from_config(config_path) } \arguments{ -\item{config_path}{specifies path to find config} +\item{config_path}{specifies path to configuration file} } \value{ code of coordinate reference system } \description{ -Reads an coordinate referenec system of MATSim output directory -from output_config.xml +Reads the coordinate reference system from an MATSim output directory +(output_config.xml) } diff --git a/man/process_get_od_matrix.Rd b/man/process_get_od_matrix.Rd index 988818a..a3ecf55 100644 --- a/man/process_get_od_matrix.Rd +++ b/man/process_get_od_matrix.Rd @@ -2,7 +2,8 @@ % Please edit documentation in R/output_trips.R \name{process_get_od_matrix} \alias{process_get_od_matrix} -\title{Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper} +\title{Creates an origin/destination matrix either in conventional form (row names = origin, column names = destination) +or for simwrapper (origin and destination as columns)} \usage{ process_get_od_matrix( tripsTable, @@ -15,23 +16,24 @@ process_get_od_matrix( ) } \arguments{ -\item{tripsTable}{table of output trips(from readTripsTable) or path to trips_output file} +\item{tripsTable}{tibble of trips_output (from \link{readTripsTable})} -\item{shapePath}{full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name)} +\item{shapePath}{string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file)} -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} +\item{crs}{numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file} -\item{dump.output.to}{path to a folder to save csv file of ODMatrix} +\item{dump.output.to}{string, path to a folder to save the .csv file} -\item{simwrapper}{create output in a simwrapper form if set to path of the shapefile} +\item{simwrapper}{boolean, creates output in the format used for simwrapper if the path for the shapefile is specified} -\item{colnames}{if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values} +\item{colnames}{string, column names can be specified (i.e. to fit the shape file), if not they are numbered} -\item{outer}{logical that represent if the table should contain outside flow of the shape, it isn't} +\item{outer}{boolean, determines if flows outside of the shapefile are used, standard value is FALSE} } \value{ tibble of origin/destination matrix } \description{ -Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper +Creates an origin/destination matrix either in conventional form (row names = origin, column names = destination) +or for simwrapper (origin and destination as columns) } diff --git a/man/readCounts.Rd b/man/readCounts.Rd index bcf3ae4..7ae29cc 100644 --- a/man/readCounts.Rd +++ b/man/readCounts.Rd @@ -10,8 +10,8 @@ readCounts(file) \item{file}{File to load. Must be an .xml file} } \value{ -tibble containing with MATSim Link id as "loc_id" as key +tibble with MATSim link id ("loc_id") as key } \description{ -Loads a MATSim Counts XML-File as tibble into memory +Loads a MATSim Counts XML-file as tibble into memory } diff --git a/man/readLinkStats.Rd b/man/readLinkStats.Rd index 30d169a..1d2ad08 100644 --- a/man/readLinkStats.Rd +++ b/man/readLinkStats.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/counts.R \name{readLinkStats} \alias{readLinkStats} -\title{Load linkstats as tibble into memory} +\title{Load a MATSim linkstats file into memory} \usage{ readLinkStats(runId, file, sampleSize = 0.25) } @@ -17,9 +17,9 @@ readLinkStats(runId, file, sampleSize = 0.25) Tibble with link stats for each qsim mode } \description{ -Reads Linkstats as .tsv created from LinkStats.class -as dataframe into memory. -Counts can be provided in any time bins. +Loads a linkstats tsv file created from the LinkStats class +as a dataframe into memory. +Counts can be provided in any time bin. Counts can be provided for any qsim mode. The argument networkModes is used to select and filter the columns. } diff --git a/man/readTripsTable.Rd b/man/readTripsTable.Rd index 176d197..e085f5a 100644 --- a/man/readTripsTable.Rd +++ b/man/readTripsTable.Rd @@ -7,7 +7,7 @@ readTripsTable(input_path = ".", n_max = Inf) } \arguments{ -\item{input_path}{character string, path to matsim output directory or http link to the file.} +\item{input_path}{character string, path to MATSim output directory or http link to the file.} \item{n_max}{integer, maximum number of lines to read within output_trips} } @@ -15,6 +15,6 @@ readTripsTable(input_path = ".", n_max = Inf) tibble of trips_output } \description{ -Loads a MATSim CSV output_trips from file or archive, -creating a tibble with columns as in csv file +Loads a MATSim output_trips file from file or archive path, +creating a tibble } diff --git a/man/read_network.Rd b/man/read_network.Rd index 2602e44..90bddc2 100644 --- a/man/read_network.Rd +++ b/man/read_network.Rd @@ -19,6 +19,6 @@ additional columns in the respective node and link tibbles. } \details{ The links table is automatically joined with the nodes table so that -node x/y coordinates (and any other node attributes) are available on the +node x/y coordinates (and any other node attributes) are available in the links table without additional processing. } diff --git a/man/read_output_trips.Rd b/man/read_output_trips.Rd index ba00957..b7cd76c 100644 --- a/man/read_output_trips.Rd +++ b/man/read_output_trips.Rd @@ -2,14 +2,14 @@ % Please edit documentation in R/output_trips.R \name{read_output_trips} \alias{read_output_trips} -\title{Load MATSIM output_trips table into Memory} +\title{Load MATSIM output_trips table into memory} \usage{ read_output_trips(input_path = ".", n_max = Inf) } \arguments{ -\item{input_path}{character string, path to matsim output directory or http link to the file.} +\item{input_path}{character string, path to the MATSim output directory or http link to the file.} -\item{n_max}{integer, maximum number of lines to read within output_trips} +\item{n_max}{optional, integer, maximum number of lines to read, standard value is Inf} } \value{ tibble of trips_output diff --git a/man/transformToSf.Rd b/man/transformToSf.Rd index 3a4f6c6..1abd90e 100644 --- a/man/transformToSf.Rd +++ b/man/transformToSf.Rd @@ -2,32 +2,27 @@ % Please edit documentation in R/output_trips.R \name{transformToSf} \alias{transformToSf} -\title{Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature)} +\title{Transforms the data frame trips_output (from \links{readTripsTable}) from tibble to sf (table with geometry features)} \usage{ transformToSf(table, crs, geometry.type = st_multipoint()) } \arguments{ -\item{table}{tibble of trips_output (from readTripsTable())} +\item{table}{tibble trips_output (from readTripsTable())} -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} +\item{crs}{numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file} -\item{geometry.type}{function of sf transformation, geometry.type can be (by default is st_multipoint()) -!!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or -!!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or -!!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!!} +\item{geometry.type}{type of sf transformation, default is st_multipoint(), geometry.type can be: +!!!st_point()- resulting table contains two geometry columns: start_wkt and end_wkt, representing start and end points as POINTS!!! or +!!!st_multipoint()- resulting table contains one geometry column, representing start and end points as MULTIPOINT!!! or +!!!st_linestring() - resulting table contains one geometry column, representing the line between start and end points as LINESTRING!!!} } \value{ -sf object (data.frame with geometries depending to geometry.type) +sf object (data frame with geometries depending on geometry.type) } \description{ -Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features -deletes from resulting data.frame start_x, end_x, start_y, end_y. -And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring() -Or adds start_wkt and end_wkt, if geometry.type = st_point() -Added column/columns projected to given CRS (coordinate reference system), -that can be taken from network file of MATSimOutputDirectory -} -\details{ -Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" -to get which type of table was generated, if it is needed +Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features. +If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format), +if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt. +Added column/columns are projected to given CRS (coordinate reference system). +The columns start_x, end_x, start_y, end_y are deleted from the resulting data frame. } From 023817355668b8cd89704bb0ab51d4ad5f5b2581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Thu, 29 Jun 2023 14:26:42 +0200 Subject: [PATCH 44/87] added missing curly brace --- R/output_trips.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/output_trips.R b/R/output_trips.R index 41a9faa..1bcc9f0 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2554,7 +2554,7 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, tripsTable = tripsTable %>% mutate(dep_time = hour(dep_time)) %>% count(dep_time,main_mode) - +} #' Plot bar chart of changes in modal split From afe45c557796a1fbb745a9c47863f6b460b91fd4 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 29 Jun 2023 14:31:09 +0200 Subject: [PATCH 45/87] deleted indentation --- R/output_trips.R | 962 +++++++++++++++++++++++------------------------ 1 file changed, 481 insertions(+), 481 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 26ad106..ebb714b 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2564,604 +2564,604 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, } - #' Plot bar chart of changes in modal split - #' - #' Takes two data frames (from \link{readTripsTable()}), calculates the - #' changes in mode shares and plots them as a bar chart - #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') - #' - #' - #' - #' @param tripsTable1 tibble of trips_output (from readTripsTable()) - #' @param tripsTable2 tibble of trips_output (from readTripsTable()) - #'@param unite.modes vector of character strings, - #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), - #' using the function (\link{process_rename_mainmodes}) - #' @param united.name character string, specifies the name of the united mode - #' - #' @return plots bar chart of changes in modal split - #' - #' @export - plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, - unite.modes = character(0), - united.name = "united") { - # renaming/uniting of modes - trips_table1 <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, - united.name = united.name) - - trips_table2 <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, - united.name = united.name) - - trips_table1 = trips_table1 %>% mutate(type = "base") - trips_table2 = trips_table2 %>% mutate(type = "policy") - - total_trips = rbind(trips_table1,trips_table2) - - plt = ggplot(total_trips, aes(x =main_mode,fill = factor(type)))+ - geom_bar(position = position_dodge())+ - coord_flip() - plotly::ggplotly(plt) - - return(plotly::ggplotly(plt)) - } - - #' Plot alluvial/sankey diagram of transport mode changes - #' - #' Takes two data frames (from \link{readTripsTable()}) and compares the mode choice for each agent and summarizes the results, showing the modal shift. - #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') - #' The parameter show.onlyChanges allows the visualization of only the mode shift (excluding the trips that do not change mode). Standard value is FALSE. - #' - #' @param tripsTable1 tibble of trips_output (from readTripsTable()) - #' @param tripsTable2 tibble of trips_output (from readTripsTable()) - #' @param show.onlyChanges boolean, if it is set to TRUE the sankey diagram only shows the mode shift - #' @param unite.modes vector of character strings, - #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), - #' using the function (\link{process_rename_mainmodes}) - #' @param united.name character string, specifies the name of the united mode - #' - #' @return Alluvial diagram that represents changes in transport mode distribution - #' - #' @export - plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, - show.onlyChanges = FALSE, +#' Plot bar chart of changes in modal split +#' +#' Takes two data frames (from \link{readTripsTable()}), calculates the +#' changes in mode shares and plots them as a bar chart +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' +#' +#' +#' @param tripsTable1 tibble of trips_output (from readTripsTable()) +#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#'@param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode +#' +#' @return plots bar chart of changes in modal split +#' +#' @export +plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, unite.modes = character(0), united.name = "united") { + # renaming/uniting of modes + trips_table1 <- process_rename_mainmodes(trips_table = trips_table, + unite.modes = unite.modes, + united.name = united.name) - # renaming/uniting of modes - trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.modes = unite.modes, - united.name = united.name) - - trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.modes = unite.modes, - united.name = united.name) - #processing - joined <- as_tibble(inner_join(trips_table1, trips_table2 %>% - select(trip_id, main_mode), by = "trip_id") %>% - dplyr::rename(base_mode = main_mode.x, policy_mode = main_mode.y)) - - #if onlychanges, then we should exclude base_mode=policy_mode - if (show.onlyChanges == TRUE) { - joined <- joined %>% - filter(base_mode != policy_mode) - } + trips_table2 <- process_rename_mainmodes(trips_table = trips_table, + unite.modes = unite.modes, + united.name = united.name) + + trips_table1 = trips_table1 %>% mutate(type = "base") + trips_table2 = trips_table2 %>% mutate(type = "policy") + + total_trips = rbind(trips_table1,trips_table2) + + plt = ggplot(total_trips, aes(x =main_mode,fill = factor(type)))+ + geom_bar(position = position_dodge())+ + coord_flip() + plotly::ggplotly(plt) + + return(plotly::ggplotly(plt)) +} + +#' Plot alluvial/sankey diagram of transport mode changes +#' +#' Takes two data frames (from \link{readTripsTable()}) and compares the mode choice for each agent and summarizes the results, showing the modal shift. +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' The parameter show.onlyChanges allows the visualization of only the mode shift (excluding the trips that do not change mode). Standard value is FALSE. +#' +#' @param tripsTable1 tibble of trips_output (from readTripsTable()) +#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#' @param show.onlyChanges boolean, if it is set to TRUE the sankey diagram only shows the mode shift +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode +#' +#' @return Alluvial diagram that represents changes in transport mode distribution +#' +#' @export +plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, + show.onlyChanges = FALSE, + unite.modes = character(0), + united.name = "united") { + # renaming/uniting of modes + trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, + unite.modes = unite.modes, + united.name = united.name) + + trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, + unite.modes = unite.modes, + united.name = united.name) + #processing + joined <- as_tibble(inner_join(trips_table1, trips_table2 %>% + select(trip_id, main_mode), by = "trip_id") %>% + dplyr::rename(base_mode = main_mode.x, policy_mode = main_mode.y)) + + #if onlychanges, then we should exclude base_mode=policy_mode + if (show.onlyChanges == TRUE) { joined <- joined %>% - group_by(base_mode, policy_mode) %>% - count() + filter(base_mode != policy_mode) + } - modes = unique(c(joined$base_mode,joined$policy_mode)) + joined <- joined %>% + group_by(base_mode, policy_mode) %>% + count() - joined$base_mode <- as.numeric(factor(joined$base_mode,levels = modes)) - joined$policy_mode <- as.numeric(factor(joined$policy_mode,levels = modes)) + modes = unique(c(joined$base_mode,joined$policy_mode)) + joined$base_mode <- as.numeric(factor(joined$base_mode,levels = modes)) + joined$policy_mode <- as.numeric(factor(joined$policy_mode,levels = modes)) - #plotting - palette <- colorRampPalette( c( "blue", "red" ) )( 7 ) + #plotting + palette <- colorRampPalette( c( "blue", "red" ) )( 7 ) - fig <- plot_ly( - type = "sankey", - orientation = "h", - node = list( - label = c(modes,modes), - color = c(palette,palette), - pad = 15, - thickness = 20, - line = list( - color = "black", - width = 0.5 - ) - ), + fig <- plot_ly( + type = "sankey", + orientation = "h", - link = list( - source = joined$base_mode-1, - target = joined$policy_mode+6, - value = joined$n + node = list( + label = c(modes,modes), + color = c(palette,palette), + pad = 15, + thickness = 20, + line = list( + color = "black", + width = 0.5 ) + ), + + link = list( + source = joined$base_mode-1, + target = joined$policy_mode+6, + value = joined$n ) - fig <- fig %>% layout( - title = "Basic Sankey Diagram", - font = list( - size = 10 - ) + ) + fig <- fig %>% layout( + title = "Basic Sankey Diagram", + font = list( + size = 10 ) + ) - fig - return(fig) - } + fig + return(fig) +} - #' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis - #' - #' Takes the data frame trips_output (from \link{readTripsTable()}), - #' to plot a bar chart of the traveling/waiting time - #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') - #' - #' - #' @param tripsTable1 tibble of trips_output (from readTripsTable()) - #' @param tripsTable2 tibble of trips_output (from readTripsTable()) - #' @param unite.modes vector of character strings, - #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), - #' using the function (\link{process_rename_mainmodes}) - #' @param united.name character string, specifies the name of the united mode - #' - #' @return Bar Chart plot of average time spent on travel/wait - #' - #' @export - plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_table2, - unite.modes = character(0), - united.name = "united", - time_format = "minute") { +#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis +#' +#' Takes the data frame trips_output (from \link{readTripsTable()}), +#' to plot a bar chart of the traveling/waiting time +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' +#' +#' @param tripsTable1 tibble of trips_output (from readTripsTable()) +#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode +#' +#' @return Bar Chart plot of average time spent on travel/wait +#' +#' @export +plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_table2, + unite.modes = character(0), + united.name = "united", + time_format = "minute") { - #TODO: - # . Document and add title to show what means positive/negative value - # . think about comparing processing functions they can appear in future often + #TODO: + # . Document and add title to show what means positive/negative value + # . think about comparing processing functions they can appear in future often - # If some columns should be united - trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.modes = unite.modes, - united.name = united.name) + # If some columns should be united + trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, + unite.modes = unite.modes, + united.name = united.name) - trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.modes = unite.modes, - united.name = united.name) + trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, + unite.modes = unite.modes, + united.name = united.name) - #processing - avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) + #processing + avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) - avg_time2 = process_get_travelwaittime_by_mainmode(trips_table2,time_format = time_format) + avg_time2 = process_get_travelwaittime_by_mainmode(trips_table2,time_format = time_format) - avg_time = full_join(avg_time1, avg_time2, by = "main_mode") %>% - replace_na(list(trav_time_avg.x = 0,wait_time_avg.x = 0,trav_time_avg.y = 0,wait_time_avg.y = 0)) + avg_time = full_join(avg_time1, avg_time2, by = "main_mode") %>% + replace_na(list(trav_time_avg.x = 0,wait_time_avg.x = 0,trav_time_avg.y = 0,wait_time_avg.y = 0)) - avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg.x - trav_time_avg.y, - wait_time_avg =wait_time_avg.x - wait_time_avg.y )%>% - select(-wait_time_avg.x,-wait_time_avg.y, -trav_time_avg.x,-trav_time_avg.y) + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg.x - trav_time_avg.y, + wait_time_avg =wait_time_avg.x - wait_time_avg.y )%>% + select(-wait_time_avg.x,-wait_time_avg.y, -trav_time_avg.x,-trav_time_avg.y) - #plotting - fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") - fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") - fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)")),barmode = "group") + #plotting + fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") + fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") + fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)")),barmode = "group") - fig - return(fig) + fig + return(fig) - } +} - ###### Mapping ###### +###### Mapping ###### - #####Processing##### +#####Processing##### - process_rename_mainmodes<-function(trips_table, - unite.modes = character(0), united.name = "united"){ +process_rename_mainmodes<-function(trips_table, + unite.modes = character(0), united.name = "united"){ - if (length(unite.modes) != 0) { - trips_table$main_mode[grep(paste0(unite.modes, collapse = "|") - , trips_table$main_mode)] <- united.name - } - return(trips_table) + if (length(unite.modes) != 0) { + trips_table$main_mode[grep(paste0(unite.modes, collapse = "|") + , trips_table$main_mode)] <- united.name } + return(trips_table) +} - process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ - - trips_table_count <- trips_table %>% - count(main_mode) - if(percentage){ - trips_table_count<- trips_table_count %>% mutate(n = n / sum(n) * 100) - } +process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ - return(trips_table_count) + trips_table_count <- trips_table %>% + count(main_mode) + if(percentage){ + trips_table_count<- trips_table_count %>% mutate(n = n / sum(n) * 100) } - process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ + return(trips_table_count) +} - trips_table = trips_table %>% - group_by(main_mode) %>% - summarize(avg_dist = if_else(euclidian,mean(euclidean_distance),mean(traveled_distance))) +process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ - return(trips_table) - } + trips_table = trips_table %>% + group_by(main_mode) %>% + summarize(avg_dist = if_else(euclidian,mean(euclidean_distance),mean(traveled_distance))) - process_get_travelwaittime_by_mainmode_barchart<-function(trips_table, - time_format = "minute"){#also could be hours/seconds + return(trips_table) +} - #get 2 columns with mean travel time and mean wait time grouped by main_mode in seconds - avg_time = trips_table %>% group_by(main_mode)%>% - summarize(trav_time_avg = hms::hms(seconds_to_period(mean(trav_time))), - wait_time_avg = hms::hms(seconds_to_period(mean(wait_time)))) %>% - mutate(trav_time_avg = as.numeric(trav_time_avg),wait_time_avg = as.numeric(wait_time_avg)) +process_get_travelwaittime_by_mainmode_barchart<-function(trips_table, + time_format = "minute"){#also could be hours/seconds - if(time_format == "minute"){ - #convert seconds to minutes - avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/60, wait_time_avg = wait_time_avg/60) - return(avg_time) - }else if(time_format == "hour"){ - avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/3600, wait_time_avg = wait_time_avg/3600) - return(avg_time) - } + #get 2 columns with mean travel time and mean wait time grouped by main_mode in seconds + avg_time = trips_table %>% group_by(main_mode)%>% + summarize(trav_time_avg = hms::hms(seconds_to_period(mean(trav_time))), + wait_time_avg = hms::hms(seconds_to_period(mean(wait_time)))) %>% + mutate(trav_time_avg = as.numeric(trav_time_avg),wait_time_avg = as.numeric(wait_time_avg)) + if(time_format == "minute"){ + #convert seconds to minutes + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/60, wait_time_avg = wait_time_avg/60) + return(avg_time) + }else if(time_format == "hour"){ + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg/3600, wait_time_avg = wait_time_avg/3600) return(avg_time) } + return(avg_time) +} - process_append_distcat <- function(trips_table,distances_array = c(1000,2000,5000,10000,20000,50000,100000)){ - distances_array = sort(c(distances_array,c(0,Inf))) - modes = levels(factor(trips_table$main_mode)) +process_append_distcat <- function(trips_table,distances_array = c(1000,2000,5000,10000,20000,50000,100000)){ - #Also filtering table into a new doesn't creates new objects in memory, so it works fast - #Upd: it creates copy of dataframe on each mutate :/ + distances_array = sort(c(distances_array,c(0,Inf))) + modes = levels(factor(trips_table$main_mode)) - result_table <- c(NULL) + #Also filtering table into a new doesn't creates new objects in memory, so it works fast + #Upd: it creates copy of dataframe on each mutate :/ - str_factors<-c(NULL) - for(i in 1:(length(distances_array)-1)){ - part_table <- trips_table %>% - filter(traveled_distance>=distances_array[i] & traveled_distance% - mutate(dist_cat = paste0(distances_array[i],"-",distances_array[i+1])) - str_factors<- c(str_factors,paste0(distances_array[i],"-",distances_array[i+1])) - result_table <- rbind(result_table,part_table) - } + result_table <- c(NULL) - result_table$dist_cat = factor(result_table$dist_cat,levels = str_factors) - return(result_table) + str_factors<-c(NULL) + for(i in 1:(length(distances_array)-1)){ + part_table <- trips_table %>% + filter(traveled_distance>=distances_array[i] & traveled_distance% + mutate(dist_cat = paste0(distances_array[i],"-",distances_array[i+1])) + str_factors<- c(str_factors,paste0(distances_array[i],"-",distances_array[i+1])) + result_table <- rbind(result_table,part_table) } - ######Spatial###### - #' XXXX trips_table but shapeTable - fix naming - #' XXXX finish when code revision is done - #' Filters trips_table(from ,\link{readTripsTable}) depending by location using a shapefile - #' - #' Uses trips_table and an sf object (can be created using the function st_read()), - #' transforms both objects to match a mutual coordinate system (crs) - #' and filters the trips from trips_table depending on *.inshape flags: - #' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape - #' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape - #' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape - #' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape - #' - #' @param trips_table tibble of trips_output (from readTripsTable()) - #' - #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) - #' - #' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file - #' - #' @param start.inshape bool, defines trips to conclude (see Description) - #' - #' @param end.inshape bool, defines trips to conclude (see Description) - #' - #' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) - #' - #' @export - process_filter_by_shape <- function(trips_table, - shape_table, - crs, - start.inshape = TRUE, end.inshape = TRUE) { - - # shape_table <- st_read(shapeFile) - if (st_crs(shape_table) == NA) { - st_crs(shape_table) <- crs - } + result_table$dist_cat = factor(result_table$dist_cat,levels = str_factors) + return(result_table) +} - sf_table <- transformToSf(trips_table, crs = crs, geometry.type = st_point()) - shape_table <- st_transform(shape_table, crs = crs) - # shape_table isn't table - shape +######Spatial###### +#' XXXX trips_table but shapeTable - fix naming +#' XXXX finish when code revision is done +#' Filters trips_table(from ,\link{readTripsTable}) depending by location using a shapefile +#' +#' Uses trips_table and an sf object (can be created using the function st_read()), +#' transforms both objects to match a mutual coordinate system (crs) +#' and filters the trips from trips_table depending on *.inshape flags: +#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape +#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +#' +#' @param trips_table tibble of trips_output (from readTripsTable()) +#' +#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' +#' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file +#' +#' @param start.inshape bool, defines trips to conclude (see Description) +#' +#' @param end.inshape bool, defines trips to conclude (see Description) +#' +#' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) +#' +#' @export +process_filter_by_shape <- function(trips_table, + shape_table, + crs, + start.inshape = TRUE, end.inshape = TRUE) { - union_shape <- st_union(shape_table) # transforms the crs back to the previous in the file - union_shape <- st_transform(union_shape, crs = st_crs(shape_table)) + # shape_table <- st_read(shapeFile) + if (st_crs(shape_table) == NA) { + st_crs(shape_table) <- crs + } + sf_table <- transformToSf(trips_table, crs = crs, geometry.type = st_point()) + shape_table <- st_transform(shape_table, crs = crs) + # shape_table isn't table - shape - st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry - cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile + union_shape <- st_union(shape_table) # transforms the crs back to the previous in the file + union_shape <- st_transform(union_shape, crs = st_crs(shape_table)) - st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry - cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile - # get trips that ended outside of shape - cont_end_outside <- setdiff(1:nrow(sf_table), cont2) + st_geometry(sf_table) <- "start_wkt" # Set start_wkt as an active geometry + cont1 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where start point is in shapefile - # get trips that started outside of shape - cont_start_outside <- setdiff(1:nrow(sf_table), cont1) + st_geometry(sf_table) <- "end_wkt" # Set end_wkt as and active geometry + cont2 <- st_contains(union_shape, sf_table)[[1]] # Indexes of rows where end point is in shapefile - if (start.inshape == TRUE && end.inshape == TRUE) { - cont_union <- intersect(cont1, cont2) - } else if (start.inshape == TRUE && end.inshape == FALSE) { - cont_union <- intersect(cont1, cont_end_outside) - } else if (start.inshape == FALSE && end.inshape == TRUE) { - cont_union <- intersect(cont2, cont_start_outside) - } else { - cont_union <- intersect(cont_start_outside, cont_end_outside) # Give back trips that are neither starting and ending outside the area - } + # get trips that ended outside of shape + cont_end_outside <- setdiff(1:nrow(sf_table), cont2) + # get trips that started outside of shape + cont_start_outside <- setdiff(1:nrow(sf_table), cont1) - return(trips_table[cont_union, ]) + if (start.inshape == TRUE && end.inshape == TRUE) { + cont_union <- intersect(cont1, cont2) + } else if (start.inshape == TRUE && end.inshape == FALSE) { + cont_union <- intersect(cont1, cont_end_outside) + } else if (start.inshape == FALSE && end.inshape == TRUE) { + cont_union <- intersect(cont2, cont_start_outside) + } else { + cont_union <- intersect(cont_start_outside, cont_end_outside) # Give back trips that are neither starting and ending outside the area } - #' Reads the coordinate reference system from an MATSim output directory - #' (output_config.xml) - #' - #' @param config_path specifies path to configuration file - #' - #' - #' @return code of coordinate reference system - #' - #' @export - process_get_crs_from_config <- function(config_path) { - if (grepl("output_config.xml$", config_path) == TRUE) - { - config <- read_xml(folder) + return(trips_table[cont_union, ]) +} - param_nodes = xml_find_all(config,"//param") +#' Reads the coordinate reference system from an MATSim output directory +#' (output_config.xml) +#' +#' @param config_path specifies path to configuration file +#' +#' +#' @return code of coordinate reference system +#' +#' @export +process_get_crs_from_config <- function(config_path) { - coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] + if (grepl("output_config.xml$", config_path) == TRUE) + { + config <- read_xml(folder) - coord_system = xml_attr(coord_node,"value") - return(coord_system) - } + param_nodes = xml_find_all(config,"//param") + + coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] + + coord_system = xml_attr(coord_node,"value") + return(coord_system) + } - files <- list.files(config_path, full.names = TRUE) - # Read from global/local directory - # output_config.xml is contained as output_trips.csv.gz - if (length(grep("output_config.xml$", files)) != 0) { - config <- read_xml(files[grep("output_config.xml$", files)]) + files <- list.files(config_path, full.names = TRUE) + # Read from global/local directory + # output_config.xml is contained as output_trips.csv.gz + if (length(grep("output_config.xml$", files)) != 0) { + config <- read_xml(files[grep("output_config.xml$", files)]) - param_nodes = xml_find_all(config,"//param") + param_nodes = xml_find_all(config,"//param") - coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] + coord_node = param_nodes[xml_attr(param_nodes,"name") == "coordinateSystem"] - coord_system = xml_attr(coord_node,"value") - return(coord_system) - } - return(NA) + coord_system = xml_attr(coord_node,"value") + return(coord_system) } + return(NA) +} - #' Creates an origin/destination matrix either in conventional form (row names = origin, column names = destination) - #' or for simwrapper (origin and destination as columns) - #' - #' - #' @param tripsTable tibble of trips_output (from \link{readTripsTable}) - #' - #' @param shapePath string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file) - #' - #' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file - #' - #' @param dump.output.to string, path to a folder to save the .csv file - #' - #' @param colnames string, column names can be specified (i.e. to fit the shape file), if not they are numbered - #' - #' @param simwrapper boolean, creates output in the format used for simwrapper if the path for the shapefile is specified - #' - #' @param outer boolean, determines if flows outside of the shapefile are used, standard value is FALSE - #' - #' @return tibble of origin/destination matrix - #' - #' @export - process_get_od_matrix<- function(tripsTable, - shapePath, - crs, - dump.output.to = matsimDumpOutputDirectory, - simwrapper = FALSE, - colnames = "numeric", - outer = FALSE){ +#' Creates an origin/destination matrix either in conventional form (row names = origin, column names = destination) +#' or for simwrapper (origin and destination as columns) +#' +#' +#' @param tripsTable tibble of trips_output (from \link{readTripsTable}) +#' +#' @param shapePath string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file) +#' +#' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file +#' +#' @param dump.output.to string, path to a folder to save the .csv file +#' +#' @param colnames string, column names can be specified (i.e. to fit the shape file), if not they are numbered +#' +#' @param simwrapper boolean, creates output in the format used for simwrapper if the path for the shapefile is specified +#' +#' @param outer boolean, determines if flows outside of the shapefile are used, standard value is FALSE +#' +#' @return tibble of origin/destination matrix +#' +#' @export +process_get_od_matrix<- function(tripsTable, + shapePath, + crs, + dump.output.to = matsimDumpOutputDirectory, + simwrapper = FALSE, + colnames = "numeric", + outer = FALSE){ - defaultW <- getOption("warn") - options(warn = -1) + defaultW <- getOption("warn") + options(warn = -1) - #if tripstable given as folder/file - if(sum(class(tripsTable) %in% c("tbl_df","tbl","data.frame"))<1){ - tripsTable <- readTripsTable(tripsTable) - } + #if tripstable given as folder/file + if(sum(class(tripsTable) %in% c("tbl_df","tbl","data.frame"))<1){ + tripsTable <- readTripsTable(tripsTable) + } - sfTable <- transformToSf(tripsTable,crs,geometry.type = st_point()) + sfTable <- transformToSf(tripsTable,crs,geometry.type = st_point()) - shape = st_read(shapePath) + shape = st_read(shapePath) - if (st_crs(shape) == NA) { - st_crs(shape) <- crs - } - shape = st_transform(shape,crs = crs) + if (st_crs(shape) == NA) { + st_crs(shape) <- crs + } + shape = st_transform(shape,crs = crs) - sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) + sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) - sf_start = sfTable %>% select(trip_id,start_wkt) - st_geometry(sfTable) = "end_wkt" - sf_end = sfTable %>% select(trip_id,end_wkt) + sf_start = sfTable %>% select(trip_id,start_wkt) + st_geometry(sfTable) = "end_wkt" + sf_end = sfTable %>% select(trip_id,end_wkt) - #Get all inner intersects - sf_intersect_start = st_contains(shape,sf_start) - sf_intersect_end = st_contains(shape,sf_end) + #Get all inner intersects + sf_intersect_start = st_contains(shape,sf_start) + sf_intersect_end = st_contains(shape,sf_end) - if(outer == TRUE){ - #Get all outer intersects - joined_shape = st_union(shape) + if(outer == TRUE){ + #Get all outer intersects + joined_shape = st_union(shape) - start_inside = st_contains(joined_shape,sf_start) - end_inside = st_contains(joined_shape,sf_end) + start_inside = st_contains(joined_shape,sf_start) + end_inside = st_contains(joined_shape,sf_end) - start_outside = 1:nrow(sf_start) - end_outside = 1:nrow(sf_end) + start_outside = 1:nrow(sf_start) + end_outside = 1:nrow(sf_end) - start_outside = start_outside[! start_outside %in% start_inside[[1]]] + start_outside = start_outside[! start_outside %in% start_inside[[1]]] - end_outside = end_outside[! end_outside %in% end_inside[[1]]] + end_outside = end_outside[! end_outside %in% end_inside[[1]]] - sf_intersect_start = append(sf_intersect_start,list(start_outside)) - sf_intersect_end = append(sf_intersect_end,list(end_outside)) - } + sf_intersect_start = append(sf_intersect_start,list(start_outside)) + sf_intersect_end = append(sf_intersect_end,list(end_outside)) + } - # Create matrix out of it - result_tibble = as_tibble(data.frame(matrix(nrow=0,ncol=nrow(shape)))) - colnames(result_tibble) = 1:nrow(shape) + # Create matrix out of it + result_tibble = as_tibble(data.frame(matrix(nrow=0,ncol=nrow(shape)))) + colnames(result_tibble) = 1:nrow(shape) - for(i in 1:length(sf_intersect_start)){ - temp = c() - for(j in 1:length(sf_intersect_start)){ - start_i = sf_intersect_start[[i]] - end_j = sf_intersect_end[[j]] + for(i in 1:length(sf_intersect_start)){ + temp = c() + for(j in 1:length(sf_intersect_start)){ + start_i = sf_intersect_start[[i]] + end_j = sf_intersect_end[[j]] - number_of_trips = length(intersect(start_i,end_j)) + number_of_trips = length(intersect(start_i,end_j)) - temp = append(temp,number_of_trips) + temp = append(temp,number_of_trips) - } - result_tibble = rbind(result_tibble,temp) } + result_tibble = rbind(result_tibble,temp) + } - if(colnames!="numeric" & colnames %in% colnames(shape)){ - colnames(result_tibble) = shape[[colnames]] - if(outer == TRUE){ - rownames(result_tibble) = c(shape[[colnames]],"outer") - colnames(result_tibble)[length(colnames(result_tibble))] = "outer" - }else{ - rownames(result_tibble) = shape[[colnames]] - } - + if(colnames!="numeric" & colnames %in% colnames(shape)){ + colnames(result_tibble) = shape[[colnames]] + if(outer == TRUE){ + rownames(result_tibble) = c(shape[[colnames]],"outer") + colnames(result_tibble)[length(colnames(result_tibble))] = "outer" }else{ - colnames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) - rownames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) + rownames(result_tibble) = shape[[colnames]] } + }else{ + colnames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) + rownames(result_tibble) = sapply(1:length(sf_intersect_start),as.character) + } - result_melt = melt(as.matrix(result_tibble)) - colnames(result_melt) = c("origin","destination",1) - # Generating yaml and output_files + result_melt = melt(as.matrix(result_tibble)) + colnames(result_melt) = c("origin","destination",1) + # Generating yaml and output_files - if (file.exists(dump.output.to) & simwrapper == TRUE) { - write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") - } else if(!file.exists(dump.output.to) & simwrapper == TRUE) { - dir.create(dump.output.to) - write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") - } else if (file.exists(dump.output.to) & simwrapper == FALSE) { - write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) - } else { - dir.create(dump.output.to) - write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) - } - yaml_list <- list( - title = "OD Flow", - description = "generated by deriveODMatrix", - projection = st_crs(shape)$input, - shpFile = paste0("../",shapePath), - dbfFile = paste0("../",substr(shapePath,start = 1,stop = nchar(shapePath)-3),"dbf"), - scaleFactor = 1, - lineWidth = 50, - csvFile = "ODMatrix.csv", - idColumn = colnames(shape)[1] # at the moment idColumn of shapefile should be the first column + if (file.exists(dump.output.to) & simwrapper == TRUE) { + write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") + } else if(!file.exists(dump.output.to) & simwrapper == TRUE) { + dir.create(dump.output.to) + write.table(result_melt,paste0(dump.output.to,"/ODMatrix.csv"),row.names = FALSE,sep = ";") + } else if (file.exists(dump.output.to) & simwrapper == FALSE) { + write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) + } else { + dir.create(dump.output.to) + write_csv2(result_tibble,paste0(dump.output.to,"/ODMatrix.csv")) + } - ) - write_yaml(yaml_list, paste0(dump.output.to, "/viz-od-flow.yaml")) - - options(warn = defaultW) - return(result_tibble) - } - - - - #' Transforms the data frame trips_output (from \links{readTripsTable}) from tibble to sf (table with geometry features) - #' - #' Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features. - #' If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format), - #' if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt. - #' Added column/columns are projected to given CRS (coordinate reference system). - #' The columns start_x, end_x, start_y, end_y are deleted from the resulting data frame. - #' - #' @param table tibble trips_output (from readTripsTable()) - #' - #' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file - #' - #' @param geometry.type type of sf transformation, default is st_multipoint(), geometry.type can be: - #' !!!st_point()- resulting table contains two geometry columns: start_wkt and end_wkt, representing start and end points as POINTS!!! or - #' !!!st_multipoint()- resulting table contains one geometry column, representing start and end points as MULTIPOINT!!! or - #' !!!st_linestring() - resulting table contains one geometry column, representing the line between start and end points as LINESTRING!!! - #' - #' @return sf object (data frame with geometries depending on geometry.type) - #' - #' @export - transformToSf <- function(table, - crs, - geometry.type = st_multipoint()) { - if (class(geometry.type)[2] == "POINT") { - table1 <- table %>% - # mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep ="")) - mutate(start_wkt = paste("POINT(", start_x, " ", start_y, ")", sep = "")) - table2 <- table %>% - mutate(end_wkt = paste("POINT(", end_x, " ", end_y, ")", sep = "")) - attr(table, "geometry.type") <- "POINT" - - - table1_wkt <- st_as_sf(table1, wkt = "start_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - table2_wkt <- st_as_sf(table2, wkt = "end_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - - - result_table <- table1_wkt %>% mutate(end_wkt = table2_wkt$end_wkt) - st_geometry(result_table) <- "start_wkt" - st_crs(result_table) <- crs - st_geometry(result_table) <- "end_wkt" - st_crs(result_table) <- crs - st_geometry(result_table) <- "start_wkt" - return(result_table) - } else if (class(geometry.type)[2] == "MULTIPOINT") { - table <- table %>% - mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) - attr(table, "geometry.type") <- "MULTIPOINT" - - - result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - - st_crs(result_table) <- crs - return(result_table) - } else if (class(geometry.type)[2] == "LINESTRING") { - table <- table %>% - mutate(wkt = paste("LINESTRING(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) - attr(table, "geometry.type") <- "LINESTRING" - - - result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) - - st_crs(result_table) <- crs - return(result_table) - } else { - return(NA) - } + yaml_list <- list( + title = "OD Flow", + description = "generated by deriveODMatrix", + projection = st_crs(shape)$input, + shpFile = paste0("../",shapePath), + dbfFile = paste0("../",substr(shapePath,start = 1,stop = nchar(shapePath)-3),"dbf"), + scaleFactor = 1, + lineWidth = 50, + csvFile = "ODMatrix.csv", + idColumn = colnames(shape)[1] # at the moment idColumn of shapefile should be the first column + + ) + write_yaml(yaml_list, paste0(dump.output.to, "/viz-od-flow.yaml")) + + options(warn = defaultW) + return(result_tibble) +} + + + +#' Transforms the data frame trips_output (from \links{readTripsTable}) from tibble to sf (table with geometry features) +#' +#' Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features. +#' If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format), +#' if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt. +#' Added column/columns are projected to given CRS (coordinate reference system). +#' The columns start_x, end_x, start_y, end_y are deleted from the resulting data frame. +#' +#' @param table tibble trips_output (from readTripsTable()) +#' +#' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file +#' +#' @param geometry.type type of sf transformation, default is st_multipoint(), geometry.type can be: +#' !!!st_point()- resulting table contains two geometry columns: start_wkt and end_wkt, representing start and end points as POINTS!!! or +#' !!!st_multipoint()- resulting table contains one geometry column, representing start and end points as MULTIPOINT!!! or +#' !!!st_linestring() - resulting table contains one geometry column, representing the line between start and end points as LINESTRING!!! +#' +#' @return sf object (data frame with geometries depending on geometry.type) +#' +#' @export +transformToSf <- function(table, + crs, + geometry.type = st_multipoint()) { + if (class(geometry.type)[2] == "POINT") { + table1 <- table %>% + # mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep ="")) + mutate(start_wkt = paste("POINT(", start_x, " ", start_y, ")", sep = "")) + table2 <- table %>% + mutate(end_wkt = paste("POINT(", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "POINT" + + + table1_wkt <- st_as_sf(table1, wkt = "start_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + table2_wkt <- st_as_sf(table2, wkt = "end_wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + + result_table <- table1_wkt %>% mutate(end_wkt = table2_wkt$end_wkt) + st_geometry(result_table) <- "start_wkt" + st_crs(result_table) <- crs + st_geometry(result_table) <- "end_wkt" + st_crs(result_table) <- crs + st_geometry(result_table) <- "start_wkt" + return(result_table) + } else if (class(geometry.type)[2] == "MULTIPOINT") { + table <- table %>% + mutate(wkt = paste("MULTIPOINT(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "MULTIPOINT" + + + result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + st_crs(result_table) <- crs + return(result_table) + } else if (class(geometry.type)[2] == "LINESTRING") { + table <- table %>% + mutate(wkt = paste("LINESTRING(", start_x, " ", start_y, ",", end_x, " ", end_y, ")", sep = "")) + attr(table, "geometry.type") <- "LINESTRING" + + + result_table <- st_as_sf(table, wkt = "wkt") %>% select(-start_x, -start_y, -end_x, -end_y) + + st_crs(result_table) <- crs + return(result_table) + } else { + return(NA) } +} - #####Helping functions#### +#####Helping functions#### From cb745059a8bcaa8ac9dc5a2af385506b96c5a9f5 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 29 Jun 2023 14:32:17 +0200 Subject: [PATCH 46/87] and closed curly bracket --- R/output_trips.R | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index aa78204..bc7b3c9 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2562,8 +2562,7 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, fig return(fig) - - +} #' Plot bar chart of changes in modal split #' #' Takes two data frames (from \link{readTripsTable()}), calculates the From 268427195d35d626c55a6b216ecce06d4772849e Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 5 Jul 2023 15:57:45 +0200 Subject: [PATCH 47/87] minor documentation changes --- NAMESPACE | 1 + R/output_trips.R | 89 +++++++++++++++++++----------- man/process_append_distcat.Rd | 20 +++++++ man/process_append_spatialcat.Rd | 28 +++++----- man/process_convert_table_to_sf.Rd | 16 +++--- man/process_convert_time.Rd | 27 +++++++++ man/process_filter_by_shape.Rd | 21 +++---- man/process_get_od_matrix.Rd | 12 ++-- 8 files changed, 141 insertions(+), 73 deletions(-) create mode 100644 man/process_append_distcat.Rd create mode 100644 man/process_convert_time.Rd diff --git a/NAMESPACE b/NAMESPACE index 22854ec..87984cb 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -61,6 +61,7 @@ export(process_filter_by_shape) export(process_get_crs_from_config) export(process_get_mainmode_distribution) export(process_get_od_matrix) +export(process_get_travdistance_distribution) export(process_get_travelwaittime_by_mainmode) export(process_rename_category) export(process_rename_mainmodes) diff --git a/R/output_trips.R b/R/output_trips.R index 0cea2b7..80078f4 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -3587,7 +3587,7 @@ process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ return(trips_table_count) } - +#' @export process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ trips_table = trips_table %>% @@ -3615,6 +3615,15 @@ process_get_travelwaittime_by_mainmode<-function(trips_table, } +#' Adds additional \strong{dist_cat} column representing category of distance traveled based on \strong{distances_array} parameter. +#' +#' Categorize column of distances based on \strong{distances_array}, each dist_cat receives relational segment from array.\cr +#' For example trip distance traveled is 1500, and distances array is (1000,2000), then this category is "1000-2000". +#' +#' @param trips_table tibble of trips_output (from \link{read_output_trips}) +#' +#' @param distances_array numeric vector, represents segments for distance categories ordered (in meters) +#' #' @export process_append_distcat <- function(trips_table,distances_array = c(1000,2000,5000,10000,20000,50000,100000)){ @@ -3639,6 +3648,20 @@ process_append_distcat <- function(trips_table,distances_array = c(1000,2000,500 return(result_table) } +#' Converts time column specified in \strong{time_column} to numeric representation of minutes, hours or seconds +#' +#' Default output_trips table time columns(\strong{dep_time}, \strong{trav_time}, \strong{wait_time}) are in 'hms' format, +#' that isn't convenient for use in some cases. To convert this type to numeric with different, specify \strong{time_column} to be converted, +#' and \strong{time_format} which will represent time(takes "hour", "minute", "second") +#' +#' @param trips_table tibble of trips_output (from \link{read_output_trips}) +#' +#' @param time_format char, defines time format to be used(takes "hour", "minute", "second") +#' +#' @param time_column char, name of the column from table to be converted(takes \strong{dep_time}, \strong{trav_time}, \strong{wait_time}) +#' +#' @return tibble, containing column with specified time_format +#' #' @export process_convert_time <- function(trips_table,time_format = "hour",time_column = "dep_time"){ @@ -3652,35 +3675,35 @@ process_convert_time <- function(trips_table,time_format = "hour",time_column = }else if(time_format == "hour"){ trips_table[[time_column]] = trips_table[[time_column]]/3600 return(trips_table) + }else if(time_format == "second"){ + return(trips_table) } + warning("time_format is unknown returned time is in seconds. Otherwise try minute, hour, second") return(trips_table) } ######Spatial###### -#' XXXX trips_table but shapeTable - fix naming #' XXXX finish when code revision is done #' Filters trips_table(from ,\link{readTripsTable}) depending by location using a shapefile #' #' Uses trips_table and an sf object (can be created using the function st_read()), #' transforms both objects to match a mutual coordinate system (crs) -#' and filters the trips from trips_table depending on *.inshape flags: -#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +#' and filters the trips from trips_table depending on spatial_type flags:\cr +#' if spatial_type="inside" return table that contains trips inside given shape\cr +#' if spatial_type="originating" return table that contains trips which starts in shape and ends out of the shape\cr +#' if spatial_type="destinating" return table that contains trips which ends in shape and starts out of the shape\cr +#' if spatial_type="outside" return table that contains trips which starts and ends our of the given shape #' #' @param trips_table tibble of trips_output (from readTripsTable()) #' -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' @param shape_table sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' #' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file #' -#' @param start.inshape bool, defines trips to conclude (see Description) -#' -#' @param end.inshape bool, defines trips to conclude (see Description) +#' @param spatial_type bool, defines trips to conclude (see Description) #' #' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) #' @@ -3749,18 +3772,18 @@ process_filter_by_shape <- function(trips_table, #' Appending spatial category as additional column to output_trips tibble #' XXXX -#' Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -#' Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +#' Takes trips_table and shape_table(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +#' Please be aware that this \link{process_filter_by_shape} currently only works, when one geometry is loaded.) #' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) #' and adds to the output_trips from table spatial category depending on postition related to shape file: -#' if start.inshape = TRUE & end.inshape = TRUE return table that contains trips \strong{inside} of the given shape -#' if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which \strong{originating} in the shape -#' if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which \strong{destinating} in the shape -#' if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which \strong{outside} of the given shape +#' category representing trips \strong{inside} of the given shape +#' category representing trips which \strong{originating} in the shape +#' category representing trips which \strong{destinating} in the shape +#' category representing trips which \strong{outside} of the given shape #' #' @param trips_table tibble of trips_output (from readTripsTable()) #' -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' @param shape_table sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' #' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' @@ -3875,8 +3898,8 @@ process_get_crs_from_config <- function(config_path) { #' @return tibble of origin/destination matrix #' #' @export -process_get_od_matrix<- function(tripsTable, - shapePath, +process_get_od_matrix<- function(trips_table, + shape_path, crs, dump.output.to = matsimDumpOutputDirectory, simwrapper = FALSE, @@ -3887,20 +3910,20 @@ process_get_od_matrix<- function(tripsTable, options(warn = -1) #if tripstable given as folder/file - if(sum(class(tripsTable) %in% c("tbl_df","tbl","data.frame"))<1){ - tripsTable <- readTripsTable(tripsTable) + if(sum(class(trips_table) %in% c("tbl_df","tbl","data.frame"))<1){ + tripsTable <- readTripsTable(trips_table) } - sfTable <- transformToSf(tripsTable,crs,geometry.type = st_point()) + sfTable <- transformToSf(trips_table,crs,geometry.type = st_point()) - shape = st_read(shapePath) + shape = st_read(shape_path) if (st_crs(shape) == NA) { st_crs(shape) <- crs } shape = st_transform(shape,crs = crs) - sf_table <- transformToSf(tripsTable, crs = crs, geometry.type = st_point()) + sf_table <- transformToSf(trips_table, crs = crs, geometry.type = st_point()) sf_start = sfTable %>% select(trip_id,start_wkt) st_geometry(sfTable) = "end_wkt" @@ -3973,20 +3996,20 @@ process_get_od_matrix<- function(tripsTable, #' Transforms the data frame trips_output (from \links{readTripsTable}) from tibble to sf (table with geometry features) #' -#' Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features. -#' If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format), -#' if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt. -#' Added column/columns are projected to given CRS (coordinate reference system). +#' Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features.\cr +#' If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format),\cr +#' if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt.\cr +#' Added column/columns are projected to given CRS (coordinate reference system).\cr #' The columns start_x, end_x, start_y, end_y are deleted from the resulting data frame. #' #' @param table tibble trips_output (from readTripsTable()) #' #' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file #' -#' @param geometry.type type of sf transformation, default is st_multipoint(), geometry.type can be: -#' !!!st_point()- resulting table contains two geometry columns: start_wkt and end_wkt, representing start and end points as POINTS!!! or -#' !!!st_multipoint()- resulting table contains one geometry column, representing start and end points as MULTIPOINT!!! or -#' !!!st_linestring() - resulting table contains one geometry column, representing the line between start and end points as LINESTRING!!! +#' @param geometry.type type of sf transformation, default is st_multipoint(), geometry.type can be:\cr +#' !!!st_point()- resulting table contains two geometry columns: start_wkt and end_wkt, representing start and end points as POINTS!!! or\cr +#' !!!st_multipoint()- resulting table contains one geometry column, representing start and end points as MULTIPOINT!!! or\cr +#' !!!st_linestring() - resulting table contains one geometry column, representing the line between start and end points as LINESTRING!!!\cr #' #' @return sf object (data frame with geometries depending on geometry.type) #' diff --git a/man/process_append_distcat.Rd b/man/process_append_distcat.Rd new file mode 100644 index 0000000..e0abf40 --- /dev/null +++ b/man/process_append_distcat.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_append_distcat} +\alias{process_append_distcat} +\title{Adds additional \strong{dist_cat} column representing category of distance traveled based on \strong{distances_array} parameter.} +\usage{ +process_append_distcat( + trips_table, + distances_array = c(1000, 2000, 5000, 10000, 20000, 50000, 1e+05) +) +} +\arguments{ +\item{trips_table}{tibble of trips_output (from \link{read_output_trips})} + +\item{distances_array}{numeric vector, represents segments for distance categories ordered (in meters)} +} +\description{ +Categorize column of distances based on \strong{distances_array}, each dist_cat receives relational segment from array.\cr +For example trip distance traveled is 1500, and distances array is (1000,2000), then this category is "1000-2000". +} diff --git a/man/process_append_spatialcat.Rd b/man/process_append_spatialcat.Rd index dd5f03a..5a87d42 100644 --- a/man/process_append_spatialcat.Rd +++ b/man/process_append_spatialcat.Rd @@ -4,23 +4,23 @@ \alias{process_append_spatialcat} \title{Appending spatial category as additional column to output_trips tibble XXXX -Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +Takes trips_table and shape_table(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +Please be aware that this \link{process_filter_by_shape} currently only works, when one geometry is loaded.) transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) and adds to the output_trips from table spatial category depending on postition related to shape file: -if start.inshape = TRUE & end.inshape = TRUE return table that contains trips \strong{inside} of the given shape -if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which \strong{originating} in the shape -if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which \strong{destinating} in the shape -if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which \strong{outside} of the given shape} +category representing trips \strong{inside} of the given shape +category representing trips which \strong{originating} in the shape +category representing trips which \strong{destinating} in the shape +category representing trips which \strong{outside} of the given shape} \usage{ process_append_spatialcat(trips_table, shape_table, crs) } \arguments{ \item{trips_table}{tibble of trips_output (from readTripsTable())} -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} +\item{shape_table}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} } \value{ tibble, with additional spatial column related to given shape @@ -28,12 +28,12 @@ tibble, with additional spatial column related to given shape \description{ Appending spatial category as additional column to output_trips tibble XXXX -Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +Takes trips_table and shape_table(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +Please be aware that this \link{process_filter_by_shape} currently only works, when one geometry is loaded.) transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) and adds to the output_trips from table spatial category depending on postition related to shape file: -if start.inshape = TRUE & end.inshape = TRUE return table that contains trips \strong{inside} of the given shape -if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which \strong{originating} in the shape -if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which \strong{destinating} in the shape -if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which \strong{outside} of the given shape +category representing trips \strong{inside} of the given shape +category representing trips which \strong{originating} in the shape +category representing trips which \strong{destinating} in the shape +category representing trips which \strong{outside} of the given shape } diff --git a/man/process_convert_table_to_sf.Rd b/man/process_convert_table_to_sf.Rd index 6f92ed6..eeb5f13 100644 --- a/man/process_convert_table_to_sf.Rd +++ b/man/process_convert_table_to_sf.Rd @@ -11,18 +11,18 @@ process_convert_table_to_sf(table, crs, geometry.type = st_multipoint()) \item{crs}{numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file} -\item{geometry.type}{type of sf transformation, default is st_multipoint(), geometry.type can be: -!!!st_point()- resulting table contains two geometry columns: start_wkt and end_wkt, representing start and end points as POINTS!!! or -!!!st_multipoint()- resulting table contains one geometry column, representing start and end points as MULTIPOINT!!! or -!!!st_linestring() - resulting table contains one geometry column, representing the line between start and end points as LINESTRING!!!} +\item{geometry.type}{type of sf transformation, default is st_multipoint(), geometry.type can be:\cr +!!!st_point()- resulting table contains two geometry columns: start_wkt and end_wkt, representing start and end points as POINTS!!! or\cr +!!!st_multipoint()- resulting table contains one geometry column, representing start and end points as MULTIPOINT!!! or\cr +!!!st_linestring() - resulting table contains one geometry column, representing the line between start and end points as LINESTRING!!!\cr} } \value{ sf object (data frame with geometries depending on geometry.type) } \description{ -Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features. -If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format), -if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt. -Added column/columns are projected to given CRS (coordinate reference system). +Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features.\cr +If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format),\cr +if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt.\cr +Added column/columns are projected to given CRS (coordinate reference system).\cr The columns start_x, end_x, start_y, end_y are deleted from the resulting data frame. } diff --git a/man/process_convert_time.Rd b/man/process_convert_time.Rd new file mode 100644 index 0000000..5802e1e --- /dev/null +++ b/man/process_convert_time.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_convert_time} +\alias{process_convert_time} +\title{Converts time column specified in \strong{time_column} to numeric representation of minutes, hours or seconds} +\usage{ +process_convert_time( + trips_table, + time_format = "hour", + time_column = "dep_time" +) +} +\arguments{ +\item{trips_table}{tibble of trips_output (from \link{read_output_trips})} + +\item{time_format}{char, defines time format to be used(takes "hour", "minute", "second")} + +\item{time_column}{char, name of the column from table to be converted(takes \strong{dep_time}, \strong{trav_time}, \strong{wait_time})} +} +\value{ +tibble, containing column with specified time_format +} +\description{ +Default output_trips table time columns(\strong{dep_time}, \strong{trav_time}, \strong{wait_time}) are in 'hms' format, +that isn't convenient for use in some cases. To convert this type to numeric with different, specify \strong{time_column} to be converted, +and \strong{time_format} which will represent time(takes "hour", "minute", "second") +} diff --git a/man/process_filter_by_shape.Rd b/man/process_filter_by_shape.Rd index bc82530..89d40b9 100644 --- a/man/process_filter_by_shape.Rd +++ b/man/process_filter_by_shape.Rd @@ -2,8 +2,7 @@ % Please edit documentation in R/output_trips.R \name{process_filter_by_shape} \alias{process_filter_by_shape} -\title{XXXX trips_table but shapeTable - fix naming -XXXX finish when code revision is done +\title{XXXX finish when code revision is done Filters trips_table(from ,\link{readTripsTable}) depending by location using a shapefile} \usage{ process_filter_by_shape(trips_table, shape_table, crs, spatial_type = "inside") @@ -11,13 +10,11 @@ process_filter_by_shape(trips_table, shape_table, crs, spatial_type = "inside") \arguments{ \item{trips_table}{tibble of trips_output (from readTripsTable())} -\item{crs}{numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file} - -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +\item{shape_table}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} -\item{start.inshape}{bool, defines trips to conclude (see Description)} +\item{crs}{numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file} -\item{end.inshape}{bool, defines trips to conclude (see Description)} +\item{spatial_type}{bool, defines trips to conclude (see Description)} } \value{ tibble, with filtered trips depending on shapeTable and special flags (see Description) @@ -25,9 +22,9 @@ tibble, with filtered trips depending on shapeTable and special flags (see Descr \description{ Uses trips_table and an sf object (can be created using the function st_read()), transforms both objects to match a mutual coordinate system (crs) -and filters the trips from trips_table depending on *.inshape flags: -if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +and filters the trips from trips_table depending on spatial_type flags:\cr +if spatial_type="inside" return table that contains trips inside given shape\cr +if spatial_type="originating" return table that contains trips which starts in shape and ends out of the shape\cr +if spatial_type="destinating" return table that contains trips which ends in shape and starts out of the shape\cr +if spatial_type="outside" return table that contains trips which starts and ends our of the given shape } diff --git a/man/process_get_od_matrix.Rd b/man/process_get_od_matrix.Rd index a3ecf55..1aec2cd 100644 --- a/man/process_get_od_matrix.Rd +++ b/man/process_get_od_matrix.Rd @@ -6,8 +6,8 @@ or for simwrapper (origin and destination as columns)} \usage{ process_get_od_matrix( - tripsTable, - shapePath, + trips_table, + shape_path, crs, dump.output.to = matsimDumpOutputDirectory, simwrapper = FALSE, @@ -16,10 +16,6 @@ process_get_od_matrix( ) } \arguments{ -\item{tripsTable}{tibble of trips_output (from \link{readTripsTable})} - -\item{shapePath}{string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file)} - \item{crs}{numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file} \item{dump.output.to}{string, path to a folder to save the .csv file} @@ -29,6 +25,10 @@ process_get_od_matrix( \item{colnames}{string, column names can be specified (i.e. to fit the shape file), if not they are numbered} \item{outer}{boolean, determines if flows outside of the shapefile are used, standard value is FALSE} + +\item{tripsTable}{tibble of trips_output (from \link{readTripsTable})} + +\item{shapePath}{string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file)} } \value{ tibble of origin/destination matrix From cfbbb8de0eb0ecab3112bb1e28f2a21a6131ec0e Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 5 Jul 2023 16:27:40 +0200 Subject: [PATCH 48/87] added details to matsimr-deprecated --- NAMESPACE | 4 +- R/output_trips.R | 243 ++++++++++-------- man/matsimr-deprecated.Rd | 32 +++ ...t_compare_count_by_spatialcat_barchart.Rd} | 6 +- ...> plot_distance_by_spatialcat_barchart.Rd} | 11 +- 5 files changed, 184 insertions(+), 112 deletions(-) rename man/{plot_compare_count_by_spatialcat.Rd => plot_compare_count_by_spatialcat_barchart.Rd} (91%) rename man/{plot_distance_by_spatialcat.Rd => plot_distance_by_spatialcat_barchart.Rd} (84%) diff --git a/NAMESPACE b/NAMESPACE index 87984cb..f5f665f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -31,7 +31,7 @@ export(plotTripDistanceByMode) export(plotTripDistancedByType) export(plotTripTypesPieChart) export(plot_arrtime_by_act) -export(plot_compare_count_by_spatialcat) +export(plot_compare_count_by_spatialcat_barchart) export(plot_compare_distcat_by_mainmode_barchart) export(plot_compare_mainmode_barchart) export(plot_compare_mainmode_sankey) @@ -39,7 +39,7 @@ export(plot_compare_travelwaittime_by_mainmode) export(plot_compare_travelwaittime_by_mainmode_barchart) export(plot_deptime_by_act) export(plot_distance_by_mainmode_barchart) -export(plot_distance_by_spatialcat) +export(plot_distance_by_spatialcat_barchart) export(plot_distcat_by_mainmode_barchart) export(plot_mainmode_barchart) export(plot_mainmode_piechart) diff --git a/R/output_trips.R b/R/output_trips.R index 80078f4..2c473ca 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -38,9 +38,41 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' @aliases plotModalSplitPieChart #' @section Details: #' \tabular{rl}{ +#' \strong{Plotting functions}:\cr #' \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr #' \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}}\cr +#' \code{plotAverageTravelWait} \tab now a synonym for \code{\link{plot_travelwaittime_mean_barchart}}\cr +#' \code{plotModalDistanceDistribution} \tab now a synonym for \code{\link{plot_distcat_by_mainmode_barchart}}\cr +#' \code{plotTripDistanceByMode} \tab now a synonym for \code{\link{plot_distance_by_mainmode_barchart}}\cr +#' \code{plotTripCountByDepTime} \tab now a synonym for \code{\link{plot_trips_count_by_deptime_and_mainmode_linechart}}\cr +#' \code{plotActivityEndTimes} \tab not part of package(contained false logic)\cr +#' \code{plotArrivalTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_arrtime_by_act}}\cr +#' \code{plotDepartureTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_deptime_by_act}}\cr +#' \strong{Spatial functions}:\cr +#' \code{plotTripTypesPieChart} \tab now a synonym for \code{\link{plot_spatialtype_by_shape_piechart}}\cr +#' \code{plotMapWithFilteredTrips} \tab not part of package, you can filter before drawing a map\cr +#' \code{plotMapWithTrips} \tab now a synonym for \code{\link{plot_map_trips}}\cr +#' \code{plotMapWithTripsType} \tab now a synonym for \code{\link{plot_map_trips_by_spatialcat}}\cr +#' \code{plotTripDistancedByType} \tab now a synonym for \code{\link{plot_distance_by_spatialcat_barchart}}\cr +#' \strong{Comparing functions}:\cr +#' \code{plotModalShiftBar} \tab now a synonym for \code{\link{plot_compare_mainmode_barchart}}\cr +#' \code{plotModalShiftSankey} \tab now a synonym for \code{\link{plot_compare_mainmode_sankey}}\cr +#' \code{compareAverageTravelWait} \tab now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}}\cr +#' \code{compareTripTypesBarChart} \tab now a synonym for \code{\link{plot_compare_count_by_spatialcat_barchart}}\cr +#' \code{compareModalDistanceDistribution} \tab now a synonym for \code{\link{plot_compare_distcat_by_mainmode_barchart}}\cr +#' \code{compareBasePolicyOutput} \tab is not used in new package version, and is prepared to be completely removed from package +#' If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} +#' \code{compareBasePolicyShapeOutput} \tab is not used in new package version, and is prepared to be completely removed from package +#' If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} +#' \strong{Processing functions}:\cr +#' \code{appendDistanceCategory} \tab now a synonym for \code{\link{process_append_distcat}}\cr +#' \code{filterByRegion} \tab now a synonym for \code{\link{process_filter_by_shape}}\cr +#' \code{deriveODMatrix} \tab now a synonym for \code{\link{process_get_od_matrix}}\cr +#' \code{getCrsFromConfig} \tab now a synonym for \code{\link{process_get_crs_from_config}}\cr +#' \code{transformToSf} \tab now a synonym for \code{\link{process_convert_table_to_sf}}\cr +#' \strong{Reading functions}:\cr #' \code{readTripsTable} \tab now a synonym for \code{\link{read_output_trips}}\cr +#' \code{readConfig} \tab now a synonym for \code{\link{read_config}}\cr #' } #' plotModalSplitPieChart <- function(tripsTable, @@ -2461,72 +2493,8 @@ plot_travelwaittime_mean_barchart <- function(trips_table, -#' Bar Chart comparing two runs with main_mode on x-axis and average travel/wait time on y-axis -#' -#' Takes two data frames (from \link{readTripsTable()}), -#' to plot a comparison bar chart of travel and wait times. -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') -#' -#' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()) -#' @param tripsTable2 tibble of trips_output (from readTripsTable()) -#' @param unite.modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode -#' -#' @return Bar chart plot comparing average time spent on travel/wait of two runs -#' -#' @export -plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, - unite.modes = character(0), - united.name = "united", - time_format = "minute") { - - #TODO: - # . Document and add title to show what means positive/negative value - # . think about comparing processing functions they can appear in future often - - - # renaming/uniting of modes - trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.modes = unite.modes, - united.name = united.name) - - trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.modes = unite.modes, - united.name = united.name) - - #processing - avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) - - - - avg_time2 = process_get_travelwaittime_by_mainmode(trips_table2,time_format = time_format) - - - avg_time = full_join(avg_time1, avg_time2, by = "main_mode") %>% - replace_na(list(trav_time_avg.x = 0,wait_time_avg.x = 0,trav_time_avg.y = 0,wait_time_avg.y = 0)) - - - - avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg.x - trav_time_avg.y, - wait_time_avg =wait_time_avg.x - wait_time_avg.y )%>% - select(-wait_time_avg.x,-wait_time_avg.y, -trav_time_avg.x,-trav_time_avg.y) - - #plotting - fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") - fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") - fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)")),barmode = "group") - - - fig - return(fig) - -} - #' Bar Chart with distance traveled on x-axis and number of trips on y-axis #' #' Takes the data frame trips_output (from \link{readTripsTable()}) and categorizes the traveled distances into pre-defined bins @@ -2706,7 +2674,7 @@ plot_spatialtype_by_shape_piechart <- function(trips_table, shape_table, crs) { #' @return Bar Chart plot of distance traveled by spatial type #' #' @export -plot_distance_by_spatialcat <- function(trips_table, shape_table, crs, euclidian = FALSE) { +plot_distance_by_spatialcat_barchart <- function(trips_table, shape_table, crs, euclidian = FALSE) { #processing @@ -2719,6 +2687,45 @@ plot_distance_by_spatialcat <- function(trips_table, shape_table, crs, euclidian fig return(fig) } +#' Line plot with departure time on x-axis and number of trips on y-axis +#' +#' Takes data frame trips_output (from \link{readTripsTable()}), +#' to create a line plot of the number of trips for a specific departure time by main_mode +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' +#' +#' @param tripsTable tibble of trips_output (from readTripsTable()) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode +#' @return Line plot of trips count by departure time per mode +#' +#' @export +plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, + unite.columns = character(0), + united.name = "united") { + + + # If some columns should be united + trips_table <- process_rename_mainmodes(trips_table = trips_table, + unite.columns = unite.columns, + united.name = united.name) + + + #processing + tripsTable = tripsTable %>% + mutate(dep_time = hour(dep_time)) %>% + count(dep_time,main_mode) + + + #plotting + fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) + fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") + + fig + return(fig) +} #' Deprecated function(s) in the matsimr package @@ -2882,45 +2889,7 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, } -#' Line plot with departure time on x-axis and number of trips on y-axis -#' -#' Takes data frame trips_output (from \link{readTripsTable()}), -#' to create a line plot of the number of trips for a specific departure time by main_mode -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') -#' -#' -#' @param tripsTable tibble of trips_output (from readTripsTable()) -#' @param unite.modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode -#' @return Line plot of trips count by departure time per mode -#' -#' @export -plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, - unite.columns = character(0), - united.name = "united") { - - - # If some columns should be united - trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, - united.name = united.name) - - - #processing - tripsTable = tripsTable %>% - mutate(dep_time = hour(dep_time)) %>% - count(dep_time,main_mode) - - #plotting - fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) - fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") - - fig - return(fig) -} #' Plot bar chart of changes in modal split #' #' Takes two data frames (from \link{readTripsTable()}), calculates the @@ -3135,7 +3104,7 @@ plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_ #' @return Bar Chart plot of average time spent on travel/wait #' #' @export -plot_compare_count_by_spatialcat <- function(trips_table1,trips_table2, shape_table ,crs,dump.output.to = matsimDumpOutputDirectory) { +plot_compare_count_by_spatialcat_barchart <- function(trips_table1,trips_table2, shape_table ,crs,dump.output.to = matsimDumpOutputDirectory) { spatial_table1 <- process_append_spatialcat(trips_table = trips_table1, shape_table = shape_table, @@ -3156,6 +3125,72 @@ plot_compare_count_by_spatialcat <- function(trips_table1,trips_table2, shape_ta } +#' Bar Chart comparing two runs with main_mode on x-axis and average travel/wait time on y-axis +#' +#' Takes two data frames (from \link{readTripsTable()}), +#' to plot a comparison bar chart of travel and wait times. +#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' +#' +#' @param tripsTable1 tibble of trips_output (from readTripsTable()) +#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +#' using the function (\link{process_rename_mainmodes}) +#' @param united.name character string, specifies the name of the united mode +#' +#' @return Bar chart plot comparing average time spent on travel/wait of two runs +#' +#' @export +plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, + unite.modes = character(0), + united.name = "united", + time_format = "minute") { + + #TODO: + # . Document and add title to show what means positive/negative value + # . think about comparing processing functions they can appear in future often + + + # renaming/uniting of modes + trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, + unite.modes = unite.modes, + united.name = united.name) + + trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, + unite.modes = unite.modes, + united.name = united.name) + + #processing + avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) + + + + avg_time2 = process_get_travelwaittime_by_mainmode(trips_table2,time_format = time_format) + + + avg_time = full_join(avg_time1, avg_time2, by = "main_mode") %>% + replace_na(list(trav_time_avg.x = 0,wait_time_avg.x = 0,trav_time_avg.y = 0,wait_time_avg.y = 0)) + + + + avg_time = avg_time %>% mutate(trav_time_avg = trav_time_avg.x - trav_time_avg.y, + wait_time_avg =wait_time_avg.x - wait_time_avg.y )%>% + select(-wait_time_avg.x,-wait_time_avg.y, -trav_time_avg.x,-trav_time_avg.y) + + + + #plotting + fig = plot_ly(data = avg_time,x = ~main_mode,y = ~trav_time_avg,type = 'bar',name = "AVG Time Travelling") + fig = fig %>% add_trace(y = ~wait_time_avg,name = "AVG Time Waiting") + fig = fig %>% layout(yaxis = list(title = paste0("Time spent (in ",time_format,"s)")),barmode = "group") + + + fig + return(fig) + +} + diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index ff35e46..a76cb28 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -458,9 +458,41 @@ to get which type of table was generated, if it is needed \section{Details}{ \tabular{rl}{ + \strong{Plotting functions}:\cr \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}}\cr + \code{plotAverageTravelWait} \tab now a synonym for \code{\link{plot_travelwaittime_mean_barchart}}\cr + \code{plotModalDistanceDistribution} \tab now a synonym for \code{\link{plot_distcat_by_mainmode_barchart}}\cr + \code{plotTripDistanceByMode} \tab now a synonym for \code{\link{plot_distance_by_mainmode_barchart}}\cr + \code{plotTripCountByDepTime} \tab now a synonym for \code{\link{plot_trips_count_by_deptime_and_mainmode_linechart}}\cr + \code{plotActivityEndTimes} \tab not part of package(contained false logic)\cr + \code{plotArrivalTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_arrtime_by_act}}\cr + \code{plotDepartureTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_deptime_by_act}}\cr + \strong{Spatial functions}:\cr + \code{plotTripTypesPieChart} \tab now a synonym for \code{\link{plot_spatialtype_by_shape_piechart}}\cr + \code{plotMapWithFilteredTrips} \tab not part of package, you can filter before drawing a map\cr + \code{plotMapWithTrips} \tab now a synonym for \code{\link{plot_map_trips}}\cr + \code{plotMapWithTripsType} \tab now a synonym for \code{\link{plot_map_trips_by_spatialcat}}\cr + \code{plotTripDistancedByType} \tab now a synonym for \code{\link{plot_distance_by_spatialcat_barchart}}\cr + \strong{Comparing functions}:\cr + \code{plotModalShiftBar} \tab now a synonym for \code{\link{plot_compare_mainmode_barchart}}\cr + \code{plotModalShiftSankey} \tab now a synonym for \code{\link{plot_compare_mainmode_sankey}}\cr + \code{compareAverageTravelWait} \tab now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}}\cr + \code{compareTripTypesBarChart} \tab now a synonym for \code{\link{plot_compare_count_by_spatialcat_barchart}}\cr + \code{compareModalDistanceDistribution} \tab now a synonym for \code{\link{plot_compare_distcat_by_mainmode_barchart}}\cr + \code{compareBasePolicyOutput} \tab is not used in new package version, and is prepared to be completely removed from package + If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} + \code{compareBasePolicyShapeOutput} \tab is not used in new package version, and is prepared to be completely removed from package + If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} + \strong{Processing functions}:\cr + \code{appendDistanceCategory} \tab now a synonym for \code{\link{process_append_distcat}}\cr + \code{filterByRegion} \tab now a synonym for \code{\link{process_filter_by_shape}}\cr + \code{deriveODMatrix} \tab now a synonym for \code{\link{process_get_od_matrix}}\cr + \code{getCrsFromConfig} \tab now a synonym for \code{\link{process_get_crs_from_config}}\cr + \code{transformToSf} \tab now a synonym for \code{\link{process_convert_table_to_sf}}\cr + \strong{Reading functions}:\cr \code{readTripsTable} \tab now a synonym for \code{\link{read_output_trips}}\cr + \code{readConfig} \tab now a synonym for \code{\link{read_config}}\cr } } diff --git a/man/plot_compare_count_by_spatialcat.Rd b/man/plot_compare_count_by_spatialcat_barchart.Rd similarity index 91% rename from man/plot_compare_count_by_spatialcat.Rd rename to man/plot_compare_count_by_spatialcat_barchart.Rd index 7577794..d587af5 100644 --- a/man/plot_compare_count_by_spatialcat.Rd +++ b/man/plot_compare_count_by_spatialcat_barchart.Rd @@ -1,7 +1,7 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/output_trips.R -\name{plot_compare_count_by_spatialcat} -\alias{plot_compare_count_by_spatialcat} +\name{plot_compare_count_by_spatialcat_barchart} +\alias{plot_compare_count_by_spatialcat_barchart} \title{Bar Chart with main_mode on x-axis and average travel/wait time on y-axis XXXX Takes Table trips_output (from readTripsTable()), @@ -9,7 +9,7 @@ to plot bar chart with with values that represent time spent on traveling/waiting Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united')} \usage{ -plot_compare_count_by_spatialcat( +plot_compare_count_by_spatialcat_barchart( trips_table1, trips_table2, shape_table, diff --git a/man/plot_distance_by_spatialcat.Rd b/man/plot_distance_by_spatialcat_barchart.Rd similarity index 84% rename from man/plot_distance_by_spatialcat.Rd rename to man/plot_distance_by_spatialcat_barchart.Rd index 1d7082b..d984c66 100644 --- a/man/plot_distance_by_spatialcat.Rd +++ b/man/plot_distance_by_spatialcat_barchart.Rd @@ -1,14 +1,19 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/output_trips.R -\name{plot_distance_by_spatialcat} -\alias{plot_distance_by_spatialcat} +\name{plot_distance_by_spatialcat_barchart} +\alias{plot_distance_by_spatialcat_barchart} \title{Bar Chart with tripType on x-axis and travelled distance on y-axis XXXX Takes Table trips_output (from readTripsTable()), to plot bar chart with with values that represent travelled distance of each tripType related to the shapeTable} \usage{ -plot_distance_by_spatialcat(trips_table, shape_table, crs, euclidian = FALSE) +plot_distance_by_spatialcat_barchart( + trips_table, + shape_table, + crs, + euclidian = FALSE +) } \arguments{ \item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} From 7c7c45bfd3754c821d6012a576ea342f49c60f11 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 6 Jul 2023 15:16:15 +0200 Subject: [PATCH 49/87] details tab fix --- R/output_trips.R | 63 ++++++++++++++++++++------------------- man/matsimr-deprecated.Rd | 63 ++++++++++++++++++++------------------- 2 files changed, 64 insertions(+), 62 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 2c473ca..58f5f1f 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -37,42 +37,43 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' @export plotModalSplitPieChart #' @aliases plotModalSplitPieChart #' @section Details: +#' XXX - tab needs to be added to category rows #' \tabular{rl}{ -#' \strong{Plotting functions}:\cr -#' \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr -#' \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}}\cr -#' \code{plotAverageTravelWait} \tab now a synonym for \code{\link{plot_travelwaittime_mean_barchart}}\cr -#' \code{plotModalDistanceDistribution} \tab now a synonym for \code{\link{plot_distcat_by_mainmode_barchart}}\cr -#' \code{plotTripDistanceByMode} \tab now a synonym for \code{\link{plot_distance_by_mainmode_barchart}}\cr -#' \code{plotTripCountByDepTime} \tab now a synonym for \code{\link{plot_trips_count_by_deptime_and_mainmode_linechart}}\cr -#' \code{plotActivityEndTimes} \tab not part of package(contained false logic)\cr -#' \code{plotArrivalTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_arrtime_by_act}}\cr -#' \code{plotDepartureTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_deptime_by_act}}\cr -#' \strong{Spatial functions}:\cr -#' \code{plotTripTypesPieChart} \tab now a synonym for \code{\link{plot_spatialtype_by_shape_piechart}}\cr -#' \code{plotMapWithFilteredTrips} \tab not part of package, you can filter before drawing a map\cr -#' \code{plotMapWithTrips} \tab now a synonym for \code{\link{plot_map_trips}}\cr -#' \code{plotMapWithTripsType} \tab now a synonym for \code{\link{plot_map_trips_by_spatialcat}}\cr -#' \code{plotTripDistancedByType} \tab now a synonym for \code{\link{plot_distance_by_spatialcat_barchart}}\cr -#' \strong{Comparing functions}:\cr -#' \code{plotModalShiftBar} \tab now a synonym for \code{\link{plot_compare_mainmode_barchart}}\cr -#' \code{plotModalShiftSankey} \tab now a synonym for \code{\link{plot_compare_mainmode_sankey}}\cr -#' \code{compareAverageTravelWait} \tab now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}}\cr -#' \code{compareTripTypesBarChart} \tab now a synonym for \code{\link{plot_compare_count_by_spatialcat_barchart}}\cr -#' \code{compareModalDistanceDistribution} \tab now a synonym for \code{\link{plot_compare_distcat_by_mainmode_barchart}}\cr +#' \strong{Plotting functions}:\tab +#' \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}} +#' \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}} +#' \code{plotAverageTravelWait} \tab now a synonym for \code{\link{plot_travelwaittime_mean_barchart}} +#' \code{plotModalDistanceDistribution} \tab now a synonym for \code{\link{plot_distcat_by_mainmode_barchart}} +#' \code{plotTripDistanceByMode} \tab now a synonym for \code{\link{plot_distance_by_mainmode_barchart}} +#' \code{plotTripCountByDepTime} \tab now a synonym for \code{\link{plot_trips_count_by_deptime_and_mainmode_linechart}} +#' \code{plotActivityEndTimes} \tab not part of package(contained false logic) +#' \code{plotArrivalTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_arrtime_by_act}} +#' \code{plotDepartureTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_deptime_by_act}} +#' \strong{Spatial functions}:\tab +#' \code{plotTripTypesPieChart} \tab now a synonym for \code{\link{plot_spatialtype_by_shape_piechart}} +#' \code{plotMapWithFilteredTrips} \tab not part of package, you can filter before drawing a map +#' \code{plotMapWithTrips} \tab now a synonym for \code{\link{plot_map_trips}} +#' \code{plotMapWithTripsType} \tab now a synonym for \code{\link{plot_map_trips_by_spatialcat}} +#' \code{plotTripDistancedByType} \tab now a synonym for \code{\link{plot_distance_by_spatialcat_barchart}} +#' \strong{Comparing functions}:\tab +#' \code{plotModalShiftBar} \tab now a synonym for \code{\link{plot_compare_mainmode_barchart}} +#' \code{plotModalShiftSankey} \tab now a synonym for \code{\link{plot_compare_mainmode_sankey}} +#' \code{compareAverageTravelWait} \tab now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}} +#' \code{compareTripTypesBarChart} \tab now a synonym for \code{\link{plot_compare_count_by_spatialcat_barchart}} +#' \code{compareModalDistanceDistribution} \tab now a synonym for \code{\link{plot_compare_distcat_by_mainmode_barchart}} #' \code{compareBasePolicyOutput} \tab is not used in new package version, and is prepared to be completely removed from package #' If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} #' \code{compareBasePolicyShapeOutput} \tab is not used in new package version, and is prepared to be completely removed from package #' If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} -#' \strong{Processing functions}:\cr -#' \code{appendDistanceCategory} \tab now a synonym for \code{\link{process_append_distcat}}\cr -#' \code{filterByRegion} \tab now a synonym for \code{\link{process_filter_by_shape}}\cr -#' \code{deriveODMatrix} \tab now a synonym for \code{\link{process_get_od_matrix}}\cr -#' \code{getCrsFromConfig} \tab now a synonym for \code{\link{process_get_crs_from_config}}\cr -#' \code{transformToSf} \tab now a synonym for \code{\link{process_convert_table_to_sf}}\cr -#' \strong{Reading functions}:\cr -#' \code{readTripsTable} \tab now a synonym for \code{\link{read_output_trips}}\cr -#' \code{readConfig} \tab now a synonym for \code{\link{read_config}}\cr +#' \strong{Processing functions}:\tab +#' \code{appendDistanceCategory} \tab now a synonym for \code{\link{process_append_distcat}} +#' \code{filterByRegion} \tab now a synonym for \code{\link{process_filter_by_shape}} +#' \code{deriveODMatrix} \tab now a synonym for \code{\link{process_get_od_matrix}} +#' \code{getCrsFromConfig} \tab now a synonym for \code{\link{process_get_crs_from_config}} +#' \code{transformToSf} \tab now a synonym for \code{\link{process_convert_table_to_sf}} +#' \strong{Reading functions}:\tab +#' \code{readTripsTable} \tab now a synonym for \code{\link{read_output_trips}} +#' \code{readConfig} \tab now a synonym for \code{\link{read_config}} #' } #' plotModalSplitPieChart <- function(tripsTable, diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index a76cb28..6105dc8 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -457,42 +457,43 @@ to get which type of table was generated, if it is needed } \section{Details}{ +XXX - tab needs to be added to category rows \tabular{rl}{ - \strong{Plotting functions}:\cr - \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}}\cr - \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}}\cr - \code{plotAverageTravelWait} \tab now a synonym for \code{\link{plot_travelwaittime_mean_barchart}}\cr - \code{plotModalDistanceDistribution} \tab now a synonym for \code{\link{plot_distcat_by_mainmode_barchart}}\cr - \code{plotTripDistanceByMode} \tab now a synonym for \code{\link{plot_distance_by_mainmode_barchart}}\cr - \code{plotTripCountByDepTime} \tab now a synonym for \code{\link{plot_trips_count_by_deptime_and_mainmode_linechart}}\cr - \code{plotActivityEndTimes} \tab not part of package(contained false logic)\cr - \code{plotArrivalTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_arrtime_by_act}}\cr - \code{plotDepartureTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_deptime_by_act}}\cr - \strong{Spatial functions}:\cr - \code{plotTripTypesPieChart} \tab now a synonym for \code{\link{plot_spatialtype_by_shape_piechart}}\cr - \code{plotMapWithFilteredTrips} \tab not part of package, you can filter before drawing a map\cr - \code{plotMapWithTrips} \tab now a synonym for \code{\link{plot_map_trips}}\cr - \code{plotMapWithTripsType} \tab now a synonym for \code{\link{plot_map_trips_by_spatialcat}}\cr - \code{plotTripDistancedByType} \tab now a synonym for \code{\link{plot_distance_by_spatialcat_barchart}}\cr - \strong{Comparing functions}:\cr - \code{plotModalShiftBar} \tab now a synonym for \code{\link{plot_compare_mainmode_barchart}}\cr - \code{plotModalShiftSankey} \tab now a synonym for \code{\link{plot_compare_mainmode_sankey}}\cr - \code{compareAverageTravelWait} \tab now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}}\cr - \code{compareTripTypesBarChart} \tab now a synonym for \code{\link{plot_compare_count_by_spatialcat_barchart}}\cr - \code{compareModalDistanceDistribution} \tab now a synonym for \code{\link{plot_compare_distcat_by_mainmode_barchart}}\cr + \strong{Plotting functions}:\tab + \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}} + \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}} + \code{plotAverageTravelWait} \tab now a synonym for \code{\link{plot_travelwaittime_mean_barchart}} + \code{plotModalDistanceDistribution} \tab now a synonym for \code{\link{plot_distcat_by_mainmode_barchart}} + \code{plotTripDistanceByMode} \tab now a synonym for \code{\link{plot_distance_by_mainmode_barchart}} + \code{plotTripCountByDepTime} \tab now a synonym for \code{\link{plot_trips_count_by_deptime_and_mainmode_linechart}} + \code{plotActivityEndTimes} \tab not part of package(contained false logic) + \code{plotArrivalTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_arrtime_by_act}} + \code{plotDepartureTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_deptime_by_act}} + \strong{Spatial functions}:\tab + \code{plotTripTypesPieChart} \tab now a synonym for \code{\link{plot_spatialtype_by_shape_piechart}} + \code{plotMapWithFilteredTrips} \tab not part of package, you can filter before drawing a map + \code{plotMapWithTrips} \tab now a synonym for \code{\link{plot_map_trips}} + \code{plotMapWithTripsType} \tab now a synonym for \code{\link{plot_map_trips_by_spatialcat}} + \code{plotTripDistancedByType} \tab now a synonym for \code{\link{plot_distance_by_spatialcat_barchart}} + \strong{Comparing functions}:\tab + \code{plotModalShiftBar} \tab now a synonym for \code{\link{plot_compare_mainmode_barchart}} + \code{plotModalShiftSankey} \tab now a synonym for \code{\link{plot_compare_mainmode_sankey}} + \code{compareAverageTravelWait} \tab now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}} + \code{compareTripTypesBarChart} \tab now a synonym for \code{\link{plot_compare_count_by_spatialcat_barchart}} + \code{compareModalDistanceDistribution} \tab now a synonym for \code{\link{plot_compare_distcat_by_mainmode_barchart}} \code{compareBasePolicyOutput} \tab is not used in new package version, and is prepared to be completely removed from package If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} \code{compareBasePolicyShapeOutput} \tab is not used in new package version, and is prepared to be completely removed from package If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} - \strong{Processing functions}:\cr - \code{appendDistanceCategory} \tab now a synonym for \code{\link{process_append_distcat}}\cr - \code{filterByRegion} \tab now a synonym for \code{\link{process_filter_by_shape}}\cr - \code{deriveODMatrix} \tab now a synonym for \code{\link{process_get_od_matrix}}\cr - \code{getCrsFromConfig} \tab now a synonym for \code{\link{process_get_crs_from_config}}\cr - \code{transformToSf} \tab now a synonym for \code{\link{process_convert_table_to_sf}}\cr - \strong{Reading functions}:\cr - \code{readTripsTable} \tab now a synonym for \code{\link{read_output_trips}}\cr - \code{readConfig} \tab now a synonym for \code{\link{read_config}}\cr + \strong{Processing functions}:\tab + \code{appendDistanceCategory} \tab now a synonym for \code{\link{process_append_distcat}} + \code{filterByRegion} \tab now a synonym for \code{\link{process_filter_by_shape}} + \code{deriveODMatrix} \tab now a synonym for \code{\link{process_get_od_matrix}} + \code{getCrsFromConfig} \tab now a synonym for \code{\link{process_get_crs_from_config}} + \code{transformToSf} \tab now a synonym for \code{\link{process_convert_table_to_sf}} + \strong{Reading functions}:\tab + \code{readTripsTable} \tab now a synonym for \code{\link{read_output_trips}} + \code{readConfig} \tab now a synonym for \code{\link{read_config}} } } From 014e96fb5daf9382ebd331b03cfed0bbf25a799b Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 6 Jul 2023 15:20:36 +0200 Subject: [PATCH 50/87] removed details category --- R/output_trips.R | 5 ----- man/matsimr-deprecated.Rd | 5 ----- 2 files changed, 10 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 58f5f1f..02e6b57 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -39,7 +39,6 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' @section Details: #' XXX - tab needs to be added to category rows #' \tabular{rl}{ -#' \strong{Plotting functions}:\tab #' \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}} #' \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}} #' \code{plotAverageTravelWait} \tab now a synonym for \code{\link{plot_travelwaittime_mean_barchart}} @@ -49,13 +48,11 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' \code{plotActivityEndTimes} \tab not part of package(contained false logic) #' \code{plotArrivalTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_arrtime_by_act}} #' \code{plotDepartureTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_deptime_by_act}} -#' \strong{Spatial functions}:\tab #' \code{plotTripTypesPieChart} \tab now a synonym for \code{\link{plot_spatialtype_by_shape_piechart}} #' \code{plotMapWithFilteredTrips} \tab not part of package, you can filter before drawing a map #' \code{plotMapWithTrips} \tab now a synonym for \code{\link{plot_map_trips}} #' \code{plotMapWithTripsType} \tab now a synonym for \code{\link{plot_map_trips_by_spatialcat}} #' \code{plotTripDistancedByType} \tab now a synonym for \code{\link{plot_distance_by_spatialcat_barchart}} -#' \strong{Comparing functions}:\tab #' \code{plotModalShiftBar} \tab now a synonym for \code{\link{plot_compare_mainmode_barchart}} #' \code{plotModalShiftSankey} \tab now a synonym for \code{\link{plot_compare_mainmode_sankey}} #' \code{compareAverageTravelWait} \tab now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}} @@ -65,13 +62,11 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} #' \code{compareBasePolicyShapeOutput} \tab is not used in new package version, and is prepared to be completely removed from package #' If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} -#' \strong{Processing functions}:\tab #' \code{appendDistanceCategory} \tab now a synonym for \code{\link{process_append_distcat}} #' \code{filterByRegion} \tab now a synonym for \code{\link{process_filter_by_shape}} #' \code{deriveODMatrix} \tab now a synonym for \code{\link{process_get_od_matrix}} #' \code{getCrsFromConfig} \tab now a synonym for \code{\link{process_get_crs_from_config}} #' \code{transformToSf} \tab now a synonym for \code{\link{process_convert_table_to_sf}} -#' \strong{Reading functions}:\tab #' \code{readTripsTable} \tab now a synonym for \code{\link{read_output_trips}} #' \code{readConfig} \tab now a synonym for \code{\link{read_config}} #' } diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 6105dc8..571903a 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -459,7 +459,6 @@ to get which type of table was generated, if it is needed XXX - tab needs to be added to category rows \tabular{rl}{ - \strong{Plotting functions}:\tab \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}} \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}} \code{plotAverageTravelWait} \tab now a synonym for \code{\link{plot_travelwaittime_mean_barchart}} @@ -469,13 +468,11 @@ XXX - tab needs to be added to category rows \code{plotActivityEndTimes} \tab not part of package(contained false logic) \code{plotArrivalTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_arrtime_by_act}} \code{plotDepartureTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_deptime_by_act}} - \strong{Spatial functions}:\tab \code{plotTripTypesPieChart} \tab now a synonym for \code{\link{plot_spatialtype_by_shape_piechart}} \code{plotMapWithFilteredTrips} \tab not part of package, you can filter before drawing a map \code{plotMapWithTrips} \tab now a synonym for \code{\link{plot_map_trips}} \code{plotMapWithTripsType} \tab now a synonym for \code{\link{plot_map_trips_by_spatialcat}} \code{plotTripDistancedByType} \tab now a synonym for \code{\link{plot_distance_by_spatialcat_barchart}} - \strong{Comparing functions}:\tab \code{plotModalShiftBar} \tab now a synonym for \code{\link{plot_compare_mainmode_barchart}} \code{plotModalShiftSankey} \tab now a synonym for \code{\link{plot_compare_mainmode_sankey}} \code{compareAverageTravelWait} \tab now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}} @@ -485,13 +482,11 @@ XXX - tab needs to be added to category rows If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} \code{compareBasePolicyShapeOutput} \tab is not used in new package version, and is prepared to be completely removed from package If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} - \strong{Processing functions}:\tab \code{appendDistanceCategory} \tab now a synonym for \code{\link{process_append_distcat}} \code{filterByRegion} \tab now a synonym for \code{\link{process_filter_by_shape}} \code{deriveODMatrix} \tab now a synonym for \code{\link{process_get_od_matrix}} \code{getCrsFromConfig} \tab now a synonym for \code{\link{process_get_crs_from_config}} \code{transformToSf} \tab now a synonym for \code{\link{process_convert_table_to_sf}} - \strong{Reading functions}:\tab \code{readTripsTable} \tab now a synonym for \code{\link{read_output_trips}} \code{readConfig} \tab now a synonym for \code{\link{read_config}} } From 3df78532badef7e0937a4a0c0801f69d144bd6c1 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 6 Jul 2023 15:24:02 +0200 Subject: [PATCH 51/87] removed table at all --- R/output_trips.R | 3 --- man/matsimr-deprecated.Rd | 3 --- 2 files changed, 6 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 02e6b57..fa36d4d 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -37,8 +37,6 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' @export plotModalSplitPieChart #' @aliases plotModalSplitPieChart #' @section Details: -#' XXX - tab needs to be added to category rows -#' \tabular{rl}{ #' \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}} #' \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}} #' \code{plotAverageTravelWait} \tab now a synonym for \code{\link{plot_travelwaittime_mean_barchart}} @@ -69,7 +67,6 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' \code{transformToSf} \tab now a synonym for \code{\link{process_convert_table_to_sf}} #' \code{readTripsTable} \tab now a synonym for \code{\link{read_output_trips}} #' \code{readConfig} \tab now a synonym for \code{\link{read_config}} -#' } #' plotModalSplitPieChart <- function(tripsTable, unite.columns = character(0), united.name = "united", diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 571903a..64250bc 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -457,8 +457,6 @@ to get which type of table was generated, if it is needed } \section{Details}{ -XXX - tab needs to be added to category rows -\tabular{rl}{ \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}} \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}} \code{plotAverageTravelWait} \tab now a synonym for \code{\link{plot_travelwaittime_mean_barchart}} @@ -490,5 +488,4 @@ XXX - tab needs to be added to category rows \code{readTripsTable} \tab now a synonym for \code{\link{read_output_trips}} \code{readConfig} \tab now a synonym for \code{\link{read_config}} } -} From 3e710bcd4924e7e5d1f2ce61b4d899b0650256f4 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 6 Jul 2023 15:27:02 +0200 Subject: [PATCH 52/87] removed tabular --- R/output_trips.R | 56 +++++++++++++++++++-------------------- man/matsimr-deprecated.Rd | 56 +++++++++++++++++++-------------------- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index fa36d4d..9716734 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -37,36 +37,36 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' @export plotModalSplitPieChart #' @aliases plotModalSplitPieChart #' @section Details: -#' \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}} -#' \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}} -#' \code{plotAverageTravelWait} \tab now a synonym for \code{\link{plot_travelwaittime_mean_barchart}} -#' \code{plotModalDistanceDistribution} \tab now a synonym for \code{\link{plot_distcat_by_mainmode_barchart}} -#' \code{plotTripDistanceByMode} \tab now a synonym for \code{\link{plot_distance_by_mainmode_barchart}} -#' \code{plotTripCountByDepTime} \tab now a synonym for \code{\link{plot_trips_count_by_deptime_and_mainmode_linechart}} -#' \code{plotActivityEndTimes} \tab not part of package(contained false logic) -#' \code{plotArrivalTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_arrtime_by_act}} -#' \code{plotDepartureTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_deptime_by_act}} -#' \code{plotTripTypesPieChart} \tab now a synonym for \code{\link{plot_spatialtype_by_shape_piechart}} -#' \code{plotMapWithFilteredTrips} \tab not part of package, you can filter before drawing a map -#' \code{plotMapWithTrips} \tab now a synonym for \code{\link{plot_map_trips}} -#' \code{plotMapWithTripsType} \tab now a synonym for \code{\link{plot_map_trips_by_spatialcat}} -#' \code{plotTripDistancedByType} \tab now a synonym for \code{\link{plot_distance_by_spatialcat_barchart}} -#' \code{plotModalShiftBar} \tab now a synonym for \code{\link{plot_compare_mainmode_barchart}} -#' \code{plotModalShiftSankey} \tab now a synonym for \code{\link{plot_compare_mainmode_sankey}} -#' \code{compareAverageTravelWait} \tab now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}} -#' \code{compareTripTypesBarChart} \tab now a synonym for \code{\link{plot_compare_count_by_spatialcat_barchart}} -#' \code{compareModalDistanceDistribution} \tab now a synonym for \code{\link{plot_compare_distcat_by_mainmode_barchart}} -#' \code{compareBasePolicyOutput} \tab is not used in new package version, and is prepared to be completely removed from package +#' \code{plotModalSplitPieChart} now a synonym for \code{\link{plot_mainmode_piechart}}\cr +#' \code{plotModalSplitBarChart} now a synonym for \code{\link{plot_mainmode_barchart}}\cr +#' \code{plotAverageTravelWait} now a synonym for \code{\link{plot_travelwaittime_mean_barchart}}\cr +#' \code{plotModalDistanceDistribution} now a synonym for \code{\link{plot_distcat_by_mainmode_barchart}}\cr +#' \code{plotTripDistanceByMode} now a synonym for \code{\link{plot_distance_by_mainmode_barchart}}\cr +#' \code{plotTripCountByDepTime} now a synonym for \code{\link{plot_trips_count_by_deptime_and_mainmode_linechart}}\cr +#' \code{plotActivityEndTimes} not part of package(contained false logic)\cr +#' \code{plotArrivalTimesPerTripPurpose}now a synonym for \code{\link{plot_arrtime_by_act}}\cr +#' \code{plotDepartureTimesPerTripPurpose} now a synonym for \code{\link{plot_deptime_by_act}}\cr +#' \code{plotTripTypesPieChart} now a synonym for \code{\link{plot_spatialtype_by_shape_piechart}}\cr +#' \code{plotMapWithFilteredTrips}not part of package, you can filter before drawing a map\cr +#' \code{plotMapWithTrips}now a synonym for \code{\link{plot_map_trips}}\cr +#' \code{plotMapWithTripsType} now a synonym for \code{\link{plot_map_trips_by_spatialcat}}\cr +#' \code{plotTripDistancedByType} now a synonym for \code{\link{plot_distance_by_spatialcat_barchart}}\cr +#' \code{plotModalShiftBar} now a synonym for \code{\link{plot_compare_mainmode_barchart}} +#' \code{plotModalShiftSankey} now a synonym for \code{\link{plot_compare_mainmode_sankey}} +#' \code{compareAverageTravelWait} now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}} +#' \code{compareTripTypesBarChart}now a synonym for \code{\link{plot_compare_count_by_spatialcat_barchart}} +#' \code{compareModalDistanceDistribution} now a synonym for \code{\link{plot_compare_distcat_by_mainmode_barchart}} +#' \code{compareBasePolicyOutput} is not used in new package version, and is prepared to be completely removed from package #' If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} -#' \code{compareBasePolicyShapeOutput} \tab is not used in new package version, and is prepared to be completely removed from package +#' \code{compareBasePolicyShapeOutput} is not used in new package version, and is prepared to be completely removed from package #' If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} -#' \code{appendDistanceCategory} \tab now a synonym for \code{\link{process_append_distcat}} -#' \code{filterByRegion} \tab now a synonym for \code{\link{process_filter_by_shape}} -#' \code{deriveODMatrix} \tab now a synonym for \code{\link{process_get_od_matrix}} -#' \code{getCrsFromConfig} \tab now a synonym for \code{\link{process_get_crs_from_config}} -#' \code{transformToSf} \tab now a synonym for \code{\link{process_convert_table_to_sf}} -#' \code{readTripsTable} \tab now a synonym for \code{\link{read_output_trips}} -#' \code{readConfig} \tab now a synonym for \code{\link{read_config}} +#' \code{appendDistanceCategory}now a synonym for \code{\link{process_append_distcat}} +#' \code{filterByRegion} now a synonym for \code{\link{process_filter_by_shape}} +#' \code{deriveODMatrix} now a synonym for \code{\link{process_get_od_matrix}} +#' \code{getCrsFromConfig}now a synonym for \code{\link{process_get_crs_from_config}} +#' \code{transformToSf} now a synonym for \code{\link{process_convert_table_to_sf}} +#' \code{readTripsTable}now a synonym for \code{\link{read_output_trips}} +#' \code{readConfig} now a synonym for \code{\link{read_config}} #' plotModalSplitPieChart <- function(tripsTable, unite.columns = character(0), united.name = "united", diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 64250bc..d36730f 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -457,35 +457,35 @@ to get which type of table was generated, if it is needed } \section{Details}{ - \code{plotModalSplitPieChart} \tab now a synonym for \code{\link{plot_mainmode_piechart}} - \code{plotModalSplitBarChart} \tab now a synonym for \code{\link{plot_mainmode_barchart}} - \code{plotAverageTravelWait} \tab now a synonym for \code{\link{plot_travelwaittime_mean_barchart}} - \code{plotModalDistanceDistribution} \tab now a synonym for \code{\link{plot_distcat_by_mainmode_barchart}} - \code{plotTripDistanceByMode} \tab now a synonym for \code{\link{plot_distance_by_mainmode_barchart}} - \code{plotTripCountByDepTime} \tab now a synonym for \code{\link{plot_trips_count_by_deptime_and_mainmode_linechart}} - \code{plotActivityEndTimes} \tab not part of package(contained false logic) - \code{plotArrivalTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_arrtime_by_act}} - \code{plotDepartureTimesPerTripPurpose} \tab now a synonym for \code{\link{plot_deptime_by_act}} - \code{plotTripTypesPieChart} \tab now a synonym for \code{\link{plot_spatialtype_by_shape_piechart}} - \code{plotMapWithFilteredTrips} \tab not part of package, you can filter before drawing a map - \code{plotMapWithTrips} \tab now a synonym for \code{\link{plot_map_trips}} - \code{plotMapWithTripsType} \tab now a synonym for \code{\link{plot_map_trips_by_spatialcat}} - \code{plotTripDistancedByType} \tab now a synonym for \code{\link{plot_distance_by_spatialcat_barchart}} - \code{plotModalShiftBar} \tab now a synonym for \code{\link{plot_compare_mainmode_barchart}} - \code{plotModalShiftSankey} \tab now a synonym for \code{\link{plot_compare_mainmode_sankey}} - \code{compareAverageTravelWait} \tab now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}} - \code{compareTripTypesBarChart} \tab now a synonym for \code{\link{plot_compare_count_by_spatialcat_barchart}} - \code{compareModalDistanceDistribution} \tab now a synonym for \code{\link{plot_compare_distcat_by_mainmode_barchart}} - \code{compareBasePolicyOutput} \tab is not used in new package version, and is prepared to be completely removed from package + \code{plotModalSplitPieChart} now a synonym for \code{\link{plot_mainmode_piechart}}\cr + \code{plotModalSplitBarChart} now a synonym for \code{\link{plot_mainmode_barchart}}\cr + \code{plotAverageTravelWait} now a synonym for \code{\link{plot_travelwaittime_mean_barchart}}\cr + \code{plotModalDistanceDistribution} now a synonym for \code{\link{plot_distcat_by_mainmode_barchart}}\cr + \code{plotTripDistanceByMode} now a synonym for \code{\link{plot_distance_by_mainmode_barchart}}\cr + \code{plotTripCountByDepTime} now a synonym for \code{\link{plot_trips_count_by_deptime_and_mainmode_linechart}}\cr + \code{plotActivityEndTimes} not part of package(contained false logic)\cr + \code{plotArrivalTimesPerTripPurpose}now a synonym for \code{\link{plot_arrtime_by_act}}\cr + \code{plotDepartureTimesPerTripPurpose} now a synonym for \code{\link{plot_deptime_by_act}}\cr + \code{plotTripTypesPieChart} now a synonym for \code{\link{plot_spatialtype_by_shape_piechart}}\cr + \code{plotMapWithFilteredTrips}not part of package, you can filter before drawing a map\cr + \code{plotMapWithTrips}now a synonym for \code{\link{plot_map_trips}}\cr + \code{plotMapWithTripsType} now a synonym for \code{\link{plot_map_trips_by_spatialcat}}\cr + \code{plotTripDistancedByType} now a synonym for \code{\link{plot_distance_by_spatialcat_barchart}}\cr + \code{plotModalShiftBar} now a synonym for \code{\link{plot_compare_mainmode_barchart}} + \code{plotModalShiftSankey} now a synonym for \code{\link{plot_compare_mainmode_sankey}} + \code{compareAverageTravelWait} now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}} + \code{compareTripTypesBarChart}now a synonym for \code{\link{plot_compare_count_by_spatialcat_barchart}} + \code{compareModalDistanceDistribution} now a synonym for \code{\link{plot_compare_distcat_by_mainmode_barchart}} + \code{compareBasePolicyOutput} is not used in new package version, and is prepared to be completely removed from package If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} - \code{compareBasePolicyShapeOutput} \tab is not used in new package version, and is prepared to be completely removed from package + \code{compareBasePolicyShapeOutput} is not used in new package version, and is prepared to be completely removed from package If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} - \code{appendDistanceCategory} \tab now a synonym for \code{\link{process_append_distcat}} - \code{filterByRegion} \tab now a synonym for \code{\link{process_filter_by_shape}} - \code{deriveODMatrix} \tab now a synonym for \code{\link{process_get_od_matrix}} - \code{getCrsFromConfig} \tab now a synonym for \code{\link{process_get_crs_from_config}} - \code{transformToSf} \tab now a synonym for \code{\link{process_convert_table_to_sf}} - \code{readTripsTable} \tab now a synonym for \code{\link{read_output_trips}} - \code{readConfig} \tab now a synonym for \code{\link{read_config}} + \code{appendDistanceCategory}now a synonym for \code{\link{process_append_distcat}} + \code{filterByRegion} now a synonym for \code{\link{process_filter_by_shape}} + \code{deriveODMatrix} now a synonym for \code{\link{process_get_od_matrix}} + \code{getCrsFromConfig}now a synonym for \code{\link{process_get_crs_from_config}} + \code{transformToSf} now a synonym for \code{\link{process_convert_table_to_sf}} + \code{readTripsTable}now a synonym for \code{\link{read_output_trips}} + \code{readConfig} now a synonym for \code{\link{read_config}} } From 5b9b4ff646547096aab026bc91f0ed4feb10c62d Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 6 Jul 2023 15:29:42 +0200 Subject: [PATCH 53/87] added newlines to details --- R/output_trips.R | 28 ++++++++++++++-------------- man/matsimr-deprecated.Rd | 28 ++++++++++++++-------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 9716734..a33b081 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -51,22 +51,22 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' \code{plotMapWithTrips}now a synonym for \code{\link{plot_map_trips}}\cr #' \code{plotMapWithTripsType} now a synonym for \code{\link{plot_map_trips_by_spatialcat}}\cr #' \code{plotTripDistancedByType} now a synonym for \code{\link{plot_distance_by_spatialcat_barchart}}\cr -#' \code{plotModalShiftBar} now a synonym for \code{\link{plot_compare_mainmode_barchart}} -#' \code{plotModalShiftSankey} now a synonym for \code{\link{plot_compare_mainmode_sankey}} -#' \code{compareAverageTravelWait} now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}} -#' \code{compareTripTypesBarChart}now a synonym for \code{\link{plot_compare_count_by_spatialcat_barchart}} -#' \code{compareModalDistanceDistribution} now a synonym for \code{\link{plot_compare_distcat_by_mainmode_barchart}} +#' \code{plotModalShiftBar} now a synonym for \code{\link{plot_compare_mainmode_barchart}}\cr +#' \code{plotModalShiftSankey} now a synonym for \code{\link{plot_compare_mainmode_sankey}}\cr +#' \code{compareAverageTravelWait} now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}}\cr +#' \code{compareTripTypesBarChart}now a synonym for \code{\link{plot_compare_count_by_spatialcat_barchart}}\cr +#' \code{compareModalDistanceDistribution} now a synonym for \code{\link{plot_compare_distcat_by_mainmode_barchart}}\cr #' \code{compareBasePolicyOutput} is not used in new package version, and is prepared to be completely removed from package -#' If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} +#' If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de}\cr #' \code{compareBasePolicyShapeOutput} is not used in new package version, and is prepared to be completely removed from package -#' If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} -#' \code{appendDistanceCategory}now a synonym for \code{\link{process_append_distcat}} -#' \code{filterByRegion} now a synonym for \code{\link{process_filter_by_shape}} -#' \code{deriveODMatrix} now a synonym for \code{\link{process_get_od_matrix}} -#' \code{getCrsFromConfig}now a synonym for \code{\link{process_get_crs_from_config}} -#' \code{transformToSf} now a synonym for \code{\link{process_convert_table_to_sf}} -#' \code{readTripsTable}now a synonym for \code{\link{read_output_trips}} -#' \code{readConfig} now a synonym for \code{\link{read_config}} +#' If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de}\cr +#' \code{appendDistanceCategory}now a synonym for \code{\link{process_append_distcat}}\cr +#' \code{filterByRegion} now a synonym for \code{\link{process_filter_by_shape}}\cr +#' \code{deriveODMatrix} now a synonym for \code{\link{process_get_od_matrix}}\cr +#' \code{getCrsFromConfig}now a synonym for \code{\link{process_get_crs_from_config}}\cr +#' \code{transformToSf} now a synonym for \code{\link{process_convert_table_to_sf}}\cr +#' \code{readTripsTable}now a synonym for \code{\link{read_output_trips}}\cr +#' \code{readConfig} now a synonym for \code{\link{read_config}}\cr #' plotModalSplitPieChart <- function(tripsTable, unite.columns = character(0), united.name = "united", diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index d36730f..3b8ee2d 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -471,21 +471,21 @@ to get which type of table was generated, if it is needed \code{plotMapWithTrips}now a synonym for \code{\link{plot_map_trips}}\cr \code{plotMapWithTripsType} now a synonym for \code{\link{plot_map_trips_by_spatialcat}}\cr \code{plotTripDistancedByType} now a synonym for \code{\link{plot_distance_by_spatialcat_barchart}}\cr - \code{plotModalShiftBar} now a synonym for \code{\link{plot_compare_mainmode_barchart}} - \code{plotModalShiftSankey} now a synonym for \code{\link{plot_compare_mainmode_sankey}} - \code{compareAverageTravelWait} now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}} - \code{compareTripTypesBarChart}now a synonym for \code{\link{plot_compare_count_by_spatialcat_barchart}} - \code{compareModalDistanceDistribution} now a synonym for \code{\link{plot_compare_distcat_by_mainmode_barchart}} + \code{plotModalShiftBar} now a synonym for \code{\link{plot_compare_mainmode_barchart}}\cr + \code{plotModalShiftSankey} now a synonym for \code{\link{plot_compare_mainmode_sankey}}\cr + \code{compareAverageTravelWait} now a synonym for \code{\link{plot_compare_travelwaittime_by_mainmode_barchart}}\cr + \code{compareTripTypesBarChart}now a synonym for \code{\link{plot_compare_count_by_spatialcat_barchart}}\cr + \code{compareModalDistanceDistribution} now a synonym for \code{\link{plot_compare_distcat_by_mainmode_barchart}}\cr \code{compareBasePolicyOutput} is not used in new package version, and is prepared to be completely removed from package - If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} + If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de}\cr \code{compareBasePolicyShapeOutput} is not used in new package version, and is prepared to be completely removed from package - If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de} - \code{appendDistanceCategory}now a synonym for \code{\link{process_append_distcat}} - \code{filterByRegion} now a synonym for \code{\link{process_filter_by_shape}} - \code{deriveODMatrix} now a synonym for \code{\link{process_get_od_matrix}} - \code{getCrsFromConfig}now a synonym for \code{\link{process_get_crs_from_config}} - \code{transformToSf} now a synonym for \code{\link{process_convert_table_to_sf}} - \code{readTripsTable}now a synonym for \code{\link{read_output_trips}} - \code{readConfig} now a synonym for \code{\link{read_config}} + If you would like to keep it in new package, write at \strong{soboliev@campus.tu-berlin.de}\cr + \code{appendDistanceCategory}now a synonym for \code{\link{process_append_distcat}}\cr + \code{filterByRegion} now a synonym for \code{\link{process_filter_by_shape}}\cr + \code{deriveODMatrix} now a synonym for \code{\link{process_get_od_matrix}}\cr + \code{getCrsFromConfig}now a synonym for \code{\link{process_get_crs_from_config}}\cr + \code{transformToSf} now a synonym for \code{\link{process_convert_table_to_sf}}\cr + \code{readTripsTable}now a synonym for \code{\link{read_output_trips}}\cr + \code{readConfig} now a synonym for \code{\link{read_config}}\cr } From d060c8db572c6bd41ff0ae8cffb8c0462d38f886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Wed, 12 Jul 2023 12:42:54 +0200 Subject: [PATCH 54/87] WIP documentation, added some comments that need clarification --- R/output_trips.R | 266 +++++++++++++++++++++++++---------------------- 1 file changed, 144 insertions(+), 122 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index a33b081..ca493ea 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -17,7 +17,7 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' These functions are provided for compatibility with older version of #' the matsimr package. They may eventually be completely #' removed.\cr\cr -#' \strong{plotModalSplitPieChart} - Takes Table trips_output (from readTripsTable()), +#' \strong{plotModalSplitPieChart} - Takes Table output_trips (from read_output_trips()), #' to plot pie chart with with values that represent #' percentage of using transport modes from trips #' @@ -25,7 +25,7 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' @name matsimr-deprecated #' #' -#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param tripsTable tible of output_trips (from read_output_trips()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored @@ -158,14 +158,14 @@ plotModalSplitPieChart <- function(tripsTable, } #' Deprecated function(s) in the matsimr package #' -#' \strong{plotModalSplitBarChart} - Takes Table trips_output (from readTripsTable()), +#' \strong{plotModalSplitBarChart} - Takes Table output_trips (from readTripsTable()), #' to plot bar chart with with values that represent #' percentage of using transport modes from trips #' #' @rdname matsimr-deprecated #' #' -#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param tripsTable tible of output_trips (from readTripsTable()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored @@ -273,7 +273,7 @@ plotModalSplitBarChart <- function(tripsTable, #' #' @param input_path character string, path to MATSim output directory or http link to the file. #' @param n_max integer, maximum number of lines to read within output_trips -#' @return \strong{readTripsTable} - tibble of trips_output +#' @return \strong{readTripsTable} - tibble of output_trips #' #' @export readTripsTable <-function(input_path = ".", n_max = Inf) { @@ -2294,14 +2294,13 @@ transformToSf <- function(table, #####Reading##### -#' Load MATSIM output_trips table into memory +#' Load MATSim output_trips table into memory #' -#' Loads a MATSim CSV output_trips from file or archive, -#' creating a tibble with columns as in csv file +#' Loads MATSim output_trips.csv from file or archive creating a tibble #' -#' @param input_path character string, path to the MATSim output directory or http link to the file. +#' @param input_path character string, path to the MATSim output directory or http link to the file #' @param n_max optional, integer, maximum number of lines to read, standard value is Inf -#' @return tibble of trips_output +#' @return tibble of output_trips #' #' @export read_output_trips <- function(input_path = ".", n_max = Inf) { @@ -2356,13 +2355,13 @@ read_output_trips <- function(input_path = ".", n_max = Inf) { #' Plot the distribution of modes as a pie chart #' -#' Uses the dataframe trips_output (from \link{readTripsTable}), +#' Uses the data frame output_trips (from \link{read_output_trips}), #' to plot a pie chart of the modal split using the column main_mode #' #' The function automatically detects the modes plots a pie chart. #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' -#' @param trips_table tibble of trips_output (from \link{readTripsTable}) +#' @param trips_table tibble of output_trips (from \link{read_output_trips}) #' @param unite.modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) @@ -2398,7 +2397,7 @@ plot_mainmode_piechart <- function(trips_table, #' Plot the distribution of modes as a bar chart #' -#' Takes the data frame trips_output (from \link{readTripsTable()}) +#' Takes the data frame output_trips (from \link{read_output_trips}) #' to plot a bar chart of the modal split using the column main_mode. #' #' The modal shares are given in percentages. @@ -2406,7 +2405,7 @@ plot_mainmode_piechart <- function(trips_table, #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tibble of trips_output (from \link{readTripsTable()}) +#' @param trips_table tibble of output_trips (from \link{read_output_trips}) #' @param unite.modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) @@ -2442,12 +2441,12 @@ plot_mainmode_barchart <- function(trips_table, #' Plot travel and wait time for each mode as a bar chart #' -#' Takes the data frame trips_output (from \links{readTripsTable()}), +#' Takes the data frame output_trips (from \links{read_output_trips()}), #' to plot a bar chart of travel and wait times. #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tibble of trips_output (from \links{readTripsTable()}) +#' @param trips_table tibble of output_trips (from \links{read_output_trips()}) #' @param unite.modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) @@ -2490,12 +2489,12 @@ plot_travelwaittime_mean_barchart <- function(trips_table, #' Bar Chart with distance traveled on x-axis and number of trips on y-axis #' -#' Takes the data frame trips_output (from \link{readTripsTable()}) and categorizes the traveled distances into pre-defined bins +#' Takes the data frame output_trips (from \link{read_output_trips()}) and categorizes the traveled distances into pre-defined bins #' to plot a histogram of the traveled distances. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tibble of trips_output (from readTripsTable()) +#' @param trips_table tibble of output_trips (from read_output_trips()) #' @param unite.modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) @@ -2533,12 +2532,12 @@ plot_distcat_by_mainmode_barchart <- function(trips_table, #' Bar chart with average distance traveled for each mode on x-axis and number of trips on y-axis #' -#' Takes the data frame trips_output (from \link{readTripsTable()}), +#' Takes the data frame output_trips (from \link{read_output_trips()}), #' to plot a bar chart of the average distance traveled for each main mode, #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tibble of trips_output (from readTripsTable()) +#' @param trips_table tibble of output_trips (from read_output_trips()) #'@param unite.modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) @@ -2581,12 +2580,12 @@ plot_distance_by_mainmode_barchart <- function(trips_table, #' Line plot with departure time on x-axis and number of trips on y-axis #' -#' Takes data frame trips_output (from \link{readTripsTable()}), +#' Takes data frame output_trips (from \link{read_output_trips()}), #' to create a line plot of the number of trips for a specific departure time by main_mode #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param tripsTable tibble of trips_output (from readTripsTable()) +#' @param tripsTable tibble of output_trips (from read_output_trips()) #' @param unite.modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) @@ -2618,19 +2617,18 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, return(fig) } -#' Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart -#' XXXX -#' -#' -#' @param table tibble of trips_output (from readTripsTable()) -#' -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' XXXX THE FUNCTION NAME IS NOT DESCRIPTIVE ENOUGH - what could we use instead of by shape? plot_trips_by_spatialtype? #' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' Plots distribution of trip types (inside, outside, origin and destinating) as a pie chart based on the data frame +#' output_trips (from \link{read_output_trips()}) #' +#' @param table tibble of output_trips (from \link{read_output_trips()}) +#' @param shapeTable sf object(data.frame with geometries), can be created using st_read() +#' @param crs numeric representation of the EPSG code or proj4string for the corresponding coordinate system +#' of the trip coordinates, can be found in network file from output directory of MATSim simulation #' #' -#' @return plot with percentage of each type of trips +#' @return plot with percentage of each type of trip #' #' @export plot_spatialtype_by_shape_piechart <- function(trips_table, shape_table, crs) { @@ -2653,18 +2651,18 @@ plot_spatialtype_by_shape_piechart <- function(trips_table, shape_table, crs) { } -#' Bar Chart with tripType on x-axis and travelled distance on y-axis -#' XXXX -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' travelled distance of each tripType related to the shapeTable +#' Bar chart with trip type on x-axis and traveled distance on y-axis #' +#' Takes the data frame output_trips (from \link{read_output_trips()}) +#' to plot a bar chart of the traveled distance of each trip type (originating, destinating, inside, outside) +#' as identified with a shape file of the project area. #' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' -#' @return Bar Chart plot of distance traveled by spatial type +#' @param tripsTable tibble of output_trips (from read_output_trips()) +#' @param shapeTable sf object(data.frame with geometries), can be created using st_read() +#' @param crs numeric representation of the EPSG code or proj4string for the corresponding coordinate system +#' of the trip coordinates, can be found in network file from output directory of MATSim simulation +#' @return Bar chart plot of the distance traveled by trip type #' #' @export plot_distance_by_spatialcat_barchart <- function(trips_table, shape_table, crs, euclidian = FALSE) { @@ -2680,14 +2678,14 @@ plot_distance_by_spatialcat_barchart <- function(trips_table, shape_table, crs, fig return(fig) } -#' Line plot with departure time on x-axis and number of trips on y-axis +#' Line plot with departure time on x-axis and number of trips on y-axis #' -#' Takes data frame trips_output (from \link{readTripsTable()}), +#' Takes the data frame output_trips (from \link{read_output_trips()}), #' to create a line plot of the number of trips for a specific departure time by main_mode #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param tripsTable tibble of trips_output (from readTripsTable()) +#' @param tripsTable tibble of output_trips (from read_output_trips()) #' @param unite.modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) @@ -2721,15 +2719,14 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, } -#' Deprecated function(s) in the matsimr package -#' XXXX -#' \strong{plot_arrtime_by_act} - Takes Table trips_output (from readTripsTable()), -#' to make line plot with with values that represent -#' count of destination activities for a specific arrival time -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Line chart of the arrival time by destination activity +#' XXXX function still needs to be updated? +#' Takes the data frame output_trips (from \link{read_output_trips()}), +#' to create a line plot of the with the arrival times on the x-axis and the count for each destination activity on the y-axis +#' Using the parameter unite.activities, specific activities can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param trips_table tibble of trips_output (from readTripsTable()) +#' @param trips_table tibble of output_trips (from read_output_trips()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in plot #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored @@ -2771,15 +2768,15 @@ plot_arrtime_by_act <- function(trips_table, unite_activities = character(0), un } #' Deprecated function(s) in the matsimr package -#' XXXX -#' \strong{plotDepartureTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), +#' XXXX function still needs to be updated? +#' \strong{plotDepartureTimesPerTripPurpose} - Takes Table output_trips (from read_output_trips()), #' to make line plot with with values that represent #' count of destination activities for a specific arrival time #' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') #' #' @rdname matsimr-deprecated #' -#' @param tripsTable tibble of trips_output (from readTripsTable()) +#' @param tripsTable tibble of output_trips (from read_output_trips()) #' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in plot #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored @@ -2822,14 +2819,14 @@ plot_deptime_by_act <- function(trips_table, unite_activities = character(0), un #' Bar chart comparing distance traveled on x-axis and number of trips on y-axis for two different runs -#' Takes two data frames (from \link{readTripsTable()}), categorizes the traveled distances into pre-defined bins +#' Takes two data frames (from \link{read_output_trips()}), categorizes the traveled distances into pre-defined bins #' and plots the difference in number of trips for each bin. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 -#' @param tripsTable2 tibble of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted +#' @param tripsTable1 tibble of output_trips (from read_output_trips()), number of trips of this table will be extracted from number of trips of tripsTable1 +#' @param tripsTable2 tibble of output_trips (from read_output_trips()), from number of trips of this table number of trips of tripsTable1 will be extracted #' @param unite.modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) @@ -2885,15 +2882,14 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, #' Plot bar chart of changes in modal split #' -#' Takes two data frames (from \link{readTripsTable()}), calculates the +#' Takes two data frames (from \link{read_output_trips()}), calculates the #' changes in mode shares and plots them as a bar chart #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()) -#' @param tripsTable2 tibble of trips_output (from readTripsTable()) -#'@param unite.modes vector of character strings, +#' @param tripsTable1 tibble of output_trips (from read_output_trips()) +#' @param tripsTable2 tibble of output_trips (from read_output_trips()) +#' @param unite.modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) #' @param united.name character string, specifies the name of the united mode @@ -2928,12 +2924,12 @@ plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, #' Plot alluvial/sankey diagram of transport mode changes #' -#' Takes two data frames (from \link{readTripsTable()}) and compares the mode choice for each agent and summarizes the results, showing the modal shift. +#' Takes two data frames (from \link{read_output_trips()}), compares the mode choice for each agent and summarizes the results, showing the modal shift. #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' The parameter show.onlyChanges allows the visualization of only the mode shift (excluding the trips that do not change mode). Standard value is FALSE. #' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()) -#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#' @param tripsTable1 tibble of output_trips (from read_output_trips()) +#' @param tripsTable2 tibble of output_trips (from read_output_trips()) #' @param show.onlyChanges boolean, if it is set to TRUE the sankey diagram only shows the mode shift #' @param unite.modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), @@ -3013,21 +3009,20 @@ plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, return(fig) } -#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis +#' Comparison bar chart with main_mode on x-axis and average travel/wait time on y-axis #' -#' Takes the data frame trips_output (from \link{readTripsTable()}), -#' to plot a bar chart of the traveling/waiting time +#' Takes two data frames (from \link{read_output_trips()}) to plot a bar chart of the travel/wait time for each mode. #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()) -#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#' @param tripsTable1 tibble of output_trips (from read_output_trips()) +#' @param tripsTable2 tibble of output_trips (from read_output_trips()) #' @param unite.modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) #' @param united.name character string, specifies the name of the united mode #' -#' @return Bar Chart plot of average time spent on travel/wait +#' @return Bar chart plot of average travel/wait time #' #' @export plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_table2, @@ -3081,20 +3076,19 @@ plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_ } -#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis -#' XXXX -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' time spent on traveling/waiting -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Comparison bar chart with trip type on x-axis and count on y-axis #' +#' Takes two data frames (from \link{read_output_trips()}) to plot a bar chart comparing the number of each trip type (originating, destinating, inside, outside). +#' The shape file is used to categorize the trips. #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' -#' @return Bar Chart plot of average time spent on travel/wait +#' @param tripsTable1 tibble of output_trips (from read_output_trips()) +#' @param tripsTable2 tibble of output_trips (from read_output_trips()) +#' @param shapeTable sf object(data.frame with geometries), can be created using st_read() +#' @param crs numeric representation of the EPSG code or proj4string for the corresponding coordinate system +#' of the trip coordinates, can be found in network file from output directory of MATSim simulation +#' +#' @return Bar chart comparing number of each trip type for two runs #' #' @export plot_compare_count_by_spatialcat_barchart <- function(trips_table1,trips_table2, shape_table ,crs,dump.output.to = matsimDumpOutputDirectory) { @@ -3120,13 +3114,13 @@ plot_compare_count_by_spatialcat_barchart <- function(trips_table1,trips_table2, #' Bar Chart comparing two runs with main_mode on x-axis and average travel/wait time on y-axis #' -#' Takes two data frames (from \link{readTripsTable()}), +#' Takes two data frames (from \link{read_output_trips()}), #' to plot a comparison bar chart of travel and wait times. #' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') #' #' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()) -#' @param tripsTable2 tibble of trips_output (from readTripsTable()) +#' @param tripsTable1 tibble of output_trips (from read_output_trips()) +#' @param tripsTable2 tibble of output_trips (from read_output_trips()) #' @param unite.modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) @@ -3190,14 +3184,13 @@ plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, ###### Mapping ###### -#' Plots start and end coordinates of the given trips table on an osm map -#' XXXX -#' @param table tibble of trips_output (from readTripsTable()) -#' +#' Plots start and end coordinates of a given output_trips table onto an osm map +#' XXXX functions uses parameter shape_table? +#' @param trips_table tibble of output_trips (from read_output_trips())#' #' #' @param crs numeric representation of the EPSG code or proj4string for the corresponding coordinate system of the trip coordinates, can be found in network file from output directory of MATSim simulation #' -#' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot +#' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE creates image with ggplot #' #' #' @return plot with trips @@ -3343,18 +3336,13 @@ plot_map_trips <- function(trips_table, crs,optimized = FALSE, } -#' Plots every type of trips(inside, outside, origin and destinating) on map -#' XXXX -#' -#' -#' @param table tibble of trips_output (from readTripsTable()) -#' -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) -#' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation -#' -#' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot +#' Plots all trips categorized by trip type (inside, outside, origin and destinating) on a map #' +#' @param table tibble of output_trips (from read_output_trips()) +#' @param shapeTable sf object(data.frame with geometries), can be created using st_read() +#' @param crs numeric representation of the EPSG code or proj4string for the corresponding coordinate system +#' of the trip coordinates, can be found in network file from output directory of MATSim simulation +#' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE creates image with ggplot #' @return plot that contains every trip with defined trip type #' #' @export @@ -3582,7 +3570,17 @@ plot_map_trips_by_spatialcat <- function(trips_table, shape_table, } #####Processing##### -#' XXXX +#' Renames modes in the column main_mode +#' +#' Changes the name of modes in the column main_mode to a new name called united.name. +#' E.g. "drtNorth" and "drtSouth" can be renamed to "drt" allowing them to be analyzed together. +#' +#' @param trips_table tibble of output_trips (from read_output_trips()) +#' @param unite.modes vector of character strings, +#' changes names of chosen modes in the column main_mode to a new chosen name +#' @param united.name character string, specifies the name of the united mode +#' +#' @return trips_table with adjused mode names #' @export process_rename_mainmodes<-function(trips_table, unite.modes = character(0), united.name = "united"){ @@ -3594,6 +3592,7 @@ process_rename_mainmodes<-function(trips_table, return(trips_table) } +#' XXXX #' @export process_rename_category<-function(trips_table, unite_template= character(0), united_name = "united",column = "main_mode"){ @@ -3604,6 +3603,14 @@ process_rename_category<-function(trips_table, return(trips_table) } +#' Calculates the count or percentage for each mode +#' +#' Calculates the count or percentage for each mode in the column main_mode +#' +#' @param trips_table tibble of output_trips (from read_output_trips()) +#' @param percentage boolean, standard value FALSE (calculates the count) +#' +#' @return tibble including the count or percentage #' @export process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ @@ -3615,6 +3622,12 @@ process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ return(trips_table_count) } +#' Calculates the average distance for each mode +#' +#' @param trips_table tibble of output_trips (from read_output_trips()) +#' @param euclidean boolean, specifies if euclidean or traveled distance should be used +#' +#' @return a tibble of main modes and their average distance #' @export process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ @@ -3625,7 +3638,15 @@ process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ return(trips_table) } +#' Calculates the average travel and wait time +#' XXXX minute_ but hourS and secondS? +#' +#' @param trips_table tibble of output_trips (from read_output_trips()) +#' @param time_format standard value is "minute", can also be "hours" or "seconds" +#' +#' @return tibble with main modes and their average wait and travel time #' @export + process_get_travelwaittime_by_mainmode<-function(trips_table, time_format = "minute"){#also could be hours/seconds @@ -3643,15 +3664,16 @@ process_get_travelwaittime_by_mainmode<-function(trips_table, } -#' Adds additional \strong{dist_cat} column representing category of distance traveled based on \strong{distances_array} parameter. +#' Adds additional \strong{dist_cat} column based on the \strong{distances_array} parameter #' -#' Categorize column of distances based on \strong{distances_array}, each dist_cat receives relational segment from array.\cr -#' For example trip distance traveled is 1500, and distances array is (1000,2000), then this category is "1000-2000". +#' Categorizes each trip into a distance bin based on traveled distance. +#' E.g. distance traveled is 1500, distances array is (1000,2000), then the category is "1000-2000". #' -#' @param trips_table tibble of trips_output (from \link{read_output_trips}) -#' -#' @param distances_array numeric vector, represents segments for distance categories ordered (in meters) +#' @param trips_table tibble of output_trips (from \link{read_output_trips})#' +#' @param distances_array numeric vector, represents segments for distance categories ordered (in meters), +#' standard value: c(1000,2000,5000,10000,20000,50000,100000) #' +#' @return trips table with added the added column dist_cat #' @export process_append_distcat <- function(trips_table,distances_array = c(1000,2000,5000,10000,20000,50000,100000)){ @@ -3677,16 +3699,16 @@ process_append_distcat <- function(trips_table,distances_array = c(1000,2000,500 } #' Converts time column specified in \strong{time_column} to numeric representation of minutes, hours or seconds +#' XXXX here minute, hour and second don't have an s? +#' Default output_trips table time columns(\strong{dep_time}, \strong{trav_time}, \strong{wait_time}) are in 'hms' format. +#' To convert this type to numeric, specify \strong{time_column} to be converted, +#' and the unit \strong{time_format}. Acceptable units are "hour", "minute" and "second". #' -#' Default output_trips table time columns(\strong{dep_time}, \strong{trav_time}, \strong{wait_time}) are in 'hms' format, -#' that isn't convenient for use in some cases. To convert this type to numeric with different, specify \strong{time_column} to be converted, -#' and \strong{time_format} which will represent time(takes "hour", "minute", "second") -#' -#' @param trips_table tibble of trips_output (from \link{read_output_trips}) +#' @param trips_table tibble of output_trips (from \link{read_output_trips}) #' -#' @param time_format char, defines time format to be used(takes "hour", "minute", "second") +#' @param time_format char, defines time unit to be used ("hour", "minute", "second") #' -#' @param time_column char, name of the column from table to be converted(takes \strong{dep_time}, \strong{trav_time}, \strong{wait_time}) +#' @param time_column char, name of the column from table to be converted (\strong{dep_time}, \strong{trav_time}, \strong{wait_time}) #' #' @return tibble, containing column with specified time_format #' @@ -3715,7 +3737,7 @@ process_convert_time <- function(trips_table,time_format = "hour",time_column = #' XXXX finish when code revision is done -#' Filters trips_table(from ,\link{readTripsTable}) depending by location using a shapefile +#' Filters trips_table(from ,\link{read_output_trips}) depending by location using a shapefile #' #' Uses trips_table and an sf object (can be created using the function st_read()), #' transforms both objects to match a mutual coordinate system (crs) @@ -3725,7 +3747,7 @@ process_convert_time <- function(trips_table,time_format = "hour",time_column = #' if spatial_type="destinating" return table that contains trips which ends in shape and starts out of the shape\cr #' if spatial_type="outside" return table that contains trips which starts and ends our of the given shape #' -#' @param trips_table tibble of trips_output (from readTripsTable()) +#' @param trips_table tibble of output_trips (from read_output_trips()) #' #' @param shape_table sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' @@ -3809,7 +3831,7 @@ process_filter_by_shape <- function(trips_table, #' category representing trips which \strong{destinating} in the shape #' category representing trips which \strong{outside} of the given shape #' -#' @param trips_table tibble of trips_output (from readTripsTable()) +#' @param trips_table tibble of output_trips (from read_output_trips()) #' #' @param shape_table sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' @@ -3909,7 +3931,7 @@ process_get_crs_from_config <- function(config_path) { #' or for simwrapper (origin and destination as columns) #' #' -#' @param tripsTable tibble of trips_output (from \link{readTripsTable}) +#' @param tripsTable tibble of output_trips (from \link{read_output_trips}) #' #' @param shapePath string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file) #' @@ -3939,7 +3961,7 @@ process_get_od_matrix<- function(trips_table, #if tripstable given as folder/file if(sum(class(trips_table) %in% c("tbl_df","tbl","data.frame"))<1){ - tripsTable <- readTripsTable(trips_table) + tripsTable <- read_output_trips(trips_table) } sfTable <- transformToSf(trips_table,crs,geometry.type = st_point()) @@ -4022,15 +4044,15 @@ process_get_od_matrix<- function(trips_table, -#' Transforms the data frame trips_output (from \links{readTripsTable}) from tibble to sf (table with geometry features) +#' Transforms the data frame output_trips (from \links{read_output_trips}) from tibble to sf (table with geometry features) #' -#' Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features.\cr +#' Transforms the data frame output_trips (from \links{read_output_trips}) into an sf object using start_x, end_x, start_y, end_y as geometry features.\cr #' If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format),\cr #' if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt.\cr #' Added column/columns are projected to given CRS (coordinate reference system).\cr #' The columns start_x, end_x, start_y, end_y are deleted from the resulting data frame. #' -#' @param table tibble trips_output (from readTripsTable()) +#' @param table tibble output_trips (from read_output_trips()) #' #' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file #' From 6207f3dd29171653ddcb5df6c9ed969a9532871b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Wed, 12 Jul 2023 15:11:28 +0200 Subject: [PATCH 55/87] WIP documentation, added comments where clarification is needed --- R/output_trips.R | 58 +++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index ca493ea..188b029 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -3737,25 +3737,24 @@ process_convert_time <- function(trips_table,time_format = "hour",time_column = #' XXXX finish when code revision is done -#' Filters trips_table(from ,\link{read_output_trips}) depending by location using a shapefile +#' Filters data frame (from \link{read_output_trips}) by location using a shapefile #' -#' Uses trips_table and an sf object (can be created using the function st_read()), +#' Uses output_trips and an sf object (can be created using the function st_read()), #' transforms both objects to match a mutual coordinate system (crs) -#' and filters the trips from trips_table depending on spatial_type flags:\cr -#' if spatial_type="inside" return table that contains trips inside given shape\cr -#' if spatial_type="originating" return table that contains trips which starts in shape and ends out of the shape\cr -#' if spatial_type="destinating" return table that contains trips which ends in shape and starts out of the shape\cr -#' if spatial_type="outside" return table that contains trips which starts and ends our of the given shape +#' and filters the trips from output_trips depending on their spatial type flags:\cr +#' if spatial_type="inside" returns a table that contains trips inside given shape\cr +#' if spatial_type="originating" returns a table that contains trips which start inside the shape and end outside of the shape\cr +#' if spatial_type="destinating" returns a table that contains trips which end inside shape and start outside of the shape\cr +#' if spatial_type="outside" returns a table that contains trips which start and end outside of the given shape #' #' @param trips_table tibble of output_trips (from read_output_trips()) #' -#' @param shape_table sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) -#' -#' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file -#' -#' @param spatial_type bool, defines trips to conclude (see Description) +#' @param shapeTable sf object(data.frame with geometries), can be created using st_read() +#' @param crs numeric representation of the EPSG code or proj4string for the corresponding coordinate system +#' of the trip coordinates, can be found in network file from output directory of MATSim simulation +#' @param spatial_type bool, defines trips to conclude (see description) #' -#' @return tibble, with filtered trips depending on shapeTable and special flags (see Description) +#' @return tibble, with filtered trips depending on shapeTable and spatial types (see description) #' #' @export process_filter_by_shape <- function(trips_table, @@ -3820,24 +3819,24 @@ process_filter_by_shape <- function(trips_table, return(trips_table[cont_union, ]) } -#' Appending spatial category as additional column to output_trips tibble -#' XXXX -#' Takes trips_table and shape_table(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +#' Appends an additional column with the trip type to output_trips +#' +#' Using a shape_file of the project area an additional column is created, categorizing all trips into the following categories. +#' inside: trips that start and end inside the given shape +#' originating: trips that start inside the shape and end outside of the shape +#' destinating: trips that end inside the shape and start outside of the shape +#' outside: trips that start and end outside of the shape +#' +#'XXXX Can this be deleted? Is this relevant here? #' Please be aware that this \link{process_filter_by_shape} currently only works, when one geometry is loaded.) -#' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -#' and adds to the output_trips from table spatial category depending on postition related to shape file: -#' category representing trips \strong{inside} of the given shape -#' category representing trips which \strong{originating} in the shape -#' category representing trips which \strong{destinating} in the shape -#' category representing trips which \strong{outside} of the given shape #' #' @param trips_table tibble of output_trips (from read_output_trips()) #' -#' @param shape_table sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) -#' -#' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' @param shapeTable sf object(data.frame with geometries), can be created using st_read() +#' @param crs numeric representation of the EPSG code or proj4string for the corresponding coordinate system +#' of the trip coordinates, can be found in network file from output directory of MATSim simulation #' -#' @return tibble, with additional spatial column related to given shape +#' @return tibble, with additional column containing the trip type #' #' @export process_append_spatialcat <- function(trips_table, @@ -3888,13 +3887,12 @@ process_append_spatialcat <- function(trips_table, return(trips_table) } -#' Reads the coordinate reference system from an MATSim output directory -#' (output_config.xml) +#' Reads the coordinate reference system from a MATSim output directory (output_config.xml) #' #' @param config_path specifies path to configuration file #' #' -#' @return code of coordinate reference system +#' @return EPSG code of coordinate reference system #' #' @export process_get_crs_from_config <- function(config_path) { @@ -4044,7 +4042,7 @@ process_get_od_matrix<- function(trips_table, -#' Transforms the data frame output_trips (from \links{read_output_trips}) from tibble to sf (table with geometry features) +#' Transforms output_trips from tibble to sf (table with geometry features) #' #' Transforms the data frame output_trips (from \links{read_output_trips}) into an sf object using start_x, end_x, start_y, end_y as geometry features.\cr #' If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format),\cr From dc6cabe3614c5dec154aaac45f5d3aa5446bf12e Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 12 Jul 2023 15:40:38 +0200 Subject: [PATCH 56/87] added first introduction vignette --- .gitignore | 1 + DESCRIPTION | 7 +++++-- R/personsOutput.R | 2 +- vignettes/.gitignore | 2 ++ vignettes/Introduction.Rmd | 19 +++++++++++++++++++ 5 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 vignettes/.gitignore create mode 100644 vignettes/Introduction.Rmd diff --git a/.gitignore b/.gitignore index f564ed6..2fc2883 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ kelheim/ test/ dashboard_test/ .sentinel* +inst/doc diff --git a/DESCRIPTION b/DESCRIPTION index 35f65ff..3c2bccc 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -11,10 +11,10 @@ Description: MATSim support package for R of the Python matsim-tools package, and thus supports reading standard MATSim networks and soon, plans and events as well. . - Developed with support from the Technische Universität Berlin's + Developed with support from the Technische Universität Berlin's VSP Transport Planning and Transport Telematics department. . - This project is under ongoing development and submissions are welcome! + This project is under ongoing development and submissions are welcome! License: GPL (>= 3) Encoding: UTF-8 Imports: @@ -42,5 +42,8 @@ URL: https://github.com/matsim-vsp/matsim-r BugReports: https://github.com/matsim-vsp/matsim-r/issues RoxygenNote: 7.2.3 Suggests: + knitr, + rmarkdown, testthat (>= 3.0.0) Config/testthat/edition: 3 +VignetteBuilder: knitr diff --git a/R/personsOutput.R b/R/personsOutput.R index 539595e..3bb6adc 100644 --- a/R/personsOutput.R +++ b/R/personsOutput.R @@ -63,7 +63,7 @@ readPersonsTable <- function(input_path = ".", n_max = Inf) { #' #' @export boxplotScoreDifferences <- function(personTibble_base, personTibble_policy){ - s + joined <- inner_join(personTibble_base, personTibble_policy, by = "person", suffix = c("_base", "_policy")) %>% select(person, executed_score_base, diff --git a/vignettes/.gitignore b/vignettes/.gitignore new file mode 100644 index 0000000..097b241 --- /dev/null +++ b/vignettes/.gitignore @@ -0,0 +1,2 @@ +*.html +*.R diff --git a/vignettes/Introduction.Rmd b/vignettes/Introduction.Rmd new file mode 100644 index 0000000..ad1f401 --- /dev/null +++ b/vignettes/Introduction.Rmd @@ -0,0 +1,19 @@ +--- +title: "Introduction for Matsim R Library" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Introduction for Matsim R Library} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r setup} +library(matsim) +``` From 4d8b9e7022772029334e1559f259f982d24228a2 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Wed, 12 Jul 2023 16:06:57 +0200 Subject: [PATCH 57/87] added inst/extdata folder to store files for vignette documentation --- inst/extdata/dataflow.png | Bin 0 -> 46057 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 inst/extdata/dataflow.png diff --git a/inst/extdata/dataflow.png b/inst/extdata/dataflow.png new file mode 100644 index 0000000000000000000000000000000000000000..02f8cf1b0bc987a87c913eeaf87a01546da1f244 GIT binary patch literal 46057 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 E0Of0IbpQYW literal 0 HcmV?d00001 From 525d3fcb68f77283da913bb9fd65efbe4c7dd7e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Thu, 13 Jul 2023 10:08:50 +0200 Subject: [PATCH 58/87] WIP documentation - fixed some typos and reran devtools::document --- R/output_trips.R | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 188b029..919c8c5 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2855,10 +2855,10 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, #Get category count difference - table_with_сounts1 = distribution1 %>% count(main_mode,dist_cat) - table_with_сounts2 = distribution2 %>% count(main_mode,dist_cat) + table_with_counts1 = distribution1 %>% count(main_mode,dist_cat) + table_with_counts2 = distribution2 %>% count(main_mode,dist_cat) - joined <- full_join(table_with_сounts1, table_with_сounts2, by = c("main_mode", "dist_cat")) + joined <- full_join(table_with_counts1, table_with_counts2, by = c("main_mode", "dist_cat")) result <- joined %>% replace_na( list(n.x = 0, n.y = 0) ) %>% @@ -3669,7 +3669,7 @@ process_get_travelwaittime_by_mainmode<-function(trips_table, #' Categorizes each trip into a distance bin based on traveled distance. #' E.g. distance traveled is 1500, distances array is (1000,2000), then the category is "1000-2000". #' -#' @param trips_table tibble of output_trips (from \link{read_output_trips})#' +#' @param trips_table tibble of output_trips (from \link{read_output_trips}) #' @param distances_array numeric vector, represents segments for distance categories ordered (in meters), #' standard value: c(1000,2000,5000,10000,20000,50000,100000) #' From 1c9b4dcef8063ecca5672f3e37bd01fadc85d180 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 13 Jul 2023 15:45:21 +0200 Subject: [PATCH 59/87] skeleton for introduction, replace code in there --- vignettes/Introduction.Rmd | 98 +++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) diff --git a/vignettes/Introduction.Rmd b/vignettes/Introduction.Rmd index ad1f401..d95a7a2 100644 --- a/vignettes/Introduction.Rmd +++ b/vignettes/Introduction.Rmd @@ -2,7 +2,7 @@ title: "Introduction for Matsim R Library" output: rmarkdown::html_vignette vignette: > - %\VignetteIndexEntry{Introduction for Matsim R Library} + %\VignetteIndexEntry{Introduction for Matsim R Library: analyzing transport simulations} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- @@ -14,6 +14,100 @@ knitr::opts_chunk$set( ) ``` -```{r setup} +```{r setup, warning = FALSE} library(matsim) ``` + +### Introduction +Welcome to the matsim package! This vignette will guide you through the process of creating plots using the functions provided by our library. matsim is a powerful R package designed for data process and visualization, with providing a wide range of functions to create high-quality and adjustable plots from processed data. + +#### Overall concept + +The purpose of this package is to provide a comprehensive set of tools and functions for efficiently analyzing output of matsim simulations. The package primarily operates on output data stored in CSV files, specifically those named with the suffix "output_trips", "legs","persons". By adhering to this naming convention, the package offers streamlined functionality for reading, processing, plotting, and utilizing special features via YAML files used in Simwrapper(in development). + +The package is organized into four main subcategories, each serving a specific purpose: + +**Reading Functions**: These functions begin with the prefix "read_" and are designed to read and import the simulation output stored in CSV files. By leveraging these functions, users can easily load the necessary data into their R environment for further analysis. + +**Processing Functions**: Functions with the prefix "process_" form the core of the package's data manipulation capabilities. Users can apply a variety of transformations and calculations to the loaded output_trips data, allowing for advanced processing and analysis tailored to their specific requirements. Additionally, the processing functionality extends beyond traditional tabular data, as it supports spatial input/output, enabling users to analyze and manipulate spatially referenced transport simulation data. + +**Plotting Functions**: With the prefix "plot_," the plotting functions enable users to create insightful visualizations based on the processed output data. These functions offer a range of plotting options, empowering users to explore patterns, trends, and relationships within the transport simulation results. The plotting functions encompass two additional subcategories, namely mapping and comparing. Within the mapping subcategory, users can generate visualizations that overlay simulation results onto geographical maps, providing insights into spatial patterns and distributions. The comparing subcategory offers tools to compare different simulation outputs, facilitating analysis and understanding of variations between scenarios or datasets. + +**Simwrapper**: The simwrapper is a specialized block within the package that facilitates plotting using YAML files in Simwrapper. This feature allows users to define complex plots and visualizations in YAML format, providing a convenient and efficient way to generate custom visual representations of their simulation data. + +By following this design philosophy and offering a well-structured collection of functions, matsim R package aims to simplify the analysis of transport simulations. It provides users with an intuitive workflow, from reading and processing the simulation output to generating informative plots and leveraging the power of YAML-based configurations. + +![Data flow and concept of matsim r package](../inst/extdata/dataflow.png) + + +#### Installation +Matsim is not still available at CRAN, so to install matsim we use github, you can use the following code: + +```{r install master,eval=FALSE} +devtools::install_github("matsim-vsp/matsim-r") +``` +However if you want to have some specific branch in your Rstudio you can specify this branch in the code: +```{r install ref,eval=FALSE} +devtools::install_github("matsim-vsp/matsim-r", ref = "{name of the branch}") +``` +#### Loading the package +Once installed, you can load the matsim package using the library() function: +```{r,eval=FALSE} +library(matsim) +``` + + + +#### Loading Data + +The first step in analyzing your transport simulations is to load the output data into your R environment. matsim provides convenient functions with the "read_" prefix for this purpose. Let's take a look at how you can load your simulation output stored in a CSV file: + +```{r reading, warning=FALSE,eval = FALSE} +# Specify the file path to your simulation output. +# It can be directory path, or direct path to file +output_file <- "path/to/your/output_trips.csv" + +# Use the read_csv_trips() function to read the simulation data +trips_data <- read_output_trips(output_file) +``` + +You can now proceed to explore and analyze the loaded data. + + +#### Data Processing + +Matsim offers a range of processing functions, prefixed with "process_", to manipulate and transform your simulation data. These functions allow you to perform various operations, such as filtering, aggregating, and calculating additional metrics. Let's see an example of applying a transformation to our loaded data: + +```{r processing, warning=FALSE,eval=FALSE} +# Filter the trips data to include only weekday trips +#weekday_trips <- process_filter_by_shape(trips_data) + +# Calculate the average trip duration +#average_duration <- process_calculate_average_duration(weekday_trips) +``` + +Feel free to explore the different processing functions available in the package to suit your specific analysis requirements. + +#### Plotting + +Visualizing your simulation data is crucial for gaining insights and effectively communicating your findings. your_package_name provides a wide range of plotting functions to help you create informative visualizations. Let's create a scatter plot to visualize the relationship between trip distance and trip duration: + + +```{r plotting, eval = FALSE} +# Create a scatter plot of trip distance against trip duration +#plot_scatter(trips_data, x = "distance", y = "duration") +``` + +ou can customize the plot appearance and explore other plot types, such as line plots, bar charts, and spatial maps, using the various plotting functions provided by matsim. + + +#### Advanced Features (still in development) + +In addition to the fundamental functionalities discussed above, your_package_name offers advanced features to enhance your analysis. For example, you can utilize YAML files in the simwrapper block to define complex plots and visualizations. This allows you to create sophisticated and customized outputs to meet your specific requirements. + + +#### Conclusion + +In this vignette, we introduced you to the matsim package, designed specifically for analyzing transport simulations. We hope that you'll have great experience using this library, and we are glad to receive feedback based on your use of package on **some mail/github ** + +For more details and specific usage examples, refer to the package documentation and other vignettes available({list of vignettes}). Happy analyzing with matsim! From 04597c3f37b49dec9d8f9a5834dd1f3d7cc30f68 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Mon, 17 Jul 2023 15:45:57 +0200 Subject: [PATCH 60/87] revisited documentation --- NAMESPACE | 1 - R/network.R | 10 +- R/output_trips.R | 548 ++++++++++-------- R/personsOutput.R | 7 +- man/boxplotScoreDifferences.Rd | 21 + man/loadNetwork.Rd | 24 - man/matsimr-deprecated.Rd | 87 +-- man/plot_arrtime_by_act.Rd | 25 +- ...ot_compare_count_by_spatialcat_barchart.Rd | 31 +- ...ot_compare_distcat_by_mainmode_barchart.Rd | 24 +- man/plot_compare_mainmode_barchart.Rd | 20 +- man/plot_compare_mainmode_sankey.Rd | 24 +- ...plot_compare_travelwaittime_by_mainmode.Rd | 20 +- ...are_travelwaittime_by_mainmode_barchart.Rd | 20 +- man/plot_deptime_by_act.Rd | 26 + man/plot_distance_by_mainmode_barchart.Rd | 16 +- man/plot_distance_by_spatialcat_barchart.Rd | 12 +- man/plot_distcat_by_mainmode_barchart.Rd | 20 +- man/plot_mainmode_barchart.Rd | 17 +- man/plot_mainmode_piechart.Rd | 11 +- man/plot_map_trips.Rd | 11 +- man/plot_map_trips_by_spatialcat.Rd | 12 +- man/plot_spatialtype_by_shape_piechart.Rd | 6 +- man/plot_travelwaittime_mean_barchart.Rd | 13 +- ...count_by_deptime_and_mainmode_linechart.Rd | 26 +- man/process_append_spatialcat.Rd | 2 +- man/process_convert_table_to_sf.Rd | 2 +- man/process_filter_by_shape.Rd | 2 +- man/process_get_mainmode_distribution.Rd | 24 + man/process_get_od_matrix.Rd | 8 +- man/process_get_travdistance_distribution.Rd | 19 + man/process_get_travelwaittime_by_mainmode.Rd | 19 + man/process_rename_category.Rd | 32 + man/process_rename_mainmodes.Rd | 22 +- 34 files changed, 681 insertions(+), 481 deletions(-) create mode 100644 man/boxplotScoreDifferences.Rd delete mode 100644 man/loadNetwork.Rd create mode 100644 man/plot_deptime_by_act.Rd create mode 100644 man/process_get_mainmode_distribution.Rd create mode 100644 man/process_get_travdistance_distribution.Rd create mode 100644 man/process_get_travelwaittime_by_mainmode.Rd create mode 100644 man/process_rename_category.Rd diff --git a/NAMESPACE b/NAMESPACE index f5f665f..28144a5 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -12,7 +12,6 @@ export(deriveODMatrix) export(filterByRegion) export(generateXYHexagonYaml) export(getCrsFromConfig) -export(loadNetwork) export(mergeCountsAndLinks) export(plotActivityEndTimes) export(plotArrivalTimesPerTripPurpose) diff --git a/R/network.R b/R/network.R index 53a556f..086e063 100644 --- a/R/network.R +++ b/R/network.R @@ -175,19 +175,19 @@ read_network <- function(filename) { #' Load MATSim network into memory #' -#' Loads a MATSim XML network file, creating a nodes tibble and a links tibble. +#' \strong{loadNetwork} - Loads a MATSim XML network file, creating a nodes tibble and a links tibble. #' Any node and link attribute records in the network are stored as -#' additional columns in the respective node and link tibbles. -#' +#' additional columns in the respective node and link tibbles.\cr #' The links table is automatically joined with the nodes table so that #' node x/y coordinates (and any other node attributes) are available on the #' links table without additional processing. #' +#' @rdname matsimr-deprecated +#' #' @param filename File to load. Can be XML or gzipped XML #' -#' @return "nodes" and "links" tibbles in a list object. +#' @return \strong{loadNetwork} - "nodes" and "links" tibbles in a list object. #' -#' @export loadNetwork <- function(filename) { .Deprecated("read_network") cat(filename, ": ") diff --git a/R/output_trips.R b/R/output_trips.R index a33b081..35f007f 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -17,7 +17,7 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' These functions are provided for compatibility with older version of #' the matsimr package. They may eventually be completely #' removed.\cr\cr -#' \strong{plotModalSplitPieChart} - Takes Table trips_output (from readTripsTable()), +#' \strong{plotModalSplitPieChart} - Takes Table trips_output (from \link{read_output_trips()}), #' to plot pie chart with with values that represent #' percentage of using transport modes from trips #' @@ -25,9 +25,9 @@ dashboard_file <- "/dashboard-1-trips.yaml" #' @name matsimr-deprecated #' #' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart +#' @param tripsTable tible of trips_output (from \link{read_output_trips()}) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns +#' @param united_name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' @@ -158,15 +158,15 @@ plotModalSplitPieChart <- function(tripsTable, } #' Deprecated function(s) in the matsimr package #' -#' \strong{plotModalSplitBarChart} - Takes Table trips_output (from readTripsTable()), +#' \strong{plotModalSplitBarChart} - Takes Table trips_output (from \link{read_output_trips()}), #' to plot bar chart with with values that represent #' percentage of using transport modes from trips #' #' @rdname matsimr-deprecated #' #' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param tripsTable tible of trips_output (from \link{read_output_trips()}) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly @@ -284,18 +284,18 @@ readTripsTable <-function(input_path = ".", n_max = Inf) { #' Deprecated function(s) in the matsimr package #' #' -#' \strong{plotAverageTravelWait} - Takes Table trips_output (from readTripsTable()), +#' \strong{plotAverageTravelWait} - Takes Table trips_output (from \link{read_output_trips()}), #' to plot bar chart with with values that represent #' time spent on traveling/waiting #' Using parameters unite.columns, specific columns could be given, -#' to unite them in 1 mode with the name united.name(by default 'united') +#' to unite them in 1 mode with the name united_name(by default 'united') #' #' #' #' @rdname matsimr-deprecated #' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param tripsTable tible of trips_output (from \link{read_output_trips()}) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly @@ -396,18 +396,18 @@ compareAverageTravelWait <- function(tripsTable1,tripsTable2, unite.columns = ch #' Deprecated function(s) in the matsimr package #' -#' \strong{plotModalDistanceDistribution} - Takes Table trips_output (from readTripsTable()), +#' \strong{plotModalDistanceDistribution} - Takes Table trips_output (from \link{read_output_trips()}), #' to plot bar chart with with values that represent #' number of trips ~ distance travelled -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') #' #' #' @rdname matsimr-deprecated #' #' @name plotModalDistanceDistribution #' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param tripsTable tible of trips_output (from \link{read_output_trips()}) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly @@ -492,16 +492,16 @@ plotModalDistanceDistribution <- function(tripsTable, unite.columns = character( #' Deprecated function(s) in the matsimr package #' -#' \strong{compareModalDistanceDistribution} - Takes 2 Tables trips_output (from readTripsTable()), +#' \strong{compareModalDistanceDistribution} - Takes 2 Tables trips_output (from \link{read_output_trips()}), #' to plot bar chart with with values that represent #' difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') #' #' @rdname matsimr-deprecated #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 -#' @param tripsTable2 tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param tripsTable1 tible of trips_output (from \link{read_output_trips()}), number of trips of this table will be extracted from number of trips of tripsTable1 +#' @param tripsTable2 tible of trips_output (from \link{read_output_trips()}), from number of trips of this table number of trips of tripsTable1 will be extracted +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly @@ -569,14 +569,14 @@ compareModalDistanceDistribution <- function(tripsTable1,tripsTable2, unite.colu #' Deprecated function(s) in the matsimr package #' -#' \strong{plotTripDistanceByMode} - Takes Table trips_output (from readTripsTable()), +#' \strong{plotTripDistanceByMode} - Takes Table trips_output (from \link{read_output_trips()}), #' to plot bar chart with with values that represent #' average distance traveled ~ main mode used -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') #' #' @rdname matsimr-deprecated -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param tripsTable tible of trips_output (from \link{read_output_trips()}) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly @@ -624,15 +624,15 @@ plotTripDistanceByMode <- function(tripsTable, #' Deprecated function(s) in the matsimr package #' -#' \strong{plotTripCountByDepTime} - Takes Table trips_output (from readTripsTable()), +#' \strong{plotTripCountByDepTime} - Takes Table trips_output (from \link{read_output_trips()}), #' to make line plot with with values that represent #' count of trips for a specific departure time by main_mode -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') #' #' @rdname matsimr-deprecated #' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param tripsTable tible of trips_output (from \link{read_output_trips()}) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly @@ -698,15 +698,15 @@ plotTripCountByDepTime <- function(tripsTable, unite.columns = character(0), uni #' Deprecated function(s) in the matsimr package #' -#' \strong{plotActivityEndTimes} - Takes Table trips_output (from readTripsTable()), +#' \strong{plotActivityEndTimes} - Takes Table trips_output (from \link{read_output_trips()}), #' to make line plot with with values that represent the #' number of activities ending at a specific time. -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') #' #' @rdname matsimr-deprecated #' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param tripsTable tible of trips_output (from \link{read_output_trips()}) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly @@ -776,15 +776,15 @@ plotActivityEndTimes <- function(tripsTable, unite.columns = character(0), unite #' Deprecated function(s) in the matsimr package #' -#' \strong{plotArrivalTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), +#' \strong{plotArrivalTimesPerTripPurpose} - Takes Table trips_output (from \link{read_output_trips()}), #' to make line plot with with values that represent #' count of destination activities for a specific arrival time -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') #' #' @rdname matsimr-deprecated #' -#' @param tripsTable tibble of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param tripsTable tibble of trips_output (from \link{read_output_trips()}) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in plot #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly @@ -897,15 +897,15 @@ plotArrivalTimesPerTripPurpose <- function(tripsTable, unite.columns = character #' Deprecated function(s) in the matsimr package #' -#' \strong{plotDepartureTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), +#' \strong{plotDepartureTimesPerTripPurpose} - Takes Table trips_output (from \link{read_output_trips()}), #' to make line plot with with values that represent #' count of destination activities for a specific arrival time -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') #' #' @rdname matsimr-deprecated #' -#' @param tripsTable tibble of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param tripsTable tibble of trips_output (from \link{read_output_trips()}) +#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns #' @param united.name character string, if columns were united, you can specify name for the resulting column in plot #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored #' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly @@ -970,13 +970,13 @@ plotDepartureTimesPerTripPurpose <- function(tripsTable, unite.columns = charact #' Deprecated function(s) in the matsimr package #' -#' \strong{plotTripDistancedByType} - Takes Table trips_output (from readTripsTable()), +#' \strong{plotTripDistancedByType} - Takes Table trips_output (from \link{read_output_trips()}), #' to plot bar chart with with values that represent #' travelled distance of each tripType related to the shapeTable #' #' @rdname matsimr-deprecated #' -#' @param tripsTable tible of trips_output (from readTripsTable()) +#' @param tripsTable tible of trips_output (from \link{read_output_trips()}) #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored @@ -1016,15 +1016,15 @@ plotTripDistancedByType <- function(tripsTable,shapeTable,crs,dump.output.to = m #' Function calculates number of each transport mode used in #' first and second table, and draws plot that represent how #' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) -#' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") +#' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united_name is "united") #' Using parameter show.onlyChanges #' #' @rdname matsimr-deprecated #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) +#' @param tripsTable1 tible of trips_output (from \link{read_output_trips()}) +#' @param tripsTable2 tible of trips_output (from \link{read_output_trips()}) #' @param show.onlyChanges boolean, if it is set to TRUE => sankey diagram only contains changes on axes -#' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns #' @param united.name if columns were united, you can specify name for the resulting column in plot #' @param dump.output.to folder that saves and configures yaml for simwrapper. folder where png of plot is stored #' @@ -1086,12 +1086,12 @@ plotModalShiftSankey <- function(tripsTable1, tripsTable2, show.onlyChanges = FA #' Function calculates number of each transport mode used in #' first and second table, and draws plot that represent how #' distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) -#' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") +#' Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united_name is "united") #' Using parameter show.onlyChanges #' @rdname matsimr-deprecated -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns +#' @param tripsTable1 tible of trips_output (from \link{read_output_trips()}) +#' @param tripsTable2 tible of trips_output (from \link{read_output_trips()}) +#' @param unite.columns vector of character string, changes name of all transport modes in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns #' @param united.name if columns were united, you can specify name for the resulting column in plot #' @param dump.output.to folder that saves and configures yaml for simwrapper. folder where png of plot is stored #' @@ -1135,7 +1135,7 @@ plotModalShiftBar <- function(tripsTable1, tripsTable2, unite.columns = characte #' \cr result of filtering is plotted on map of shapeTable where green points are startpoints of trip and red points are endpoints of trip #' #' @rdname matsimr-deprecated -#' @param table tibble of trips_output (from readTripsTable()) +#' @param table tibble of trips_output (from \link{read_output_trips()}) #' #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' @@ -1285,7 +1285,7 @@ plotMapWithFilteredTrips <- function(table, shapeTable, crs, start.inshape = TRU #' #' \strong{plotMapWithTrips} - Plots start and end coordinates of the given trips table on an osm map #' @rdname matsimr-deprecated -#' @param table tibble of trips_output (from readTripsTable()) +#' @param table tibble of trips_output (from \link{read_output_trips()}) #' #' #' @param crs numeric representation of the EPSG code or proj4string for the corresponding coordinate system of the trip coordinates, can be found in network file from output directory of MATSim simulation @@ -1416,7 +1416,7 @@ plotMapWithTrips <- function(table, crs, optimized = FALSE) { #' #' @rdname matsimr-deprecated #' -#' @param table tibble of trips_output (from readTripsTable()) +#' @param table tibble of trips_output (from \link{read_output_trips()}) #' #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' @@ -1476,9 +1476,9 @@ plotTripTypesPieChart <- function(table, shapeTable, crs) { #' #' @rdname matsimr-deprecated #' -#' @param tripsTable1 tibble of trips_output (from readTripsTable(),f.e. base case) +#' @param tripsTable1 tibble of trips_output (from \link{read_output_trips()},f.e. base case) #' -#' @param tripsTable2 tibble of trips_output (from readTripsTable(),f.e. policy case) +#' @param tripsTable2 tibble of trips_output (from \link{read_output_trips()},f.e. policy case) #' #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' @@ -1538,7 +1538,7 @@ compareTripTypesBarChart <- function(tripsTable1,tripsTable2,shapeTable,crs,dump #' #' @rdname matsimr-deprecated #' -#' @param table tibble of trips_output (from readTripsTable()) +#' @param table tibble of trips_output (from \link{read_output_trips()}) #' #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' @@ -1964,7 +1964,7 @@ appendDistanceCategory <- function(tripsTable){ #' #' @rdname matsimr-deprecated #' -#' @param tripsTable tibble of trips_output (from readTripsTable()) +#' @param tripsTable tibble of trips_output (from \link{read_output_trips()}) #' #' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' @@ -2227,7 +2227,7 @@ getCrsFromConfig <- function(folder) { #' #' @rdname matsimr-deprecated #' -#' @param table tibble of trips_output (from readTripsTable()) +#' @param table tibble of trips_output (from \link{read_output_trips()}) #' #' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' @@ -2360,25 +2360,24 @@ read_output_trips <- function(input_path = ".", n_max = Inf) { #' to plot a pie chart of the modal split using the column main_mode #' #' The function automatically detects the modes plots a pie chart. -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') #' #' @param trips_table tibble of trips_output (from \link{readTripsTable}) -#' @param unite.modes vector of character strings, +#' @param unite_modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param united_name character string, specifies the name of the united mode #' #' @return pie chart plot of transport mode distribution, values given in percent #' #' @export plot_mainmode_piechart <- function(trips_table, - unite.modes = character(0), united.name = "united", - dump.output.to = matsimDumpOutputDirectory) { + unite_modes = character(0), united_name = "united") { # renaming/uniting of modes trips_table = process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) # processing # calculates the mode share and saves it as a tibble @@ -2398,33 +2397,33 @@ plot_mainmode_piechart <- function(trips_table, #' Plot the distribution of modes as a bar chart #' -#' Takes the data frame trips_output (from \link{readTripsTable()}) +#' Takes the data frame trips_output (from \link{read_output_trips()}) #' to plot a bar chart of the modal split using the column main_mode. #' #' The modal shares are given in percentages. #' -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') #' #' -#' @param trips_table tibble of trips_output (from \link{readTripsTable()}) -#' @param unite.modes vector of character strings, +#' @param trips_table tibble of trips_output (from \link{read_output_trips()}) +#' @param unite_modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param united_name character string, specifies the name of the united mode +#' @param percentage boolean, by default FALSE, sets if output is given in percentage #' #' @return Bar Chart plot of transport mode distribution, values given in percents #' #' @export plot_mainmode_barchart <- function(trips_table, - unite.modes = character(0), - united.name = "united", - dump.output.to = matsimDumpOutputDirectory, + unite_modes = character(0), + united_name = "united", percentage = FALSE) { # renaming/uniting of modes trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) # processing # calculates the mode share and saves it as a tibble trips_table_count <- process_get_mainmode_distribution(trips_table, @@ -2444,27 +2443,29 @@ plot_mainmode_barchart <- function(trips_table, #' #' Takes the data frame trips_output (from \links{readTripsTable()}), #' to plot a bar chart of travel and wait times. -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') #' #' #' @param trips_table tibble of trips_output (from \links{readTripsTable()}) -#' @param unite.modes vector of character strings, +#' @param unite_modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param united_name character string, specifies the name of the united mode +#' @param time_format A character string indicating the desired time format for the output. +#' The options are "minute", "hour", or "second". The default is "minute". #' #' @return Bar Chart plot of average time spent on travel/wait #' #' @export plot_travelwaittime_mean_barchart <- function(trips_table, - unite.modes = character(0), - united.name = "united", + unite_modes = character(0), + united_name = "united", time_format = "minute") { # renaming/uniting of modes trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) #processing avg_time = process_get_travelwaittime_by_mainmode(trips_table,time_format = time_format) @@ -2490,30 +2491,33 @@ plot_travelwaittime_mean_barchart <- function(trips_table, #' Bar Chart with distance traveled on x-axis and number of trips on y-axis #' -#' Takes the data frame trips_output (from \link{readTripsTable()}) and categorizes the traveled distances into pre-defined bins +#' Takes the data frame trips_output (from \link{read_output_trips()}) and categorizes the traveled distances into pre-defined bins #' to plot a histogram of the traveled distances. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') #' #' -#' @param trips_table tibble of trips_output (from readTripsTable()) -#' @param unite.modes vector of character strings, +#' @param trips_table tibble of trips_output (from \link{read_output_trips()}) +#' @param unite_modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode -#' @return Bar Chart plot of count of trips among distance travelled +#' @param united_name character string, specifies the name of the united mode +#' @param dist_column A character string specifying the column name in the trips_table tibble that contains the distance categories. +#' @param distances_array A numeric vector defining the distance thresholds for creating distance categories. +#' +#' @return Plotly bar Chart of count of trips among distance travelled #' #' @export plot_distcat_by_mainmode_barchart <- function(trips_table, - unite.modes = character(0), - united.name = "united", + unite_modes = character(0), + united_name = "united", dist_column = "dist_cat", distances_array = c(1000,2000,5000,10000,20000,50000,100000)) { # renaming/uniting of modes trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) #processing trips_table <- process_append_distcat(trips_table =trips_table, @@ -2533,28 +2537,30 @@ plot_distcat_by_mainmode_barchart <- function(trips_table, #' Bar chart with average distance traveled for each mode on x-axis and number of trips on y-axis #' -#' Takes the data frame trips_output (from \link{readTripsTable()}), +#' Takes the data frame trips_output (from \link{read_output_trips()}), #' to plot a bar chart of the average distance traveled for each main mode, -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') #' #' -#' @param trips_table tibble of trips_output (from readTripsTable()) -#'@param unite.modes vector of character strings, +#' @param trips_table tibble of trips_output (from \link{read_output_trips()}) +#' @param unite_modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param united_name character string, specifies the name of the united mode +#' @param euclidean Logical value indicating whether to calculate the average as euclidean distance or as travel distance. Default is FALSE, which calculates the average traveled distance. +#' #' @return Bar Chart plot of distance traveled per mode #' #' @export plot_distance_by_mainmode_barchart <- function(trips_table, - unite.modes = character(0), united.name = "united", + unite_modes = character(0), united_name = "united", euclidean = FALSE) { # renaming/uniting of modes trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) #processing trips_table <- process_get_travdistance_distribution(trips_table = trips_table,euclidean = euclidean) @@ -2581,28 +2587,28 @@ plot_distance_by_mainmode_barchart <- function(trips_table, #' Line plot with departure time on x-axis and number of trips on y-axis #' -#' Takes data frame trips_output (from \link{readTripsTable()}), +#' Takes data frame trips_output (from \link{read_output_trips()}), #' to create a line plot of the number of trips for a specific departure time by main_mode -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') #' #' -#' @param tripsTable tibble of trips_output (from readTripsTable()) -#' @param unite.modes vector of character strings, +#' @param tripsTable tibble of trips_output (from \link{read_output_trips()}) +#' @param unite_modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param united_name character string, specifies the name of the united mode #' @return Line plot of trips count by departure time per mode #' #' @export plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, unite.columns = character(0), - united.name = "united") { + united_name = "united") { # If some columns should be united trips_table <- process_rename_mainmodes(trips_table = trips_table, unite.columns = unite.columns, - united.name = united.name) + united_name = united_name) #processing @@ -2622,9 +2628,9 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, #' XXXX #' #' -#' @param table tibble of trips_output (from readTripsTable()) +#' @param trips_table tibble of trips_output (from \link{read_output_trips()}) #' -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' @param shape_table sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' #' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' @@ -2655,14 +2661,15 @@ plot_spatialtype_by_shape_piechart <- function(trips_table, shape_table, crs) { #' Bar Chart with tripType on x-axis and travelled distance on y-axis #' XXXX -#' Takes Table trips_output (from readTripsTable()), +#' Takes Table trips_output (from \link{read_output_trips()}), #' to plot bar chart with with values that represent #' travelled distance of each tripType related to the shapeTable #' #' -#' @param tripsTable tible of trips_output (from readTripsTable()) -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' @param trips_table tible of trips_output (from \link{read_output_trips()}) +#' @param shape_table sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation +#' @param euclidean Logical value indicating whether to calculate the average as euclidean distance or as travel distance. Default is FALSE, which calculates the average traveled distance. #' #' @return Bar Chart plot of distance traveled by spatial type #' @@ -2682,28 +2689,28 @@ plot_distance_by_spatialcat_barchart <- function(trips_table, shape_table, crs, } #' Line plot with departure time on x-axis and number of trips on y-axis #' -#' Takes data frame trips_output (from \link{readTripsTable()}), +#' Takes data frame trips_output (from \link{read_output_trips()}), #' to create a line plot of the number of trips for a specific departure time by main_mode -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') #' #' -#' @param tripsTable tibble of trips_output (from readTripsTable()) -#' @param unite.modes vector of character strings, +#' @param trips_table tibble of trips_output (from \link{read_output_trips()}) +#' @param unite_modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param united_name character string, specifies the name of the united mode #' @return Line plot of trips count by departure time per mode #' #' @export plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, - unite.columns = character(0), - united.name = "united") { + unite_modes = character(0), + united_name = "united") { # If some columns should be united trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) #processing @@ -2721,21 +2728,19 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, } -#' Deprecated function(s) in the matsimr package -#' XXXX -#' \strong{plot_arrtime_by_act} - Takes Table trips_output (from readTripsTable()), +#' Plot Arrival Time by Activity +#' +#' \strong{plot_arrtime_by_act} - Takes Table trips_output (from \link{read_output_trips}()), #' to make line plot with with values that represent #' count of destination activities for a specific arrival time -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') #' #' -#' @param trips_table tibble of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in plot -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly +#' @param trips_table tibble of trips_output (from \link{read_output_trips()}) +#' @param unite_activities vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns +#' @param united_name character string, if columns were united, you can specify name for the resulting column in plot #' -#' @return \strong{plot_arrtime_by_act} - Line plot with arrival time x-axis and number end activities on y-axis +#' @return A plotly object representing the line plot of arrival time by activity. #' #' @export plot_arrtime_by_act <- function(trips_table, unite_activities = character(0), united_name = "united") { @@ -2770,22 +2775,17 @@ plot_arrtime_by_act <- function(trips_table, unite_activities = character(0), un } -#' Deprecated function(s) in the matsimr package -#' XXXX -#' \strong{plotDepartureTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), -#' to make line plot with with values that represent -#' count of destination activities for a specific arrival time -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Plot Departure Time by Activity #' -#' @rdname matsimr-deprecated +#' The \code{plot_deptime_by_act} function generates a line plot to visualize the departure time of trips by activity in a given trips_table tibble. +#' It provides insights into the number of trips starting at different times for each activity. #' -#' @param tripsTable tibble of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in plot -#' @param dump.output.to folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored -#' @param only.files boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly #' -#' @return \strong{plotDepartureTimesPerTripPurpose} - Line plot with arrival time x-axis and number end activities on y-axis +#' @param tripsTable tibble of trips_output (from \link{read_output_trips()}) +#' @param unite_activities vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united_name = "united" that matches PATTERNS given in unite_columns +#' @param united_name character string, if columns were united, you can specify name for the resulting column in plot +#' +#' @return A plotly object representing the line plot of departure time by activity. #' #' @export plot_deptime_by_act <- function(trips_table, unite_activities = character(0), united_name = "united") { @@ -2822,33 +2822,36 @@ plot_deptime_by_act <- function(trips_table, unite_activities = character(0), un #' Bar chart comparing distance traveled on x-axis and number of trips on y-axis for two different runs -#' Takes two data frames (from \link{readTripsTable()}), categorizes the traveled distances into pre-defined bins +#' Takes two data frames (from \link{read_output_trips()}), categorizes the traveled distances into pre-defined bins #' and plots the difference in number of trips for each bin. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') #' #' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1 -#' @param tripsTable2 tibble of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted -#' @param unite.modes vector of character strings, +#' @param trips_table1 tibble of trips_output (from \link{read_output_trips()}), number of trips of this table will be extracted from number of trips of tripsTable1 +#' @param trips_table2 tibble of trips_output (from \link{read_output_trips()}), from number of trips of this table number of trips of tripsTable1 will be extracted +#' @param unite_modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param united_name character string, specifies the name of the united mode +#' @param dist_column A character string specifying the column name in the trips_table tibble that contains the distance categories. +#' @param distances_array A numeric vector defining the distance thresholds for creating distance categories. +#' #' @return Bar Chart plot of count of trips among distance travelled #' #' @export plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, - unite.modes = character(0), united.name = "united", + unite_modes = character(0), united_name = "united", dist_column = "dist_cat", distances_array = c(1000,2000,5000,10000,20000,50000,100000)) { trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) modes = unique(c(unique(trips_table1$main_mode),unique(trips_table2$main_mode))) @@ -2885,33 +2888,33 @@ plot_compare_distcat_by_mainmode_barchart <- function(trips_table1,trips_table2, #' Plot bar chart of changes in modal split #' -#' Takes two data frames (from \link{readTripsTable()}), calculates the +#' Takes two data frames (from \link{read_output_trips()}), calculates the #' changes in mode shares and plots them as a bar chart -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') #' #' #' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()) -#' @param tripsTable2 tibble of trips_output (from readTripsTable()) -#'@param unite.modes vector of character strings, +#' @param trips_table1 tibble of trips_output (from \link{read_output_trips()}) +#' @param trips_table2 tibble of trips_output (from \link{read_output_trips()}) +#' @param unite_modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param united_name character string, specifies the name of the united mode #' #' @return plots bar chart of changes in modal split #' #' @export plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, - unite.modes = character(0), - united.name = "united") { + unite_modes = character(0), + united_name = "united") { # renaming/uniting of modes trips_table1 <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) trips_table2 <- process_rename_mainmodes(trips_table = trips_table, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) trips_table1 = trips_table1 %>% mutate(type = "base") trips_table2 = trips_table2 %>% mutate(type = "policy") @@ -2928,41 +2931,41 @@ plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, #' Plot alluvial/sankey diagram of transport mode changes #' -#' Takes two data frames (from \link{readTripsTable()}) and compares the mode choice for each agent and summarizes the results, showing the modal shift. -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Takes two data frames (from \link{read_output_trips()}) and compares the mode choice for each agent and summarizes the results, showing the modal shift. +#' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') #' The parameter show.onlyChanges allows the visualization of only the mode shift (excluding the trips that do not change mode). Standard value is FALSE. #' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()) -#' @param tripsTable2 tibble of trips_output (from readTripsTable()) -#' @param show.onlyChanges boolean, if it is set to TRUE the sankey diagram only shows the mode shift -#' @param unite.modes vector of character strings, +#' @param trips_table1 tibble of trips_output (from read_output_trips()) +#' @param trips_table2 tibble of trips_output (from read_output_trips()) +#' @param show_onlychanges boolean, if it is set to TRUE the sankey diagram only shows the mode shift +#' @param unite_modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param united_name character string, specifies the name of the united mode #' #' @return Alluvial diagram that represents changes in transport mode distribution #' #' @export plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, - show.onlyChanges = FALSE, - unite.modes = character(0), - united.name = "united") { + show_onlychanges = FALSE, + unite_modes = character(0), + united_name = "united") { # renaming/uniting of modes trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) #processing joined <- as_tibble(inner_join(trips_table1, trips_table2 %>% select(trip_id, main_mode), by = "trip_id") %>% dplyr::rename(base_mode = main_mode.x, policy_mode = main_mode.y)) #if onlychanges, then we should exclude base_mode=policy_mode - if (show.onlyChanges == TRUE) { + if (show_onlychanges == TRUE) { joined <- joined %>% filter(base_mode != policy_mode) } @@ -3015,25 +3018,26 @@ plot_compare_mainmode_sankey <- function(trips_table1, trips_table2, #' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis #' -#' Takes the data frame trips_output (from \link{readTripsTable()}), +#' Takes the data frame trips_output (from \link{read_output_trips()}), #' to plot a bar chart of the traveling/waiting time -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') #' #' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()) -#' @param tripsTable2 tibble of trips_output (from readTripsTable()) -#' @param unite.modes vector of character strings, +#' @param trips_table1 tibble of trips_output (from \link{read_output_trips()}) +#' @param trips_table2 tibble of trips_output (from \link{read_output_trips()}) +#' @param unite_modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param united_name character string, specifies the name of the united mode +#' @param time_format character string, defines time format to be used(takes "hour", "minute", "second") #' #' @return Bar Chart plot of average time spent on travel/wait #' #' @export plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_table2, - unite.modes = character(0), - united.name = "united", + unite_modes = character(0), + united_name = "united", time_format = "minute") { #TODO: @@ -3043,12 +3047,12 @@ plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_ # If some columns should be united trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) #processing avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) @@ -3081,23 +3085,24 @@ plot_compare_travelwaittime_by_mainmode_barchart <- function(trips_table1,trips_ } -#' Bar Chart with main_mode on x-axis and average travel/wait time on y-axis -#' XXXX -#' Takes Table trips_output (from readTripsTable()), -#' to plot bar chart with with values that represent -#' time spent on traveling/waiting -#' Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +#' Plot Comparison of Count by Spatial Category (Bar Chart) #' +#' The \code{plot_compare_count_by_spatialcat_barchart} +#' function generates a bar chart to compare the count of trips between two trips_table +#' tibbles across different spatial categories. +#' It provides insights into the distribution of trips across spatial categories for each table. #' -#' @param tripsTable1 tible of trips_output (from readTripsTable()) -#' @param tripsTable2 tible of trips_output (from readTripsTable()) -#' @param unite.columns vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns -#' @param united.name character string, if columns were united, you can specify name for the resulting column in chart #' -#' @return Bar Chart plot of average time spent on travel/wait +#' @param trips_table1 tible of trips_output (from \link{read_output_trips()}) +#' @param trips_table2 tible of trips_output (from \link{read_output_trips()}) +#' @param shape_table A spatial shapefile or spatial polygons dataframe representing the spatial categories. +#' @param crs numeric representation of the EPSG code or proj4string for the corresponding coordinate system of the trip coordinates, +#' can be found in network file from output directory of MATSim simulation +#' +#' @return A plotly object representing the bar chart of the comparison of count by spatial category. #' #' @export -plot_compare_count_by_spatialcat_barchart <- function(trips_table1,trips_table2, shape_table ,crs,dump.output.to = matsimDumpOutputDirectory) { +plot_compare_count_by_spatialcat_barchart <- function(trips_table1,trips_table2, shape_table ,crs) { spatial_table1 <- process_append_spatialcat(trips_table = trips_table1, shape_table = shape_table, @@ -3120,24 +3125,25 @@ plot_compare_count_by_spatialcat_barchart <- function(trips_table1,trips_table2, #' Bar Chart comparing two runs with main_mode on x-axis and average travel/wait time on y-axis #' -#' Takes two data frames (from \link{readTripsTable()}), +#' Takes two data frames (from \link{read_output_trips()}), #' to plot a comparison bar chart of travel and wait times. -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +#' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') #' #' -#' @param tripsTable1 tibble of trips_output (from readTripsTable()) -#' @param tripsTable2 tibble of trips_output (from readTripsTable()) -#' @param unite.modes vector of character strings, +#' @param trips_table1 tibble of trips_output (from \link{read_output_trips()}) +#' @param trips_table2 tibble of trips_output (from \link{read_output_trips()}) +#' @param unite_modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode +#' @param united_name character string, specifies the name of the united mode#' +#' @param time_format character string, defines time format to be used(takes "hour", "minute", "second") #' #' @return Bar chart plot comparing average time spent on travel/wait of two runs #' #' @export plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, - unite.modes = character(0), - united.name = "united", + unite_modes = character(0), + united_name = "united", time_format = "minute") { #TODO: @@ -3147,12 +3153,12 @@ plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, # renaming/uniting of modes trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, - unite.modes = unite.modes, - united.name = united.name) + unite_modes = unite_modes, + united_name = united_name) #processing avg_time1 = process_get_travelwaittime_by_mainmode(trips_table1,time_format = time_format) @@ -3191,16 +3197,17 @@ plot_compare_travelwaittime_by_mainmode <- function(trips_table1,trips_table2, #' Plots start and end coordinates of the given trips table on an osm map -#' XXXX -#' @param table tibble of trips_output (from readTripsTable()) #' +#' @param trips_table tibble of trips_output (from \link{read_output_trips()}) #' +#' @param shape_table spatial #' @param crs numeric representation of the EPSG code or proj4string for the corresponding coordinate system of the trip coordinates, can be found in network file from output directory of MATSim simulation -#' +#' @param shape_table A spatial shapefile or spatial polygons dataframe representing the spatial categories. +#' By default NULL, means there are no specific shape map on the backgroung. #' @param optimized bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot #' #' -#' @return plot with trips +#' @return leaflet/ggplot plot with trips start-, end- points #' #' @export plot_map_trips <- function(trips_table, crs,optimized = FALSE, @@ -3247,17 +3254,6 @@ plot_map_trips <- function(trips_table, crs,optimized = FALSE, } - - - - - - - # If we need to change design - # css_fix <- "div.info.legend.leaflet-control br {clear: both;}" - # Convert CSS to HTML - # html_fix <- htmltools::tags$style(type = "text/css", css_fix) - plt <- leaflet() %>% addTiles() %>% addProviderTiles( @@ -3344,12 +3340,11 @@ plot_map_trips <- function(trips_table, crs,optimized = FALSE, #' Plots every type of trips(inside, outside, origin and destinating) on map -#' XXXX #' #' -#' @param table tibble of trips_output (from readTripsTable()) +#' @param trips_table tibble of trips_output (from \link{read_output_trips()}) #' -#' @param shapeTable sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) +#' @param shape_table sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' #' @param crs numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation #' @@ -3582,18 +3577,47 @@ plot_map_trips_by_spatialcat <- function(trips_table, shape_table, } #####Processing##### -#' XXXX + +#' Replace Matching Categories of main_mode with United Name in Tibble +#' +#' The process_rename_mainmodes function takes a tibble, trips_table, +#' as input and replaces all occurrences in column main_mode of categories +#' that match a given template with another name provided in united_name. +#' The function provides the flexibility to specify multiple category templates +#' to be united into a single name. +#' +#' @param trips_table tible of output_trips (from \link{\code{read_output_trips}}) +#' @param unite_modes vector of character string, representing pattern to match categories +#' @param united_name character string, to represent new category for all occurrences matched unite_modes +#' +#' @return tibble with new main_mode representation +#' #' @export process_rename_mainmodes<-function(trips_table, - unite.modes = character(0), united.name = "united"){ + unite_modes = character(0), united_name = "united"){ - if (length(unite.modes) != 0) { - trips_table$main_mode[grep(paste0(unite.modes, collapse = "|") - , trips_table$main_mode)] <- united.name + if (length(unite_modes) != 0) { + trips_table$main_mode[grep(paste0(unite_modes, collapse = "|") + , trips_table$main_mode)] <- united_name } return(trips_table) } +#' Replace Matching Categories of any column with United Name in Tibble +#' +#' The \code{process_rename_category} function takes a tibble, trips_table, +#' as input and replaces all occurrences of categories +#' that match a given template with another name provided in united_name. +#' The function provides the flexibility to specify multiple category templates +#' to be united into a single name. +#' +#' @param trips_table tible of output_trips (from \link{\code{read_output_trips}}) +#' @param unite_template vector of character string, representing pattern to match categories +#' @param united_name character string, to represent new category for all occurrences matched unite_modes +#' @param column tibble column name, which will be used in occurrences renaming +#' +#' @return modified trips table tibble +#' #' @export process_rename_category<-function(trips_table, unite_template= character(0), united_name = "united",column = "main_mode"){ @@ -3604,6 +3628,19 @@ process_rename_category<-function(trips_table, return(trips_table) } +#' Calculates main mode distribution +#' +#' The process_get_mainmode_distribution function calculates the distribution of main modes in a given trips_table.\cr +#' It provides insights into the frequency or percentage of each main mode within the dataset. +#' +#' By default, the function counts the occurrences of each main mode in the trips_table tibble and returns the counts for each unique main mode. \cr +#' Alternatively, when the percentage parameter is set to TRUE, the function normalizes the counts to represent the percentage distribution of each main mode within the dataset. +#' +#' @param trips_table tible of output_trips (from \link{\code{read_output_trips}}) +#' @param percenate boolean, by default FALSE, sets if output should be given in percentage +#' +#' @return tibble that provides the distribution of main modes in the input trips_table. +#' #' @export process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ @@ -3615,6 +3652,16 @@ process_get_mainmode_distribution<-function(trips_table,percentage = FALSE){ return(trips_table_count) } + +#' Get Travel Distance Distribution by Main Mode +#' +#' The \code{process_get_travdistance_distribution} function calculates the distribution of travel distances based on main modes in a given trips_table tibble. It provides insights into the average distance traveled for each main mode. +#' +#' @param trips_table A tibble of output_trips (from \link{\code{read_output_trips}}) +#' @param euclidean Logical value indicating whether to calculate the average as euclidean distance or as travel distance. Default is FALSE, which calculates the average traveled distance. +#' +#' @return A tibble containing the main_mode column representing unique main modes and the avg_dist column representing the average travel distance for each main mode. +#' #' @export process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ @@ -3625,6 +3672,15 @@ process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ return(trips_table) } +#' Get Travel and Wait Time by Main Mode +#' +#' The \code{process_get_travelwaittime_by_mainmode} function calculates the average travel time and average wait time for each main mode in a given trips_table tibble. +#' +#' @param trips_table A tibble of output_trips (from \link{\code{read_output_trips}}) +#' @param time_format A character string indicating the desired time format for the output. The options are "minute", "hour", or "second". The default is "minute". +#' +#' @return A tibble containing the main_mode column representing unique main modes, trav_time_avg column representing the average travel time for each main mode, and wait_time_avg column representing the average wait time for each main mode. +#' #' @export process_get_travelwaittime_by_mainmode<-function(trips_table, time_format = "minute"){#also could be hours/seconds @@ -3725,7 +3781,7 @@ process_convert_time <- function(trips_table,time_format = "hour",time_column = #' if spatial_type="destinating" return table that contains trips which ends in shape and starts out of the shape\cr #' if spatial_type="outside" return table that contains trips which starts and ends our of the given shape #' -#' @param trips_table tibble of trips_output (from readTripsTable()) +#' @param trips_table tibble of trips_output (from \link{read_output_trips()}) #' #' @param shape_table sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' @@ -3809,7 +3865,7 @@ process_filter_by_shape <- function(trips_table, #' category representing trips which \strong{destinating} in the shape #' category representing trips which \strong{outside} of the given shape #' -#' @param trips_table tibble of trips_output (from readTripsTable()) +#' @param trips_table tibble of trips_output (from \link{read_output_trips()}) #' #' @param shape_table sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file) #' @@ -3909,9 +3965,9 @@ process_get_crs_from_config <- function(config_path) { #' or for simwrapper (origin and destination as columns) #' #' -#' @param tripsTable tibble of trips_output (from \link{readTripsTable}) +#' @param trips_table tibble of trips_output (from \link{readTripsTable}) #' -#' @param shapePath string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file) +#' @param shape_path string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file) #' #' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file #' @@ -4030,7 +4086,7 @@ process_get_od_matrix<- function(trips_table, #' Added column/columns are projected to given CRS (coordinate reference system).\cr #' The columns start_x, end_x, start_y, end_y are deleted from the resulting data frame. #' -#' @param table tibble trips_output (from readTripsTable()) +#' @param table tibble trips_output (from \link{read_output_trips()}) #' #' @param crs numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file #' diff --git a/R/personsOutput.R b/R/personsOutput.R index 3bb6adc..cec2db4 100644 --- a/R/personsOutput.R +++ b/R/personsOutput.R @@ -55,7 +55,12 @@ readPersonsTable <- function(input_path = ".", n_max = Inf) { return(persons_output_table) } - +#' Boxplot of Score Differences +#' +#' The \code{boxplotScoreDifferences} function generates a boxplot to compare the score differences between two sets of data +#' represented by personTibble_base and personTibble_policy tibbles. +#' It provides insights into the distribution of score differences between the two sets of data. +#' #' @param personTibble_base persons tibble of the base case, can be loaded with readPersonsTable. #' @param personTibble_policy persons tibble of the policy case, can be loaded with readPersonsTable. #' diff --git a/man/boxplotScoreDifferences.Rd b/man/boxplotScoreDifferences.Rd new file mode 100644 index 0000000..16e7b58 --- /dev/null +++ b/man/boxplotScoreDifferences.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/personsOutput.R +\name{boxplotScoreDifferences} +\alias{boxplotScoreDifferences} +\title{Boxplot of Score Differences} +\usage{ +boxplotScoreDifferences(personTibble_base, personTibble_policy) +} +\arguments{ +\item{personTibble_base}{persons tibble of the base case, can be loaded with readPersonsTable.} + +\item{personTibble_policy}{persons tibble of the policy case, can be loaded with readPersonsTable.} +} +\value{ +ggplot boxplot of the distribution of the score differences +} +\description{ +The \code{boxplotScoreDifferences} function generates a boxplot to compare the score differences between two sets of data +represented by personTibble_base and personTibble_policy tibbles. +It provides insights into the distribution of score differences between the two sets of data. +} diff --git a/man/loadNetwork.Rd b/man/loadNetwork.Rd deleted file mode 100644 index 9ac6c5b..0000000 --- a/man/loadNetwork.Rd +++ /dev/null @@ -1,24 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/network.R -\name{loadNetwork} -\alias{loadNetwork} -\title{Load MATSim network into memory} -\usage{ -loadNetwork(filename) -} -\arguments{ -\item{filename}{File to load. Can be XML or gzipped XML} -} -\value{ -"nodes" and "links" tibbles in a list object. -} -\description{ -Loads a MATSim XML network file, creating a nodes tibble and a links tibble. -Any node and link attribute records in the network are stored as -additional columns in the respective node and link tibbles. -} -\details{ -The links table is automatically joined with the nodes table so that -node x/y coordinates (and any other node attributes) are available on the -links table without additional processing. -} diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 3b8ee2d..0372fbc 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -1,7 +1,8 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/output_trips.R +% Please edit documentation in R/network.R, R/output_trips.R \docType{package} -\name{matsimr-deprecated} +\name{loadNetwork} +\alias{loadNetwork} \alias{matsimr-deprecated} \alias{plotModalSplitPieChart} \alias{plotModalSplitBarChart} @@ -30,9 +31,10 @@ \alias{deriveODMatrix} \alias{getCrsFromConfig} \alias{transformToSf} -\alias{plot_deptime_by_act} -\title{Deprecated function(s) in the matsimr package} +\title{Load MATSim network into memory} \usage{ +loadNetwork(filename) + plotModalSplitPieChart( tripsTable, unite.columns = character(0), @@ -210,21 +212,17 @@ deriveODMatrix( getCrsFromConfig(folder) transformToSf(table, crs, geometry.type = st_multipoint()) - -plot_deptime_by_act( - trips_table, - unite_activities = character(0), - united_name = "united" -) } \arguments{ -\item{tripsTable}{tibble of trips_output (from readTripsTable())} +\item{filename}{File to load. Can be XML or gzipped XML} -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{tripsTable}{table of output trips(from readTripsTable) or path to trips_output file} -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in plot} +\item{unite.columns}{vector of character string, changes name of all transport modes in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns} -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} +\item{united.name}{if columns were united, you can specify name for the resulting column in plot} + +\item{dump.output.to}{path to a folder to save csv file of ODMatrix} \item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} @@ -232,9 +230,9 @@ plot_deptime_by_act( \item{n_max}{integer, maximum number of lines to read within output_trips} -\item{tripsTable1}{tibble of trips_output (from readTripsTable(),f.e. base case)} +\item{tripsTable1}{tibble of trips_output (from \link{read_output_trips()},f.e. base case)} -\item{tripsTable2}{tibble of trips_output (from readTripsTable(),f.e. policy case)} +\item{tripsTable2}{tibble of trips_output (from \link{read_output_trips()},f.e. policy case)} \item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} @@ -242,7 +240,7 @@ plot_deptime_by_act( \item{show.onlyChanges}{boolean, if it is set to TRUE => sankey diagram only contains changes on axes} -\item{table}{tibble of trips_output (from readTripsTable())} +\item{table}{tibble of trips_output (from \link{read_output_trips()})} \item{start.inshape}{bool, defines trips to conclude (see Description)} @@ -270,8 +268,12 @@ plot_deptime_by_act( !!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or \cr !!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or \cr !!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!!} + +\item{united_name}{character string, if columns were united, you can specify name for the resulting column in chart} } \value{ +\strong{loadNetwork} - "nodes" and "links" tibbles in a list object. + \strong{plotModalSplitPieChart} - Pie Chart plot of transport mode distribution, values given in percents \strong{plotModalSplitBarChart} - Bar Chart plot of transport mode distribution, values given in percents @@ -323,66 +325,71 @@ tibble of output_trips with distance category column \strong{getCrsFromConfig} - code of coordinate reference system \strong{transformToSf} - sf object (data.frame with geometries depending to geometry.type) - -\strong{plotDepartureTimesPerTripPurpose} - Line plot with arrival time x-axis and number end activities on y-axis } \description{ +\strong{loadNetwork} - Loads a MATSim XML network file, creating a nodes tibble and a links tibble. +Any node and link attribute records in the network are stored as +additional columns in the respective node and link tibbles.\cr +The links table is automatically joined with the nodes table so that +node x/y coordinates (and any other node attributes) are available on the +links table without additional processing. + These functions are provided for compatibility with older version of the matsimr package. They may eventually be completely removed.\cr\cr -\strong{plotModalSplitPieChart} - Takes Table trips_output (from readTripsTable()), +\strong{plotModalSplitPieChart} - Takes Table trips_output (from \link{read_output_trips()}), to plot pie chart with with values that represent percentage of using transport modes from trips -\strong{plotModalSplitBarChart} - Takes Table trips_output (from readTripsTable()), +\strong{plotModalSplitBarChart} - Takes Table trips_output (from \link{read_output_trips()}), to plot bar chart with with values that represent percentage of using transport modes from trips \strong{readTripsTable} - Loads a MATSim output_trips file from file or archive path, creating a tibble -\strong{plotAverageTravelWait} - Takes Table trips_output (from readTripsTable()), +\strong{plotAverageTravelWait} - Takes Table trips_output (from \link{read_output_trips()}), to plot bar chart with with values that represent time spent on traveling/waiting Using parameters unite.columns, specific columns could be given, -to unite them in 1 mode with the name united.name(by default 'united') +to unite them in 1 mode with the name united_name(by default 'united') -\strong{plotModalDistanceDistribution} - Takes Table trips_output (from readTripsTable()), +\strong{plotModalDistanceDistribution} - Takes Table trips_output (from \link{read_output_trips()}), to plot bar chart with with values that represent number of trips ~ distance travelled -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') -\strong{compareModalDistanceDistribution} - Takes 2 Tables trips_output (from readTripsTable()), +\strong{compareModalDistanceDistribution} - Takes 2 Tables trips_output (from \link{read_output_trips()}), to plot bar chart with with values that represent difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') -\strong{plotTripDistanceByMode} - Takes Table trips_output (from readTripsTable()), +\strong{plotTripDistanceByMode} - Takes Table trips_output (from \link{read_output_trips()}), to plot bar chart with with values that represent average distance traveled ~ main mode used -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') -\strong{plotTripCountByDepTime} - Takes Table trips_output (from readTripsTable()), +\strong{plotTripCountByDepTime} - Takes Table trips_output (from \link{read_output_trips()}), to make line plot with with values that represent count of trips for a specific departure time by main_mode -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') -\strong{plotActivityEndTimes} - Takes Table trips_output (from readTripsTable()), +\strong{plotActivityEndTimes} - Takes Table trips_output (from \link{read_output_trips()}), to make line plot with with values that represent the number of activities ending at a specific time. -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') -\strong{plotArrivalTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), +\strong{plotArrivalTimesPerTripPurpose} - Takes Table trips_output (from \link{read_output_trips()}), to make line plot with with values that represent count of destination activities for a specific arrival time -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') -\strong{plotDepartureTimesPerTripPurpose} - Takes Table trips_output (from readTripsTable()), +\strong{plotDepartureTimesPerTripPurpose} - Takes Table trips_output (from \link{read_output_trips()}), to make line plot with with values that represent count of destination activities for a specific arrival time -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') -\strong{plotTripDistancedByType} - Takes Table trips_output (from readTripsTable()), +\strong{plotTripDistancedByType} - Takes Table trips_output (from \link{read_output_trips()}), to plot bar chart with with values that represent travelled distance of each tripType related to the shapeTable @@ -392,7 +399,7 @@ to make alluvial diagram from this data\cr Function calculates number of each transport mode used in first and second table, and draws plot that represent how distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) -Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") +Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united_name is "united") Using parameter show.onlyChanges \strong{plotModalShiftBar} - Takes two trips_table (from readTripsTable), and collects @@ -401,7 +408,7 @@ to make bar chart diagram with dodging positioning from this data\cr Function calculates number of each transport mode used in first and second table, and draws plot that represent how distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) -Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united.name is "united") +Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united_name is "united") Using parameter show.onlyChanges \strong{plotMapWithFilteredTrips} - Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file)) diff --git a/man/plot_arrtime_by_act.Rd b/man/plot_arrtime_by_act.Rd index 75953b4..927b611 100644 --- a/man/plot_arrtime_by_act.Rd +++ b/man/plot_arrtime_by_act.Rd @@ -2,12 +2,7 @@ % Please edit documentation in R/output_trips.R \name{plot_arrtime_by_act} \alias{plot_arrtime_by_act} -\title{Deprecated function(s) in the matsimr package -XXXX -\strong{plot_arrtime_by_act} - Takes Table trips_output (from readTripsTable()), -to make line plot with with values that represent -count of destination activities for a specific arrival time -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united')} +\title{Plot Arrival Time by Activity} \usage{ plot_arrtime_by_act( trips_table, @@ -16,24 +11,18 @@ plot_arrtime_by_act( ) } \arguments{ -\item{trips_table}{tibble of trips_output (from readTripsTable())} - -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} - -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in plot} +\item{trips_table}{tibble of trips_output (from \link{read_output_trips()})} -\item{dump.output.to}{folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored} +\item{unite_activities}{vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns} -\item{only.files}{boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly} +\item{united_name}{character string, if columns were united, you can specify name for the resulting column in plot} } \value{ -\strong{plot_arrtime_by_act} - Line plot with arrival time x-axis and number end activities on y-axis +A plotly object representing the line plot of arrival time by activity. } \description{ -Deprecated function(s) in the matsimr package -XXXX -\strong{plot_arrtime_by_act} - Takes Table trips_output (from readTripsTable()), +\strong{plot_arrtime_by_act} - Takes Table trips_output (from \link{read_output_trips}()), to make line plot with with values that represent count of destination activities for a specific arrival time -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united') } diff --git a/man/plot_compare_count_by_spatialcat_barchart.Rd b/man/plot_compare_count_by_spatialcat_barchart.Rd index d587af5..9589b0b 100644 --- a/man/plot_compare_count_by_spatialcat_barchart.Rd +++ b/man/plot_compare_count_by_spatialcat_barchart.Rd @@ -2,38 +2,31 @@ % Please edit documentation in R/output_trips.R \name{plot_compare_count_by_spatialcat_barchart} \alias{plot_compare_count_by_spatialcat_barchart} -\title{Bar Chart with main_mode on x-axis and average travel/wait time on y-axis -XXXX -Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -time spent on traveling/waiting -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united')} +\title{Plot Comparison of Count by Spatial Category (Bar Chart)} \usage{ plot_compare_count_by_spatialcat_barchart( trips_table1, trips_table2, shape_table, - crs, - dump.output.to = matsimDumpOutputDirectory + crs ) } \arguments{ -\item{tripsTable1}{tible of trips_output (from readTripsTable())} +\item{trips_table1}{tible of trips_output (from \link{read_output_trips()})} -\item{tripsTable2}{tible of trips_output (from readTripsTable())} +\item{trips_table2}{tible of trips_output (from \link{read_output_trips()})} -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{shape_table}{A spatial shapefile or spatial polygons dataframe representing the spatial categories.} -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +\item{crs}{numeric representation of the EPSG code or proj4string for the corresponding coordinate system of the trip coordinates, +can be found in network file from output directory of MATSim simulation} } \value{ -Bar Chart plot of average time spent on travel/wait +A plotly object representing the bar chart of the comparison of count by spatial category. } \description{ -Bar Chart with main_mode on x-axis and average travel/wait time on y-axis -XXXX -Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -time spent on traveling/waiting -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +The \code{plot_compare_count_by_spatialcat_barchart} +function generates a bar chart to compare the count of trips between two trips_table +tibbles across different spatial categories. +It provides insights into the distribution of trips across spatial categories for each table. } diff --git a/man/plot_compare_distcat_by_mainmode_barchart.Rd b/man/plot_compare_distcat_by_mainmode_barchart.Rd index 807a64a..5bc93bd 100644 --- a/man/plot_compare_distcat_by_mainmode_barchart.Rd +++ b/man/plot_compare_distcat_by_mainmode_barchart.Rd @@ -3,36 +3,40 @@ \name{plot_compare_distcat_by_mainmode_barchart} \alias{plot_compare_distcat_by_mainmode_barchart} \title{Bar chart comparing distance traveled on x-axis and number of trips on y-axis for two different runs -Takes two data frames (from \link{readTripsTable()}), categorizes the traveled distances into pre-defined bins +Takes two data frames (from \link{read_output_trips()}), categorizes the traveled distances into pre-defined bins and plots the difference in number of trips for each bin. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) -Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united')} +Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united')} \usage{ plot_compare_distcat_by_mainmode_barchart( trips_table1, trips_table2, - unite.modes = character(0), - united.name = "united", + unite_modes = character(0), + united_name = "united", dist_column = "dist_cat", distances_array = c(1000, 2000, 5000, 10000, 20000, 50000, 1e+05) ) } \arguments{ -\item{unite.modes}{vector of character strings, +\item{trips_table1}{tibble of trips_output (from \link{read_output_trips()}), number of trips of this table will be extracted from number of trips of tripsTable1} + +\item{trips_table2}{tibble of trips_output (from \link{read_output_trips()}), from number of trips of this table number of trips of tripsTable1 will be extracted} + +\item{unite_modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), using the function (\link{process_rename_mainmodes})} -\item{united.name}{character string, specifies the name of the united mode} +\item{united_name}{character string, specifies the name of the united mode} -\item{tripsTable1}{tibble of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1} +\item{dist_column}{A character string specifying the column name in the trips_table tibble that contains the distance categories.} -\item{tripsTable2}{tibble of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted} +\item{distances_array}{A numeric vector defining the distance thresholds for creating distance categories.} } \value{ Bar Chart plot of count of trips among distance travelled } \description{ Bar chart comparing distance traveled on x-axis and number of trips on y-axis for two different runs -Takes two data frames (from \link{readTripsTable()}), categorizes the traveled distances into pre-defined bins +Takes two data frames (from \link{read_output_trips()}), categorizes the traveled distances into pre-defined bins and plots the difference in number of trips for each bin. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) -Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') } diff --git a/man/plot_compare_mainmode_barchart.Rd b/man/plot_compare_mainmode_barchart.Rd index 395491e..4893606 100644 --- a/man/plot_compare_mainmode_barchart.Rd +++ b/man/plot_compare_mainmode_barchart.Rd @@ -7,26 +7,26 @@ plot_compare_mainmode_barchart( trips_table1, trips_table2, - unite.modes = character(0), - united.name = "united" + unite_modes = character(0), + united_name = "united" ) } \arguments{ -\item{unite.modes}{vector of character strings, -changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -using the function (\link{process_rename_mainmodes})} +\item{trips_table1}{tibble of trips_output (from \link{read_output_trips()})} -\item{united.name}{character string, specifies the name of the united mode} +\item{trips_table2}{tibble of trips_output (from \link{read_output_trips()})} -\item{tripsTable1}{tibble of trips_output (from readTripsTable())} +\item{unite_modes}{vector of character strings, +changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +using the function (\link{process_rename_mainmodes})} -\item{tripsTable2}{tibble of trips_output (from readTripsTable())} +\item{united_name}{character string, specifies the name of the united mode} } \value{ plots bar chart of changes in modal split } \description{ -Takes two data frames (from \link{readTripsTable()}), calculates the +Takes two data frames (from \link{read_output_trips()}), calculates the changes in mode shares and plots them as a bar chart -Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') } diff --git a/man/plot_compare_mainmode_sankey.Rd b/man/plot_compare_mainmode_sankey.Rd index a144e4f..c90cde9 100644 --- a/man/plot_compare_mainmode_sankey.Rd +++ b/man/plot_compare_mainmode_sankey.Rd @@ -7,29 +7,29 @@ plot_compare_mainmode_sankey( trips_table1, trips_table2, - show.onlyChanges = FALSE, - unite.modes = character(0), - united.name = "united" + show_onlychanges = FALSE, + unite_modes = character(0), + united_name = "united" ) } \arguments{ -\item{show.onlyChanges}{boolean, if it is set to TRUE the sankey diagram only shows the mode shift} +\item{trips_table1}{tibble of trips_output (from read_output_trips())} -\item{unite.modes}{vector of character strings, -changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -using the function (\link{process_rename_mainmodes})} +\item{trips_table2}{tibble of trips_output (from read_output_trips())} -\item{united.name}{character string, specifies the name of the united mode} +\item{show_onlychanges}{boolean, if it is set to TRUE the sankey diagram only shows the mode shift} -\item{tripsTable1}{tibble of trips_output (from readTripsTable())} +\item{unite_modes}{vector of character strings, +changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), +using the function (\link{process_rename_mainmodes})} -\item{tripsTable2}{tibble of trips_output (from readTripsTable())} +\item{united_name}{character string, specifies the name of the united mode} } \value{ Alluvial diagram that represents changes in transport mode distribution } \description{ -Takes two data frames (from \link{readTripsTable()}) and compares the mode choice for each agent and summarizes the results, showing the modal shift. -Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +Takes two data frames (from \link{read_output_trips()}) and compares the mode choice for each agent and summarizes the results, showing the modal shift. +Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') The parameter show.onlyChanges allows the visualization of only the mode shift (excluding the trips that do not change mode). Standard value is FALSE. } diff --git a/man/plot_compare_travelwaittime_by_mainmode.Rd b/man/plot_compare_travelwaittime_by_mainmode.Rd index 86ab86a..1816e79 100644 --- a/man/plot_compare_travelwaittime_by_mainmode.Rd +++ b/man/plot_compare_travelwaittime_by_mainmode.Rd @@ -7,27 +7,29 @@ plot_compare_travelwaittime_by_mainmode( trips_table1, trips_table2, - unite.modes = character(0), - united.name = "united", + unite_modes = character(0), + united_name = "united", time_format = "minute" ) } \arguments{ -\item{unite.modes}{vector of character strings, +\item{trips_table1}{tibble of trips_output (from \link{read_output_trips()})} + +\item{trips_table2}{tibble of trips_output (from \link{read_output_trips()})} + +\item{unite_modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), using the function (\link{process_rename_mainmodes})} -\item{united.name}{character string, specifies the name of the united mode} - -\item{tripsTable1}{tibble of trips_output (from readTripsTable())} +\item{united_name}{character string, specifies the name of the united mode#'} -\item{tripsTable2}{tibble of trips_output (from readTripsTable())} +\item{time_format}{character string, defines time format to be used(takes "hour", "minute", "second")} } \value{ Bar chart plot comparing average time spent on travel/wait of two runs } \description{ -Takes two data frames (from \link{readTripsTable()}), +Takes two data frames (from \link{read_output_trips()}), to plot a comparison bar chart of travel and wait times. -Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') } diff --git a/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd b/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd index 3e8b5a4..3c7727d 100644 --- a/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd +++ b/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd @@ -7,27 +7,29 @@ plot_compare_travelwaittime_by_mainmode_barchart( trips_table1, trips_table2, - unite.modes = character(0), - united.name = "united", + unite_modes = character(0), + united_name = "united", time_format = "minute" ) } \arguments{ -\item{unite.modes}{vector of character strings, +\item{trips_table1}{tibble of trips_output (from \link{read_output_trips()})} + +\item{trips_table2}{tibble of trips_output (from \link{read_output_trips()})} + +\item{unite_modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), using the function (\link{process_rename_mainmodes})} -\item{united.name}{character string, specifies the name of the united mode} - -\item{tripsTable1}{tibble of trips_output (from readTripsTable())} +\item{united_name}{character string, specifies the name of the united mode} -\item{tripsTable2}{tibble of trips_output (from readTripsTable())} +\item{time_format}{character string, defines time format to be used(takes "hour", "minute", "second")} } \value{ Bar Chart plot of average time spent on travel/wait } \description{ -Takes the data frame trips_output (from \link{readTripsTable()}), +Takes the data frame trips_output (from \link{read_output_trips()}), to plot a bar chart of the traveling/waiting time -Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') } diff --git a/man/plot_deptime_by_act.Rd b/man/plot_deptime_by_act.Rd new file mode 100644 index 0000000..3ece558 --- /dev/null +++ b/man/plot_deptime_by_act.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{plot_deptime_by_act} +\alias{plot_deptime_by_act} +\title{Plot Departure Time by Activity} +\usage{ +plot_deptime_by_act( + trips_table, + unite_activities = character(0), + united_name = "united" +) +} +\arguments{ +\item{unite_activities}{vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united_name = "united" that matches PATTERNS given in unite_columns} + +\item{united_name}{character string, if columns were united, you can specify name for the resulting column in plot} + +\item{tripsTable}{tibble of trips_output (from \link{read_output_trips()})} +} +\value{ +A plotly object representing the line plot of departure time by activity. +} +\description{ +The \code{plot_deptime_by_act} function generates a line plot to visualize the departure time of trips by activity in a given trips_table tibble. +It provides insights into the number of trips starting at different times for each activity. +} diff --git a/man/plot_distance_by_mainmode_barchart.Rd b/man/plot_distance_by_mainmode_barchart.Rd index 7500cc0..7216645 100644 --- a/man/plot_distance_by_mainmode_barchart.Rd +++ b/man/plot_distance_by_mainmode_barchart.Rd @@ -6,25 +6,27 @@ \usage{ plot_distance_by_mainmode_barchart( trips_table, - unite.modes = character(0), - united.name = "united", + unite_modes = character(0), + united_name = "united", euclidean = FALSE ) } \arguments{ -\item{trips_table}{tibble of trips_output (from readTripsTable())} +\item{trips_table}{tibble of trips_output (from \link{read_output_trips()})} -\item{unite.modes}{vector of character strings, +\item{unite_modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), using the function (\link{process_rename_mainmodes})} -\item{united.name}{character string, specifies the name of the united mode} +\item{united_name}{character string, specifies the name of the united mode} + +\item{euclidean}{Logical value indicating whether to calculate the average as euclidean distance or as travel distance. Default is FALSE, which calculates the average traveled distance.} } \value{ Bar Chart plot of distance traveled per mode } \description{ -Takes the data frame trips_output (from \link{readTripsTable()}), +Takes the data frame trips_output (from \link{read_output_trips()}), to plot a bar chart of the average distance traveled for each main mode, -Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') } diff --git a/man/plot_distance_by_spatialcat_barchart.Rd b/man/plot_distance_by_spatialcat_barchart.Rd index d984c66..7d34ad2 100644 --- a/man/plot_distance_by_spatialcat_barchart.Rd +++ b/man/plot_distance_by_spatialcat_barchart.Rd @@ -4,7 +4,7 @@ \alias{plot_distance_by_spatialcat_barchart} \title{Bar Chart with tripType on x-axis and travelled distance on y-axis XXXX -Takes Table trips_output (from readTripsTable()), +Takes Table trips_output (from \link{read_output_trips()}), to plot bar chart with with values that represent travelled distance of each tripType related to the shapeTable} \usage{ @@ -16,11 +16,13 @@ plot_distance_by_spatialcat_barchart( ) } \arguments{ -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} +\item{trips_table}{tible of trips_output (from \link{read_output_trips()})} + +\item{shape_table}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} -\item{tripsTable}{tible of trips_output (from readTripsTable())} +\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +\item{euclidean}{Logical value indicating whether to calculate the average as euclidean distance or as travel distance. Default is FALSE, which calculates the average traveled distance.} } \value{ Bar Chart plot of distance traveled by spatial type @@ -28,7 +30,7 @@ Bar Chart plot of distance traveled by spatial type \description{ Bar Chart with tripType on x-axis and travelled distance on y-axis XXXX -Takes Table trips_output (from readTripsTable()), +Takes Table trips_output (from \link{read_output_trips()}), to plot bar chart with with values that represent travelled distance of each tripType related to the shapeTable } diff --git a/man/plot_distcat_by_mainmode_barchart.Rd b/man/plot_distcat_by_mainmode_barchart.Rd index bcc8d0c..4c55c85 100644 --- a/man/plot_distcat_by_mainmode_barchart.Rd +++ b/man/plot_distcat_by_mainmode_barchart.Rd @@ -6,26 +6,30 @@ \usage{ plot_distcat_by_mainmode_barchart( trips_table, - unite.modes = character(0), - united.name = "united", + unite_modes = character(0), + united_name = "united", dist_column = "dist_cat", distances_array = c(1000, 2000, 5000, 10000, 20000, 50000, 1e+05) ) } \arguments{ -\item{trips_table}{tibble of trips_output (from readTripsTable())} +\item{trips_table}{tibble of trips_output (from \link{read_output_trips()})} -\item{unite.modes}{vector of character strings, +\item{unite_modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), using the function (\link{process_rename_mainmodes})} -\item{united.name}{character string, specifies the name of the united mode} +\item{united_name}{character string, specifies the name of the united mode} + +\item{dist_column}{A character string specifying the column name in the trips_table tibble that contains the distance categories.} + +\item{distances_array}{A numeric vector defining the distance thresholds for creating distance categories.} } \value{ -Bar Chart plot of count of trips among distance travelled +Plotly bar Chart of count of trips among distance travelled } \description{ -Takes the data frame trips_output (from \link{readTripsTable()}) and categorizes the traveled distances into pre-defined bins +Takes the data frame trips_output (from \link{read_output_trips()}) and categorizes the traveled distances into pre-defined bins to plot a histogram of the traveled distances. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) -Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') } diff --git a/man/plot_mainmode_barchart.Rd b/man/plot_mainmode_barchart.Rd index 189f356..9b6e341 100644 --- a/man/plot_mainmode_barchart.Rd +++ b/man/plot_mainmode_barchart.Rd @@ -6,30 +6,31 @@ \usage{ plot_mainmode_barchart( trips_table, - unite.modes = character(0), - united.name = "united", - dump.output.to = matsimDumpOutputDirectory, + unite_modes = character(0), + united_name = "united", percentage = FALSE ) } \arguments{ -\item{trips_table}{tibble of trips_output (from \link{readTripsTable()})} +\item{trips_table}{tibble of trips_output (from \link{read_output_trips()})} -\item{unite.modes}{vector of character strings, +\item{unite_modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), using the function (\link{process_rename_mainmodes})} -\item{united.name}{character string, specifies the name of the united mode} +\item{united_name}{character string, specifies the name of the united mode} + +\item{percentage}{boolean, by default FALSE, sets if output is given in percentage} } \value{ Bar Chart plot of transport mode distribution, values given in percents } \description{ -Takes the data frame trips_output (from \link{readTripsTable()}) +Takes the data frame trips_output (from \link{read_output_trips()}) to plot a bar chart of the modal split using the column main_mode. } \details{ The modal shares are given in percentages. -Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') } diff --git a/man/plot_mainmode_piechart.Rd b/man/plot_mainmode_piechart.Rd index 9ec835d..76d5802 100644 --- a/man/plot_mainmode_piechart.Rd +++ b/man/plot_mainmode_piechart.Rd @@ -6,19 +6,18 @@ \usage{ plot_mainmode_piechart( trips_table, - unite.modes = character(0), - united.name = "united", - dump.output.to = matsimDumpOutputDirectory + unite_modes = character(0), + united_name = "united" ) } \arguments{ \item{trips_table}{tibble of trips_output (from \link{readTripsTable})} -\item{unite.modes}{vector of character strings, +\item{unite_modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), using the function (\link{process_rename_mainmodes})} -\item{united.name}{character string, specifies the name of the united mode} +\item{united_name}{character string, specifies the name of the united mode} } \value{ pie chart plot of transport mode distribution, values given in percent @@ -29,5 +28,5 @@ to plot a pie chart of the modal split using the column main_mode } \details{ The function automatically detects the modes plots a pie chart. -Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') } diff --git a/man/plot_map_trips.Rd b/man/plot_map_trips.Rd index ed20ca0..fdf848d 100644 --- a/man/plot_map_trips.Rd +++ b/man/plot_map_trips.Rd @@ -2,22 +2,23 @@ % Please edit documentation in R/output_trips.R \name{plot_map_trips} \alias{plot_map_trips} -\title{Plots start and end coordinates of the given trips table on an osm map -XXXX} +\title{Plots start and end coordinates of the given trips table on an osm map} \usage{ plot_map_trips(trips_table, crs, optimized = FALSE, shape_table = NULL) } \arguments{ +\item{trips_table}{tibble of trips_output (from \link{read_output_trips()})} + \item{crs}{numeric representation of the EPSG code or proj4string for the corresponding coordinate system of the trip coordinates, can be found in network file from output directory of MATSim simulation} \item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot} -\item{table}{tibble of trips_output (from readTripsTable())} +\item{shape_table}{A spatial shapefile or spatial polygons dataframe representing the spatial categories. +By default NULL, means there are no specific shape map on the backgroung.} } \value{ -plot with trips +leaflet/ggplot plot with trips start-, end- points } \description{ Plots start and end coordinates of the given trips table on an osm map -XXXX } diff --git a/man/plot_map_trips_by_spatialcat.Rd b/man/plot_map_trips_by_spatialcat.Rd index c9d792e..35ff651 100644 --- a/man/plot_map_trips_by_spatialcat.Rd +++ b/man/plot_map_trips_by_spatialcat.Rd @@ -2,24 +2,22 @@ % Please edit documentation in R/output_trips.R \name{plot_map_trips_by_spatialcat} \alias{plot_map_trips_by_spatialcat} -\title{Plots every type of trips(inside, outside, origin and destinating) on map -XXXX} +\title{Plots every type of trips(inside, outside, origin and destinating) on map} \usage{ plot_map_trips_by_spatialcat(trips_table, shape_table, crs, optimized = FALSE) } \arguments{ -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} +\item{trips_table}{tibble of trips_output (from \link{read_output_trips()})} -\item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot} +\item{shape_table}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} -\item{table}{tibble of trips_output (from readTripsTable())} +\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +\item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot} } \value{ plot that contains every trip with defined trip type } \description{ Plots every type of trips(inside, outside, origin and destinating) on map -XXXX } diff --git a/man/plot_spatialtype_by_shape_piechart.Rd b/man/plot_spatialtype_by_shape_piechart.Rd index 09efa62..0242d28 100644 --- a/man/plot_spatialtype_by_shape_piechart.Rd +++ b/man/plot_spatialtype_by_shape_piechart.Rd @@ -8,11 +8,11 @@ XXXX} plot_spatialtype_by_shape_piechart(trips_table, shape_table, crs) } \arguments{ -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} +\item{trips_table}{tibble of trips_output (from \link{read_output_trips()})} -\item{table}{tibble of trips_output (from readTripsTable())} +\item{shape_table}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} } \value{ plot with percentage of each type of trips diff --git a/man/plot_travelwaittime_mean_barchart.Rd b/man/plot_travelwaittime_mean_barchart.Rd index 310f71c..0b719b6 100644 --- a/man/plot_travelwaittime_mean_barchart.Rd +++ b/man/plot_travelwaittime_mean_barchart.Rd @@ -6,19 +6,22 @@ \usage{ plot_travelwaittime_mean_barchart( trips_table, - unite.modes = character(0), - united.name = "united", + unite_modes = character(0), + united_name = "united", time_format = "minute" ) } \arguments{ \item{trips_table}{tibble of trips_output (from \links{readTripsTable()})} -\item{unite.modes}{vector of character strings, +\item{unite_modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), using the function (\link{process_rename_mainmodes})} -\item{united.name}{character string, specifies the name of the united mode} +\item{united_name}{character string, specifies the name of the united mode} + +\item{time_format}{A character string indicating the desired time format for the output. +The options are "minute", "hour", or "second". The default is "minute".} } \value{ Bar Chart plot of average time spent on travel/wait @@ -26,5 +29,5 @@ Bar Chart plot of average time spent on travel/wait \description{ Takes the data frame trips_output (from \links{readTripsTable()}), to plot a bar chart of travel and wait times. -Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') } diff --git a/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd b/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd index 474ff08..12b474e 100644 --- a/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd +++ b/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd @@ -6,24 +6,26 @@ \usage{ plot_trips_count_by_deptime_and_mainmode_linechart( trips_table, - unite.columns = character(0), - united.name = "united" + unite_modes = character(0), + united_name = "united" ) plot_trips_count_by_deptime_and_mainmode_linechart( trips_table, - unite.columns = character(0), - united.name = "united" + unite_modes = character(0), + united_name = "united" ) } \arguments{ -\item{united.name}{character string, specifies the name of the united mode} +\item{trips_table}{tibble of trips_output (from \link{read_output_trips()})} -\item{tripsTable}{tibble of trips_output (from readTripsTable())} - -\item{unite.modes}{vector of character strings, +\item{unite_modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), using the function (\link{process_rename_mainmodes})} + +\item{united_name}{character string, specifies the name of the united mode} + +\item{tripsTable}{tibble of trips_output (from \link{read_output_trips()})} } \value{ Line plot of trips count by departure time per mode @@ -31,11 +33,11 @@ Line plot of trips count by departure time per mode Line plot of trips count by departure time per mode } \description{ -Takes data frame trips_output (from \link{readTripsTable()}), +Takes data frame trips_output (from \link{read_output_trips()}), to create a line plot of the number of trips for a specific departure time by main_mode -Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') -Takes data frame trips_output (from \link{readTripsTable()}), +Takes data frame trips_output (from \link{read_output_trips()}), to create a line plot of the number of trips for a specific departure time by main_mode -Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') +Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') } diff --git a/man/process_append_spatialcat.Rd b/man/process_append_spatialcat.Rd index 5a87d42..53b8b92 100644 --- a/man/process_append_spatialcat.Rd +++ b/man/process_append_spatialcat.Rd @@ -16,7 +16,7 @@ category representing trips which \strong{outside} of the given shape} process_append_spatialcat(trips_table, shape_table, crs) } \arguments{ -\item{trips_table}{tibble of trips_output (from readTripsTable())} +\item{trips_table}{tibble of trips_output (from \link{read_output_trips()})} \item{shape_table}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} diff --git a/man/process_convert_table_to_sf.Rd b/man/process_convert_table_to_sf.Rd index eeb5f13..ef6a1f8 100644 --- a/man/process_convert_table_to_sf.Rd +++ b/man/process_convert_table_to_sf.Rd @@ -7,7 +7,7 @@ process_convert_table_to_sf(table, crs, geometry.type = st_multipoint()) } \arguments{ -\item{table}{tibble trips_output (from readTripsTable())} +\item{table}{tibble trips_output (from \link{read_output_trips()})} \item{crs}{numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file} diff --git a/man/process_filter_by_shape.Rd b/man/process_filter_by_shape.Rd index 89d40b9..9f01924 100644 --- a/man/process_filter_by_shape.Rd +++ b/man/process_filter_by_shape.Rd @@ -8,7 +8,7 @@ Filters trips_table(from ,\link{readTripsTable}) depending by location using a s process_filter_by_shape(trips_table, shape_table, crs, spatial_type = "inside") } \arguments{ -\item{trips_table}{tibble of trips_output (from readTripsTable())} +\item{trips_table}{tibble of trips_output (from \link{read_output_trips()})} \item{shape_table}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} diff --git a/man/process_get_mainmode_distribution.Rd b/man/process_get_mainmode_distribution.Rd new file mode 100644 index 0000000..d1c74d6 --- /dev/null +++ b/man/process_get_mainmode_distribution.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_get_mainmode_distribution} +\alias{process_get_mainmode_distribution} +\title{Calculates main mode distribution} +\usage{ +process_get_mainmode_distribution(trips_table, percentage = FALSE) +} +\arguments{ +\item{trips_table}{tible of output_trips (from \link{\code{read_output_trips}})} + +\item{percenate}{boolean, by default FALSE, sets if output should be given in percentage} +} +\value{ +tibble that provides the distribution of main modes in the input trips_table. +} +\description{ +The process_get_mainmode_distribution function calculates the distribution of main modes in a given trips_table.\cr +It provides insights into the frequency or percentage of each main mode within the dataset. +} +\details{ +By default, the function counts the occurrences of each main mode in the trips_table tibble and returns the counts for each unique main mode. \cr +Alternatively, when the percentage parameter is set to TRUE, the function normalizes the counts to represent the percentage distribution of each main mode within the dataset. +} diff --git a/man/process_get_od_matrix.Rd b/man/process_get_od_matrix.Rd index 1aec2cd..2825c06 100644 --- a/man/process_get_od_matrix.Rd +++ b/man/process_get_od_matrix.Rd @@ -16,6 +16,10 @@ process_get_od_matrix( ) } \arguments{ +\item{trips_table}{tibble of trips_output (from \link{readTripsTable})} + +\item{shape_path}{string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file)} + \item{crs}{numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file} \item{dump.output.to}{string, path to a folder to save the .csv file} @@ -25,10 +29,6 @@ process_get_od_matrix( \item{colnames}{string, column names can be specified (i.e. to fit the shape file), if not they are numbered} \item{outer}{boolean, determines if flows outside of the shapefile are used, standard value is FALSE} - -\item{tripsTable}{tibble of trips_output (from \link{readTripsTable})} - -\item{shapePath}{string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file)} } \value{ tibble of origin/destination matrix diff --git a/man/process_get_travdistance_distribution.Rd b/man/process_get_travdistance_distribution.Rd new file mode 100644 index 0000000..de86cd1 --- /dev/null +++ b/man/process_get_travdistance_distribution.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_get_travdistance_distribution} +\alias{process_get_travdistance_distribution} +\title{Get Travel Distance Distribution by Main Mode} +\usage{ +process_get_travdistance_distribution(trips_table, euclidean = FALSE) +} +\arguments{ +\item{trips_table}{A tibble of output_trips (from \link{\code{read_output_trips}})} + +\item{euclidean}{Logical value indicating whether to calculate the average as euclidean distance or as travel distance. Default is FALSE, which calculates the average traveled distance.} +} +\value{ +A tibble containing the main_mode column representing unique main modes and the avg_dist column representing the average travel distance for each main mode. +} +\description{ +The \code{process_get_travdistance_distribution} function calculates the distribution of travel distances based on main modes in a given trips_table tibble. It provides insights into the average distance traveled for each main mode. +} diff --git a/man/process_get_travelwaittime_by_mainmode.Rd b/man/process_get_travelwaittime_by_mainmode.Rd new file mode 100644 index 0000000..bff71c7 --- /dev/null +++ b/man/process_get_travelwaittime_by_mainmode.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_get_travelwaittime_by_mainmode} +\alias{process_get_travelwaittime_by_mainmode} +\title{Get Travel and Wait Time by Main Mode} +\usage{ +process_get_travelwaittime_by_mainmode(trips_table, time_format = "minute") +} +\arguments{ +\item{trips_table}{A tibble of output_trips (from \link{\code{read_output_trips}})} + +\item{time_format}{A character string indicating the desired time format for the output. The options are "minute", "hour", or "second". The default is "minute".} +} +\value{ +A tibble containing the main_mode column representing unique main modes, trav_time_avg column representing the average travel time for each main mode, and wait_time_avg column representing the average wait time for each main mode. +} +\description{ +The \code{process_get_travelwaittime_by_mainmode} function calculates the average travel time and average wait time for each main mode in a given trips_table tibble. +} diff --git a/man/process_rename_category.Rd b/man/process_rename_category.Rd new file mode 100644 index 0000000..6543b4e --- /dev/null +++ b/man/process_rename_category.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_rename_category} +\alias{process_rename_category} +\title{Replace Matching Categories of any column with United Name in Tibble} +\usage{ +process_rename_category( + trips_table, + unite_template = character(0), + united_name = "united", + column = "main_mode" +) +} +\arguments{ +\item{trips_table}{tible of output_trips (from \link{\code{read_output_trips}})} + +\item{unite_template}{vector of character string, representing pattern to match categories} + +\item{united_name}{character string, to represent new category for all occurrences matched unite_modes} + +\item{column}{tibble column name, which will be used in occurrences renaming} +} +\value{ +modified trips table tibble +} +\description{ +The \code{process_rename_category} function takes a tibble, trips_table, +as input and replaces all occurrences of categories +that match a given template with another name provided in united_name. +The function provides the flexibility to specify multiple category templates +to be united into a single name. +} diff --git a/man/process_rename_mainmodes.Rd b/man/process_rename_mainmodes.Rd index e35bc72..9beecf6 100644 --- a/man/process_rename_mainmodes.Rd +++ b/man/process_rename_mainmodes.Rd @@ -2,14 +2,28 @@ % Please edit documentation in R/output_trips.R \name{process_rename_mainmodes} \alias{process_rename_mainmodes} -\title{XXXX} +\title{Replace Matching Categories of main_mode with United Name in Tibble} \usage{ process_rename_mainmodes( trips_table, - unite.modes = character(0), - united.name = "united" + unite_modes = character(0), + united_name = "united" ) } +\arguments{ +\item{trips_table}{tible of output_trips (from \link{\code{read_output_trips}})} + +\item{unite_modes}{vector of character string, representing pattern to match categories} + +\item{united_name}{character string, to represent new category for all occurrences matched unite_modes} +} +\value{ +tibble with new main_mode representation +} \description{ -XXXX +The process_rename_mainmodes function takes a tibble, trips_table, +as input and replaces all occurrences in column main_mode of categories +that match a given template with another name provided in united_name. +The function provides the flexibility to specify multiple category templates +to be united into a single name. } From bba446aac3e5f21f3f0a77a27e1af1503abad0a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Tue, 18 Jul 2023 10:12:06 +0200 Subject: [PATCH 61/87] WIP vignettes --- vignettes/Example project.Rmd | 80 +++++++++++++++++++++++++++++++++++ vignettes/Introduction.Rmd | 48 +++++++++++---------- 2 files changed, 105 insertions(+), 23 deletions(-) create mode 100644 vignettes/Example project.Rmd diff --git a/vignettes/Example project.Rmd b/vignettes/Example project.Rmd new file mode 100644 index 0000000..36156bb --- /dev/null +++ b/vignettes/Example project.Rmd @@ -0,0 +1,80 @@ +--- +title: "Example project" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Example project: Leipzig} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include=FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r setup, warning = FALSE} +library(matsim) +``` + +#### Introduction + +This vignette offers an example workflow from MATSim output to thematic plots and maps. For a general overview of the package and its structure please read XXX LINK OTHER VIGNETTE XXX. + +A short recap however: functions are divided into four categories and start with a respective prefix. Read_, process_, plot_ or compare_ and in the future simwrapper_. +To better understand the naming conventions (for example to create your own functions) consult XXXX LINK TO VIGNETTE XXXX. + +#### Installation + +MATSim R is not yet available at CRAN, so to install MATSim R using github use the following code. + +```{r install master,eval=FALSE} +devtools::install_github("matsim-vsp/matsim-r") +``` + +#### Loading the package +Once installed, you can load the MATSim R package using the library() function: +```{r,eval=FALSE} +library(matsim) +``` + +#### Loading data + +The data we'll use in this example project is the result of a Leipzig run which you can find under the following link. XXX MAKE LINK NICE XXX https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/leipzig/projects/namav/base-case/ + +If you want to follow along, download a copy of the folder. + +To start we will load the output_trips.csv.gz file. It is a zipped file but that is okay, the functions can handle that. +```{r,eval=FALSE} + + trips_file_path <- "paste_file_path_here" + + # if you don't want to immediately load the whole file, the function read_output_trips has the option to only load the first n lines + output_trips <- read_output_trips(trips_file_path, n_max = 5000) +``` + +#### Plot a modal split + + + + +## R Markdown + +This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see . + +When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this: + +```{r cars} +summary(cars) +``` + +## Including Plots + +You can also embed plots, for example: + +```{r pressure, echo=FALSE} +plot(pressure) +``` + +Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot. diff --git a/vignettes/Introduction.Rmd b/vignettes/Introduction.Rmd index d95a7a2..281bb65 100644 --- a/vignettes/Introduction.Rmd +++ b/vignettes/Introduction.Rmd @@ -1,8 +1,8 @@ --- -title: "Introduction for Matsim R Library" +title: "Introduction to MATSim R Library" output: rmarkdown::html_vignette vignette: > - %\VignetteIndexEntry{Introduction for Matsim R Library: analyzing transport simulations} + %\VignetteIndexEntry{Introduction to MATSim R Library: analyzing transport simulations} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- @@ -18,40 +18,41 @@ knitr::opts_chunk$set( library(matsim) ``` -### Introduction -Welcome to the matsim package! This vignette will guide you through the process of creating plots using the functions provided by our library. matsim is a powerful R package designed for data process and visualization, with providing a wide range of functions to create high-quality and adjustable plots from processed data. +#### Introduction +Welcome to the MATSim R package! MATSim R is an R package designed for data processing and visualization and provides a wide range of functions to create adjustable plots from processed data. This vignette will give you an overview of the structure of the package and quickly guide you through the process of creating plots using the functions provided by the library. #### Overall concept -The purpose of this package is to provide a comprehensive set of tools and functions for efficiently analyzing output of matsim simulations. The package primarily operates on output data stored in CSV files, specifically those named with the suffix "output_trips", "legs","persons". By adhering to this naming convention, the package offers streamlined functionality for reading, processing, plotting, and utilizing special features via YAML files used in Simwrapper(in development). +The purpose of this package is to provide a comprehensive set of tools to efficiently analyze the output of MATSim runs. The package primarily processes output data stored in CSV and XML files, especially the so called "output_trips", "legs" and "persons" files. By adhering to this standardized naming convention, the package offers a streamlined functionality for reading, processing, plotting and YAML file creation for use in Simwrapper. XXXX LINK TO SIMWRAPPER GITHUB xxxx -The package is organized into four main subcategories, each serving a specific purpose: +![Data flow and concept of matsim r package](../inst/extdata/dataflow.png) -**Reading Functions**: These functions begin with the prefix "read_" and are designed to read and import the simulation output stored in CSV files. By leveraging these functions, users can easily load the necessary data into their R environment for further analysis. +The package is organized into four categories, each serving a specific purpose: -**Processing Functions**: Functions with the prefix "process_" form the core of the package's data manipulation capabilities. Users can apply a variety of transformations and calculations to the loaded output_trips data, allowing for advanced processing and analysis tailored to their specific requirements. Additionally, the processing functionality extends beyond traditional tabular data, as it supports spatial input/output, enabling users to analyze and manipulate spatially referenced transport simulation data. +**Reading Functions**: These functions begin with the prefix "read_" and are designed to read and import the simulation output. Field types are automatically set and a tibble is created. -**Plotting Functions**: With the prefix "plot_," the plotting functions enable users to create insightful visualizations based on the processed output data. These functions offer a range of plotting options, empowering users to explore patterns, trends, and relationships within the transport simulation results. The plotting functions encompass two additional subcategories, namely mapping and comparing. Within the mapping subcategory, users can generate visualizations that overlay simulation results onto geographical maps, providing insights into spatial patterns and distributions. The comparing subcategory offers tools to compare different simulation outputs, facilitating analysis and understanding of variations between scenarios or datasets. +**Processing Functions**: Functions with the prefix "process_" form the core of the package's data manipulation capabilities. Users can apply a variety of transformations and calculations to the loaded tibbles, allowing for advanced processing and analysis tailored to their specific needs. Spatial input/output is also supported, enabling users to manipulate and analyze the data on a spatial level as well. -**Simwrapper**: The simwrapper is a specialized block within the package that facilitates plotting using YAML files in Simwrapper. This feature allows users to define complex plots and visualizations in YAML format, providing a convenient and efficient way to generate custom visual representations of their simulation data. +**Plotting Functions**: The plotting functions with the prefix "plot_" enable users to create visualizations based on the processed output data. These functions offer a range of plotting options, allowing users to explore patterns, trends, and relationships within the simulation results. The plotting functions encompass two additional subcategories, namely ***mapping*** and ***comparing***. Within the mapping subcategory, users can generate visualizations that overlay simulation results onto geographical maps, providing insights into spatial patterns and distributions. The comparing subcategory offers tools to compare different simulation outputs, allowing analysis and understanding of variations between scenarios or data sets. -By following this design philosophy and offering a well-structured collection of functions, matsim R package aims to simplify the analysis of transport simulations. It provides users with an intuitive workflow, from reading and processing the simulation output to generating informative plots and leveraging the power of YAML-based configurations. +**Simwrapper**: The simwrapper category is a specialized group within the package that facilitates plotting using YAML files in Simwrapper. This feature allows users to define complex plots and visualizations in the YAML format, providing a convenient and efficient way to generate custom visual representations of their simulation data. + +With this structure MATSim R aims to simplify the analysis of MATSim runs. It provides users with an intuitive workflow, from reading and processing the simulation output to generating informative plots and leveraging the power of YAML-based configurations. -![Data flow and concept of matsim r package](../inst/extdata/dataflow.png) #### Installation -Matsim is not still available at CRAN, so to install matsim we use github, you can use the following code: +MATSim R is not yet available at CRAN, so to install MATSim R using github, you can use the following code: ```{r install master,eval=FALSE} devtools::install_github("matsim-vsp/matsim-r") ``` -However if you want to have some specific branch in your Rstudio you can specify this branch in the code: +However if you want to use a specific branch it can be specified like so: ```{r install ref,eval=FALSE} devtools::install_github("matsim-vsp/matsim-r", ref = "{name of the branch}") ``` #### Loading the package -Once installed, you can load the matsim package using the library() function: +Once installed, you can load the MATSim R package using the library() function: ```{r,eval=FALSE} library(matsim) ``` @@ -60,11 +61,11 @@ library(matsim) #### Loading Data -The first step in analyzing your transport simulations is to load the output data into your R environment. matsim provides convenient functions with the "read_" prefix for this purpose. Let's take a look at how you can load your simulation output stored in a CSV file: +The first step in analyzing your transport simulations is to load the output data into your R environment. MATSim provides several functions with the "read_" prefix for this purpose. Let's take a look at how you can load your simulation output stored in a CSV file: ```{r reading, warning=FALSE,eval = FALSE} # Specify the file path to your simulation output. -# It can be directory path, or direct path to file +# It can be a directory path or direct path to a file output_file <- "path/to/your/output_trips.csv" # Use the read_csv_trips() function to read the simulation data @@ -76,7 +77,8 @@ You can now proceed to explore and analyze the loaded data. #### Data Processing -Matsim offers a range of processing functions, prefixed with "process_", to manipulate and transform your simulation data. These functions allow you to perform various operations, such as filtering, aggregating, and calculating additional metrics. Let's see an example of applying a transformation to our loaded data: +MATSim R offers a range of processing functions, prefixed with "process_", to manipulate and transform your simulation data. These functions allow you to perform various operations, such as filtering, aggregating, and calculating additional metrics. Let's see an example of applying a transformation to our loaded data: +XXXX IS THE EXAMPLE CORRECT? - filter by shape?? XXXX ```{r processing, warning=FALSE,eval=FALSE} # Filter the trips data to include only weekday trips @@ -90,7 +92,7 @@ Feel free to explore the different processing functions available in the package #### Plotting -Visualizing your simulation data is crucial for gaining insights and effectively communicating your findings. your_package_name provides a wide range of plotting functions to help you create informative visualizations. Let's create a scatter plot to visualize the relationship between trip distance and trip duration: +Visualizing your simulation data is crucial for gaining insights and effectively communicating your findings. MATSim R provides a wide range of plotting functions to help you create informative visualizations. Let's create a scatter plot to visualize the relationship between trip distance and trip duration: ```{r plotting, eval = FALSE} @@ -98,16 +100,16 @@ Visualizing your simulation data is crucial for gaining insights and effectively #plot_scatter(trips_data, x = "distance", y = "duration") ``` -ou can customize the plot appearance and explore other plot types, such as line plots, bar charts, and spatial maps, using the various plotting functions provided by matsim. +You can customize the plot appearance and explore other plot types, such as line plots, bar charts, and spatial maps, using the various plotting functions provided by MATSim R. #### Advanced Features (still in development) -In addition to the fundamental functionalities discussed above, your_package_name offers advanced features to enhance your analysis. For example, you can utilize YAML files in the simwrapper block to define complex plots and visualizations. This allows you to create sophisticated and customized outputs to meet your specific requirements. +- still in development - #### Conclusion -In this vignette, we introduced you to the matsim package, designed specifically for analyzing transport simulations. We hope that you'll have great experience using this library, and we are glad to receive feedback based on your use of package on **some mail/github ** +In this vignette, we introduced you to the MATSim R package, designed specifically for analyzing MATSim outputs. We hope that you'll have a great experience using this library and we are glad to receive feedback at **some mail/github ** XXXX ADD CONTACT XXXX -For more details and specific usage examples, refer to the package documentation and other vignettes available({list of vignettes}). Happy analyzing with matsim! +For more details and specific usage examples, refer to the package documentation and other vignettes available({list of vignettes}). Happy analyzing with MATSim R! From 7723e87979cfe734497ffa2cbd69d8d2bb581b2f Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Tue, 18 Jul 2023 14:22:04 +0200 Subject: [PATCH 62/87] mainmode_piechart percentage fixed --- R/output_trips.R | 19 +++++++++-------- man/plot_distance_by_spatialcat_barchart.Rd | 7 +------ man/process_append_spatialcat.Rd | 23 ++++++--------------- man/process_filter_by_shape.Rd | 2 +- man/process_get_mainmode_distribution.Rd | 2 +- vignettes/Example project.Rmd | 4 ++-- 6 files changed, 21 insertions(+), 36 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 35f007f..249a124 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2382,7 +2382,7 @@ plot_mainmode_piechart <- function(trips_table, # processing # calculates the mode share and saves it as a tibble trips_table_count<-process_get_mainmode_distribution(trips_table, - percentage= percentage) + percentage= FALSE) # plotting @@ -2660,6 +2660,7 @@ plot_spatialtype_by_shape_piechart <- function(trips_table, shape_table, crs) { } #' Bar Chart with tripType on x-axis and travelled distance on y-axis +#' #' XXXX #' Takes Table trips_output (from \link{read_output_trips()}), #' to plot bar chart with with values that represent @@ -3637,7 +3638,7 @@ process_rename_category<-function(trips_table, #' Alternatively, when the percentage parameter is set to TRUE, the function normalizes the counts to represent the percentage distribution of each main mode within the dataset. #' #' @param trips_table tible of output_trips (from \link{\code{read_output_trips}}) -#' @param percenate boolean, by default FALSE, sets if output should be given in percentage +#' @param percentage boolean, by default FALSE, sets if output should be given in percentage #' #' @return tibble that provides the distribution of main modes in the input trips_table. #' @@ -3771,7 +3772,7 @@ process_convert_time <- function(trips_table,time_format = "hour",time_column = #' XXXX finish when code revision is done -#' Filters trips_table(from ,\link{readTripsTable}) depending by location using a shapefile +#' Filters trips_table(from ,\link{read_output_trips()}) depending by location using a shapefile #' #' Uses trips_table and an sf object (can be created using the function st_read()), #' transforms both objects to match a mutual coordinate system (crs) @@ -3855,15 +3856,15 @@ process_filter_by_shape <- function(trips_table, } #' Appending spatial category as additional column to output_trips tibble -#' XXXX +#' #' Takes trips_table and shape_table(sf object from file representing geographical data, can be received by using function st_read(path_to_file). #' Please be aware that this \link{process_filter_by_shape} currently only works, when one geometry is loaded.) #' transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -#' and adds to the output_trips from table spatial category depending on postition related to shape file: -#' category representing trips \strong{inside} of the given shape -#' category representing trips which \strong{originating} in the shape -#' category representing trips which \strong{destinating} in the shape -#' category representing trips which \strong{outside} of the given shape +#' and adds to the output_trips from table spatial category depending on postition related to shape file:\cr +#' category representing trips \strong{inside} of the given shape\cr +#' category representing trips which \strong{originating} in the shape\cr +#' category representing trips which \strong{destinating} in the shape\cr +#' category representing trips which \strong{outside} of the given shape\cr #' #' @param trips_table tibble of trips_output (from \link{read_output_trips()}) #' diff --git a/man/plot_distance_by_spatialcat_barchart.Rd b/man/plot_distance_by_spatialcat_barchart.Rd index 7d34ad2..37b203d 100644 --- a/man/plot_distance_by_spatialcat_barchart.Rd +++ b/man/plot_distance_by_spatialcat_barchart.Rd @@ -2,11 +2,7 @@ % Please edit documentation in R/output_trips.R \name{plot_distance_by_spatialcat_barchart} \alias{plot_distance_by_spatialcat_barchart} -\title{Bar Chart with tripType on x-axis and travelled distance on y-axis -XXXX -Takes Table trips_output (from \link{read_output_trips()}), -to plot bar chart with with values that represent -travelled distance of each tripType related to the shapeTable} +\title{Bar Chart with tripType on x-axis and travelled distance on y-axis} \usage{ plot_distance_by_spatialcat_barchart( trips_table, @@ -28,7 +24,6 @@ plot_distance_by_spatialcat_barchart( Bar Chart plot of distance traveled by spatial type } \description{ -Bar Chart with tripType on x-axis and travelled distance on y-axis XXXX Takes Table trips_output (from \link{read_output_trips()}), to plot bar chart with with values that represent diff --git a/man/process_append_spatialcat.Rd b/man/process_append_spatialcat.Rd index 53b8b92..fd91a3d 100644 --- a/man/process_append_spatialcat.Rd +++ b/man/process_append_spatialcat.Rd @@ -2,16 +2,7 @@ % Please edit documentation in R/output_trips.R \name{process_append_spatialcat} \alias{process_append_spatialcat} -\title{Appending spatial category as additional column to output_trips tibble -XXXX -Takes trips_table and shape_table(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -Please be aware that this \link{process_filter_by_shape} currently only works, when one geometry is loaded.) -transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -and adds to the output_trips from table spatial category depending on postition related to shape file: -category representing trips \strong{inside} of the given shape -category representing trips which \strong{originating} in the shape -category representing trips which \strong{destinating} in the shape -category representing trips which \strong{outside} of the given shape} +\title{Appending spatial category as additional column to output_trips tibble} \usage{ process_append_spatialcat(trips_table, shape_table, crs) } @@ -26,14 +17,12 @@ process_append_spatialcat(trips_table, shape_table, crs) tibble, with additional spatial column related to given shape } \description{ -Appending spatial category as additional column to output_trips tibble -XXXX Takes trips_table and shape_table(sf object from file representing geographical data, can be received by using function st_read(path_to_file). Please be aware that this \link{process_filter_by_shape} currently only works, when one geometry is loaded.) transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -and adds to the output_trips from table spatial category depending on postition related to shape file: -category representing trips \strong{inside} of the given shape -category representing trips which \strong{originating} in the shape -category representing trips which \strong{destinating} in the shape -category representing trips which \strong{outside} of the given shape +and adds to the output_trips from table spatial category depending on postition related to shape file:\cr +category representing trips \strong{inside} of the given shape\cr +category representing trips which \strong{originating} in the shape\cr +category representing trips which \strong{destinating} in the shape\cr +category representing trips which \strong{outside} of the given shape\cr } diff --git a/man/process_filter_by_shape.Rd b/man/process_filter_by_shape.Rd index 9f01924..9ae9bd3 100644 --- a/man/process_filter_by_shape.Rd +++ b/man/process_filter_by_shape.Rd @@ -3,7 +3,7 @@ \name{process_filter_by_shape} \alias{process_filter_by_shape} \title{XXXX finish when code revision is done -Filters trips_table(from ,\link{readTripsTable}) depending by location using a shapefile} +Filters trips_table(from ,\link{read_output_trips()}) depending by location using a shapefile} \usage{ process_filter_by_shape(trips_table, shape_table, crs, spatial_type = "inside") } diff --git a/man/process_get_mainmode_distribution.Rd b/man/process_get_mainmode_distribution.Rd index d1c74d6..d6e8833 100644 --- a/man/process_get_mainmode_distribution.Rd +++ b/man/process_get_mainmode_distribution.Rd @@ -9,7 +9,7 @@ process_get_mainmode_distribution(trips_table, percentage = FALSE) \arguments{ \item{trips_table}{tible of output_trips (from \link{\code{read_output_trips}})} -\item{percenate}{boolean, by default FALSE, sets if output should be given in percentage} +\item{percentage}{boolean, by default FALSE, sets if output should be given in percentage} } \value{ tibble that provides the distribution of main modes in the input trips_table. diff --git a/vignettes/Example project.Rmd b/vignettes/Example project.Rmd index 36156bb..7da798c 100644 --- a/vignettes/Example project.Rmd +++ b/vignettes/Example project.Rmd @@ -65,7 +65,7 @@ This is an R Markdown document. Markdown is a simple formatting syntax for autho When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this: -```{r cars} +```{r cars, eval = FALSE} summary(cars) ``` @@ -73,7 +73,7 @@ summary(cars) You can also embed plots, for example: -```{r pressure, echo=FALSE} +```{r pressure, echo=FALSE,eval = FALSE} plot(pressure) ``` From caf8026aa34f833c59841946468bd842196185bd Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Tue, 18 Jul 2023 14:59:02 +0200 Subject: [PATCH 63/87] fixed euclidian->eucidean problem --- R/output_trips.R | 4 ++-- man/plot_distance_by_spatialcat_barchart.Rd | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 249a124..38eb76e 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2675,7 +2675,7 @@ plot_spatialtype_by_shape_piechart <- function(trips_table, shape_table, crs) { #' @return Bar Chart plot of distance traveled by spatial type #' #' @export -plot_distance_by_spatialcat_barchart <- function(trips_table, shape_table, crs, euclidian = FALSE) { +plot_distance_by_spatialcat_barchart <- function(trips_table, shape_table, crs, euclidean = FALSE) { #processing @@ -3668,7 +3668,7 @@ process_get_travdistance_distribution<-function(trips_table,euclidean = FALSE){ trips_table = trips_table %>% group_by(main_mode) %>% - summarize(avg_dist = if_else(euclidian,mean(euclidean_distance),mean(traveled_distance))) + summarize(avg_dist = if_else(euclidean,mean(euclidean_distance),mean(traveled_distance))) return(trips_table) } diff --git a/man/plot_distance_by_spatialcat_barchart.Rd b/man/plot_distance_by_spatialcat_barchart.Rd index 37b203d..d3d54e1 100644 --- a/man/plot_distance_by_spatialcat_barchart.Rd +++ b/man/plot_distance_by_spatialcat_barchart.Rd @@ -8,7 +8,7 @@ plot_distance_by_spatialcat_barchart( trips_table, shape_table, crs, - euclidian = FALSE + euclidean = FALSE ) } \arguments{ From 55a452d099f4a5de334574c5f6f954a3b42990c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Tue, 18 Jul 2023 16:15:54 +0200 Subject: [PATCH 64/87] WIP example vignette --- inst/extdata/Leipzig_modal_split.png | Bin 0 -> 1425637 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 inst/extdata/Leipzig_modal_split.png diff --git a/inst/extdata/Leipzig_modal_split.png b/inst/extdata/Leipzig_modal_split.png new file mode 100644 index 0000000000000000000000000000000000000000..be5e6b580ef0dd341ec5d80c489f973278070a69 GIT binary patch literal 1425637 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 DDnyCX literal 0 HcmV?d00001 From 3b02a42f490b51e96d3b8803439de13b06d40f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Tue, 18 Jul 2023 16:24:03 +0200 Subject: [PATCH 65/87] WIP example vignette --- vignettes/Example project.Rmd | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/vignettes/Example project.Rmd b/vignettes/Example project.Rmd index 7da798c..c733ba7 100644 --- a/vignettes/Example project.Rmd +++ b/vignettes/Example project.Rmd @@ -43,9 +43,12 @@ library(matsim) The data we'll use in this example project is the result of a Leipzig run which you can find under the following link. XXX MAKE LINK NICE XXX https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/leipzig/projects/namav/base-case/ +The shape file can be found here: +https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/leipzig/leipzig-v1.1/input/shp/ + If you want to follow along, download a copy of the folder. -To start we will load the output_trips.csv.gz file. It is a zipped file but that is okay, the functions can handle that. +To start we will load the output_trips.csv.gz file. It is a zipped file but that is okay, the functions can handle that. We will also load a shape file. ```{r,eval=FALSE} trips_file_path <- "paste_file_path_here" @@ -56,8 +59,19 @@ To start we will load the output_trips.csv.gz file. It is a zipped file but that #### Plot a modal split +There are two functions to calculate and plot modal splits: plot_mainmode_piechart() and plot_mainmode_piechart(). As the name suggests the first one plots the modal split as a pie chart and the second one as a bar chart. To do this, they use the processing function process_get_mainmode_distribution() and plot the resulting table. The processing function can also be used on its own to just get the raw numbers. + +We are going to plot a bar chart: + +```{r,eval=FALSE} + + plot_mainmode_barchart(output_trips) + +``` +The resulting bar chart looks like this: +![Leipzig modal split](../inst/extdata/Leipzig_modal_split.png) ## R Markdown From 293dc9e3c5b48ead5705a296e650b418651ec824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Tue, 18 Jul 2023 16:26:16 +0200 Subject: [PATCH 66/87] fixed a typo --- R/output_trips.R | 44 ++------------------------------------------ 1 file changed, 2 insertions(+), 42 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 919c8c5..c433243 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2594,13 +2594,13 @@ plot_distance_by_mainmode_barchart <- function(trips_table, #' #' @export plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, - unite.columns = character(0), + unite.modes = character(0), united.name = "united") { # If some columns should be united trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, + unite.modes = unite.modes, united.name = united.name) @@ -2678,46 +2678,6 @@ plot_distance_by_spatialcat_barchart <- function(trips_table, shape_table, crs, fig return(fig) } -#' Line plot with departure time on x-axis and number of trips on y-axis -#' -#' Takes the data frame output_trips (from \link{read_output_trips()}), -#' to create a line plot of the number of trips for a specific departure time by main_mode -#' Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') -#' -#' -#' @param tripsTable tibble of output_trips (from read_output_trips()) -#' @param unite.modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united.name character string, specifies the name of the united mode -#' @return Line plot of trips count by departure time per mode -#' -#' @export -plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, - unite.columns = character(0), - united.name = "united") { - - - # If some columns should be united - trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, - united.name = united.name) - - - #processing - tripsTable = tripsTable %>% - mutate(dep_time = hour(dep_time)) %>% - count(dep_time,main_mode) - - - #plotting - fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) - fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") - - fig - return(fig) -} - #' Line chart of the arrival time by destination activity #' XXXX function still needs to be updated? From b7ce241274cb9df22e5945bfd1f26babc174ecb0 Mon Sep 17 00:00:00 2001 From: j-bnsch <78746351+j-bnsch@users.noreply.github.com> Date: Tue, 18 Jul 2023 16:50:15 +0200 Subject: [PATCH 67/87] fixed typos --- R/output_trips.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index c433243..4299a5e 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2605,12 +2605,12 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, #processing - tripsTable = tripsTable %>% + tripsTable = trips_table %>% mutate(dep_time = hour(dep_time)) %>% count(dep_time,main_mode) #plotting - fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) + fig = plot_ly(trips_table,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") fig From 986374e970f457d8afcfdc353b7c5249932018dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Tue, 18 Jul 2023 17:30:05 +0200 Subject: [PATCH 68/87] WIP example vignette --- vignettes/Example project.Rmd | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/vignettes/Example project.Rmd b/vignettes/Example project.Rmd index c733ba7..e7a6f81 100644 --- a/vignettes/Example project.Rmd +++ b/vignettes/Example project.Rmd @@ -72,6 +72,32 @@ We are going to plot a bar chart: The resulting bar chart looks like this: ![Leipzig modal split](../inst/extdata/Leipzig_modal_split.png) +#### Spatial filter + +In a next step we want to spatially filter our data. So far we have been looking at all the trips in the simulation, now we want to focus on those that touch our project area. + +To do this we can use the function process_filter_by_shape() and the shape file we've already loaded. The parameter crs is the coordinate system number and the spatial_type describes the way the trips interact with the project area. The four options are inside, outside, originating and destinating. In this case we will look at the originating trips. + + +```{r, eval = FALSE} +trips_originating <- process_filter_by_shape(output_trips, leipzig_shp, crs = 25832, spatial_type = "originating" ) +``` + +Using plot_mainmode_barchart() once more on the 507 originating trips, results in the following chart: + +![Leipzig modal split - trips originating in project area](../inst/extdata/Leipzig_modalsplit_originating.png) + +#### Comparison plots + +In a next step we will compare the modal split of this base model with the modal split of a scenario. To do this we need to load the output_trips file from a scenario, e.g. this one. https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/leipzig/projects/namav/drt-outskirts/ XXXX NICE LINK XXXX + +```{r, eval = FALSE} + +output_trips_scenario <- read_output_trips(trips_file_scenario_path, n_max = 5000) + +trips_scenario_originating <- process_filter_by_shape(output_trips_scenario, leipzig_shp, crs = 25832, spatial_type = "originating") + +``` ## R Markdown From ac52436ae64a779cbbf7a21032c92c4d39be00d0 Mon Sep 17 00:00:00 2001 From: j-bnsch <78746351+j-bnsch@users.noreply.github.com> Date: Tue, 18 Jul 2023 17:36:27 +0200 Subject: [PATCH 69/87] fixed typos --- R/output_trips.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 4299a5e..4224d25 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2861,11 +2861,11 @@ plot_compare_mainmode_barchart <- function(trips_table1, trips_table2, unite.modes = character(0), united.name = "united") { # renaming/uniting of modes - trips_table1 <- process_rename_mainmodes(trips_table = trips_table, + trips_table1 <- process_rename_mainmodes(trips_table = trips_table1, unite.modes = unite.modes, united.name = united.name) - trips_table2 <- process_rename_mainmodes(trips_table = trips_table, + trips_table2 <- process_rename_mainmodes(trips_table = trips_table2, unite.modes = unite.modes, united.name = united.name) From 7fa71975feb6a9ca95ddcde3af8f00fcfe1df328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Tue, 18 Jul 2023 18:43:46 +0200 Subject: [PATCH 70/87] Example vignette - links still need fixing --- vignettes/Example project.Rmd | 64 +++++++++++++++++------------------ 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/vignettes/Example project.Rmd b/vignettes/Example project.Rmd index e7a6f81..94e3395 100644 --- a/vignettes/Example project.Rmd +++ b/vignettes/Example project.Rmd @@ -14,107 +14,105 @@ knitr::opts_chunk$set( ) ``` -```{r setup, warning = FALSE} -library(matsim) -``` +The data used in this example project can be found on the [public repository] (https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/) from VSP Berlin. There you can also find other MATSim scenarios. #### Introduction -This vignette offers an example workflow from MATSim output to thematic plots and maps. For a general overview of the package and its structure please read XXX LINK OTHER VIGNETTE XXX. +This vignette offers an example workflow from MATSim output to thematic plots and maps. For a general overview of the package and its structure please read the introduction. A short recap however: functions are divided into four categories and start with a respective prefix. Read_, process_, plot_ or compare_ and in the future simwrapper_. -To better understand the naming conventions (for example to create your own functions) consult XXXX LINK TO VIGNETTE XXXX. +To better understand the naming conventions (for example to create your own functions) consult this vignette [LINK]. #### Installation -MATSim R is not yet available at CRAN, so to install MATSim R using github use the following code. +MATSim R is not yet available at CRAN, so to install MATSim R using github, use the following code. ```{r install master,eval=FALSE} devtools::install_github("matsim-vsp/matsim-r") ``` + #### Loading the package + Once installed, you can load the MATSim R package using the library() function: ```{r,eval=FALSE} library(matsim) +library(sf) ``` -#### Loading data -The data we'll use in this example project is the result of a Leipzig run which you can find under the following link. XXX MAKE LINK NICE XXX https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/leipzig/projects/namav/base-case/ +#### Loading data -The shape file can be found here: -https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/leipzig/leipzig-v1.1/input/shp/ +The data we'll use in this example project is the result of a Leipzig run which you can find under the following link. (https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/leipzig/projects/namav/base-case/) If you want to follow along, download a copy of the folder. -To start we will load the output_trips.csv.gz file. It is a zipped file but that is okay, the functions can handle that. We will also load a shape file. -```{r,eval=FALSE} +To start, we will load the output_trips.csv.gz file. It is a zipped file, but that is okay, the functions can handle that. We will also load a shape file, which can be found here. (https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/leipzig/leipzig-v1.1/input/shp/) +```{r,eval=FALSE} trips_file_path <- "paste_file_path_here" # if you don't want to immediately load the whole file, the function read_output_trips has the option to only load the first n lines output_trips <- read_output_trips(trips_file_path, n_max = 5000) ``` + #### Plot a modal split -There are two functions to calculate and plot modal splits: plot_mainmode_piechart() and plot_mainmode_piechart(). As the name suggests the first one plots the modal split as a pie chart and the second one as a bar chart. To do this, they use the processing function process_get_mainmode_distribution() and plot the resulting table. The processing function can also be used on its own to just get the raw numbers. +There are two functions to calculate and plot modal splits: `plot_mainmode_piechart()` and `plot_mainmode_piechart()`. As the name suggests the first one plots the modal split as a pie chart and the second one as a bar chart. To do this, they use the processing function `process_get_mainmode_distribution()` and plot the resulting table. The processing function can also be used on its own to just get the raw numbers. We are going to plot a bar chart: ```{r,eval=FALSE} - plot_mainmode_barchart(output_trips) - ``` The resulting bar chart looks like this: ![Leipzig modal split](../inst/extdata/Leipzig_modal_split.png) + #### Spatial filter In a next step we want to spatially filter our data. So far we have been looking at all the trips in the simulation, now we want to focus on those that touch our project area. -To do this we can use the function process_filter_by_shape() and the shape file we've already loaded. The parameter crs is the coordinate system number and the spatial_type describes the way the trips interact with the project area. The four options are inside, outside, originating and destinating. In this case we will look at the originating trips. - +To do this we can use the function `process_filter_by_shape()` and the shape file we've already loaded. The parameter `crs` is the coordinate system number and the spatial_type describes the way the trips interact with the project area. The four options are inside, outside, originating and destinating. In this case we will look at the originating trips. ```{r, eval = FALSE} trips_originating <- process_filter_by_shape(output_trips, leipzig_shp, crs = 25832, spatial_type = "originating" ) ``` -Using plot_mainmode_barchart() once more on the 507 originating trips, results in the following chart: +Using `plot_mainmode_barchart()` on the 507 originating trips, results in the following chart: ![Leipzig modal split - trips originating in project area](../inst/extdata/Leipzig_modalsplit_originating.png) + #### Comparison plots -In a next step we will compare the modal split of this base model with the modal split of a scenario. To do this we need to load the output_trips file from a scenario, e.g. this one. https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/leipzig/projects/namav/drt-outskirts/ XXXX NICE LINK XXXX +In a next step we will compare the modal split of this base model with the modal split of a scenario. To do this we need to load the output_trips file from a scenario, e.g. this one. https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/leipzig/projects/namav/drt-outskirts/ ```{r, eval = FALSE} - +#loading the scenario data output_trips_scenario <- read_output_trips(trips_file_scenario_path, n_max = 5000) +#filtering the scenario data trips_scenario_originating <- process_filter_by_shape(output_trips_scenario, leipzig_shp, crs = 25832, spatial_type = "originating") +#creating the comparison plot +plot_compare_mainmode_barchart(trips_originating, trips_scenario_originating) ``` -## R Markdown +The resulting plot looks like this: +![Leipzig modal split comparison](../inst/extdata/Leipzig_modalsplit_comparison.png) -This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see . -When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this: +#### Maps -```{r cars, eval = FALSE} -summary(cars) -``` - -## Including Plots - -You can also embed plots, for example: +The package also allows the plotting of spatial data. As an example we can plot the trips originating in the project area to see where they end. -```{r pressure, echo=FALSE,eval = FALSE} -plot(pressure) +```{r,eval=FALSE} +plot_map_trips(trips_originating, crs = 25832) ``` -Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot. +The result is an interactive map using leaflet, showing the places of origin in blue and the destinations in red. (The following image is a screenshot) + +![Leipzig - originating trips](../inst/extdata/Leipzig_map.png) From d3a67e1822d299dec0f26f9136afb58d79a60dde Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 20 Jul 2023 13:43:18 +0200 Subject: [PATCH 71/87] fixed documentation, changed vignettes titles --- R/output_trips.R | 16 ++++++++-------- man/plot_mainmode_piechart.Rd | 4 ++-- man/plot_travelwaittime_mean_barchart.Rd | 4 ++-- man/process_convert_table_to_sf.Rd | 4 ++-- man/process_get_mainmode_distribution.Rd | 2 +- man/process_get_od_matrix.Rd | 2 +- vignettes/Example project.Rmd | 2 +- vignettes/Introduction.Rmd | 14 +++++++------- vignettes/Namings.Rmd | 19 +++++++++++++++++++ 9 files changed, 43 insertions(+), 24 deletions(-) create mode 100644 vignettes/Namings.Rmd diff --git a/R/output_trips.R b/R/output_trips.R index 38eb76e..e168e33 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2356,13 +2356,13 @@ read_output_trips <- function(input_path = ".", n_max = Inf) { #' Plot the distribution of modes as a pie chart #' -#' Uses the dataframe trips_output (from \link{readTripsTable}), +#' Uses the dataframe trips_output (from \link{read_output_trips}), #' to plot a pie chart of the modal split using the column main_mode #' #' The function automatically detects the modes plots a pie chart. #' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') #' -#' @param trips_table tibble of trips_output (from \link{readTripsTable}) +#' @param trips_table tibble of trips_output (from \link{read_output_trips}) #' @param unite_modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) @@ -2441,12 +2441,12 @@ plot_mainmode_barchart <- function(trips_table, #' Plot travel and wait time for each mode as a bar chart #' -#' Takes the data frame trips_output (from \links{readTripsTable()}), +#' Takes the data frame trips_output (from \link{readTripsTable()}), #' to plot a bar chart of travel and wait times. #' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') #' #' -#' @param trips_table tibble of trips_output (from \links{readTripsTable()}) +#' @param trips_table tibble of trips_output (from \link{readTripsTable()}) #' @param unite_modes vector of character strings, #' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), #' using the function (\link{process_rename_mainmodes}) @@ -3637,7 +3637,7 @@ process_rename_category<-function(trips_table, #' By default, the function counts the occurrences of each main mode in the trips_table tibble and returns the counts for each unique main mode. \cr #' Alternatively, when the percentage parameter is set to TRUE, the function normalizes the counts to represent the percentage distribution of each main mode within the dataset. #' -#' @param trips_table tible of output_trips (from \link{\code{read_output_trips}}) +#' @param trips_table tible of output_trips (from \link{read_output_trips}) #' @param percentage boolean, by default FALSE, sets if output should be given in percentage #' #' @return tibble that provides the distribution of main modes in the input trips_table. @@ -3966,7 +3966,7 @@ process_get_crs_from_config <- function(config_path) { #' or for simwrapper (origin and destination as columns) #' #' -#' @param trips_table tibble of trips_output (from \link{readTripsTable}) +#' @param trips_table tibble of trips_output (from \link{read_output_trips}) #' #' @param shape_path string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file) #' @@ -4079,9 +4079,9 @@ process_get_od_matrix<- function(trips_table, -#' Transforms the data frame trips_output (from \links{readTripsTable}) from tibble to sf (table with geometry features) +#' Transforms the data frame trips_output (from \link{read_output_trips}) from tibble to sf (table with geometry features) #' -#' Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features.\cr +#' Transforms the data frame trips_output (from \link{read_output_trips}) into an sf object using start_x, end_x, start_y, end_y as geometry features.\cr #' If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format),\cr #' if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt.\cr #' Added column/columns are projected to given CRS (coordinate reference system).\cr diff --git a/man/plot_mainmode_piechart.Rd b/man/plot_mainmode_piechart.Rd index 76d5802..50b2f92 100644 --- a/man/plot_mainmode_piechart.Rd +++ b/man/plot_mainmode_piechart.Rd @@ -11,7 +11,7 @@ plot_mainmode_piechart( ) } \arguments{ -\item{trips_table}{tibble of trips_output (from \link{readTripsTable})} +\item{trips_table}{tibble of trips_output (from \link{read_output_trips})} \item{unite_modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), @@ -23,7 +23,7 @@ using the function (\link{process_rename_mainmodes})} pie chart plot of transport mode distribution, values given in percent } \description{ -Uses the dataframe trips_output (from \link{readTripsTable}), +Uses the dataframe trips_output (from \link{read_output_trips}), to plot a pie chart of the modal split using the column main_mode } \details{ diff --git a/man/plot_travelwaittime_mean_barchart.Rd b/man/plot_travelwaittime_mean_barchart.Rd index 0b719b6..423901d 100644 --- a/man/plot_travelwaittime_mean_barchart.Rd +++ b/man/plot_travelwaittime_mean_barchart.Rd @@ -12,7 +12,7 @@ plot_travelwaittime_mean_barchart( ) } \arguments{ -\item{trips_table}{tibble of trips_output (from \links{readTripsTable()})} +\item{trips_table}{tibble of trips_output (from \link{readTripsTable()})} \item{unite_modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), @@ -27,7 +27,7 @@ The options are "minute", "hour", or "second". The default is "minute".} Bar Chart plot of average time spent on travel/wait } \description{ -Takes the data frame trips_output (from \links{readTripsTable()}), +Takes the data frame trips_output (from \link{readTripsTable()}), to plot a bar chart of travel and wait times. Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') } diff --git a/man/process_convert_table_to_sf.Rd b/man/process_convert_table_to_sf.Rd index ef6a1f8..9d5b357 100644 --- a/man/process_convert_table_to_sf.Rd +++ b/man/process_convert_table_to_sf.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/output_trips.R \name{process_convert_table_to_sf} \alias{process_convert_table_to_sf} -\title{Transforms the data frame trips_output (from \links{readTripsTable}) from tibble to sf (table with geometry features)} +\title{Transforms the data frame trips_output (from \link{read_output_trips}) from tibble to sf (table with geometry features)} \usage{ process_convert_table_to_sf(table, crs, geometry.type = st_multipoint()) } @@ -20,7 +20,7 @@ process_convert_table_to_sf(table, crs, geometry.type = st_multipoint()) sf object (data frame with geometries depending on geometry.type) } \description{ -Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features.\cr +Transforms the data frame trips_output (from \link{read_output_trips}) into an sf object using start_x, end_x, start_y, end_y as geometry features.\cr If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format),\cr if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt.\cr Added column/columns are projected to given CRS (coordinate reference system).\cr diff --git a/man/process_get_mainmode_distribution.Rd b/man/process_get_mainmode_distribution.Rd index d6e8833..94c2cea 100644 --- a/man/process_get_mainmode_distribution.Rd +++ b/man/process_get_mainmode_distribution.Rd @@ -7,7 +7,7 @@ process_get_mainmode_distribution(trips_table, percentage = FALSE) } \arguments{ -\item{trips_table}{tible of output_trips (from \link{\code{read_output_trips}})} +\item{trips_table}{tible of output_trips (from \link{read_output_trips})} \item{percentage}{boolean, by default FALSE, sets if output should be given in percentage} } diff --git a/man/process_get_od_matrix.Rd b/man/process_get_od_matrix.Rd index 2825c06..a2cc88a 100644 --- a/man/process_get_od_matrix.Rd +++ b/man/process_get_od_matrix.Rd @@ -16,7 +16,7 @@ process_get_od_matrix( ) } \arguments{ -\item{trips_table}{tibble of trips_output (from \link{readTripsTable})} +\item{trips_table}{tibble of trips_output (from \link{read_output_trips})} \item{shape_path}{string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file)} diff --git a/vignettes/Example project.Rmd b/vignettes/Example project.Rmd index 94e3395..943cccd 100644 --- a/vignettes/Example project.Rmd +++ b/vignettes/Example project.Rmd @@ -1,5 +1,5 @@ --- -title: "Example project" +title: "Example project: Leipzig" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Example project: Leipzig} diff --git a/vignettes/Introduction.Rmd b/vignettes/Introduction.Rmd index 281bb65..9ed8477 100644 --- a/vignettes/Introduction.Rmd +++ b/vignettes/Introduction.Rmd @@ -1,5 +1,5 @@ --- -title: "Introduction to MATSim R Library" +title: "Introduction to MATSim R Library: analyzing transport simulations" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Introduction to MATSim R Library: analyzing transport simulations} @@ -82,10 +82,10 @@ XXXX IS THE EXAMPLE CORRECT? - filter by shape?? XXXX ```{r processing, warning=FALSE,eval=FALSE} # Filter the trips data to include only weekday trips -#weekday_trips <- process_filter_by_shape(trips_data) +weekday_trips <- process_filter_by_shape(trips_data) # Calculate the average trip duration -#average_duration <- process_calculate_average_duration(weekday_trips) +average_duration <- process_get_travelwaittime_by_mainmode(weekday_trips) ``` Feel free to explore the different processing functions available in the package to suit your specific analysis requirements. @@ -96,8 +96,8 @@ Visualizing your simulation data is crucial for gaining insights and effectively ```{r plotting, eval = FALSE} -# Create a scatter plot of trip distance against trip duration -#plot_scatter(trips_data, x = "distance", y = "duration") +# Create a scatter plot of trip distance among different main modes +plot_distance_by_mainmode_barchart(trips_data, x = "distance", y = "duration") ``` You can customize the plot appearance and explore other plot types, such as line plots, bar charts, and spatial maps, using the various plotting functions provided by MATSim R. @@ -110,6 +110,6 @@ You can customize the plot appearance and explore other plot types, such as line #### Conclusion -In this vignette, we introduced you to the MATSim R package, designed specifically for analyzing MATSim outputs. We hope that you'll have a great experience using this library and we are glad to receive feedback at **some mail/github ** XXXX ADD CONTACT XXXX +In this vignette, we introduced you to the MATSim R package, designed specifically for analyzing MATSim outputs. We hope that you'll have a great experience using this library and we are glad to receive feedback at **https://github.com/matsim-vsp/matsim-r/tree/master** or at mail **soboliev@vsp.tu-berlin.de** -For more details and specific usage examples, refer to the package documentation and other vignettes available({list of vignettes}). Happy analyzing with MATSim R! +For more details and specific usage examples, refer to the package documentation and other vignettes available. Happy analyzing with MATSim R! diff --git a/vignettes/Namings.Rmd b/vignettes/Namings.Rmd new file mode 100644 index 0000000..5465b6a --- /dev/null +++ b/vignettes/Namings.Rmd @@ -0,0 +1,19 @@ +--- +title: "Namings" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Namings} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r setup} +library(matsim) +``` From cda416405fd27daff1e344d61a85bec4ffcd061b Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 20 Jul 2023 13:45:49 +0200 Subject: [PATCH 72/87] fixing plot_trips_count_by_deptime_and_mainmode_linechart --- R/output_trips.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index e168e33..2d050ae 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2612,12 +2612,12 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, #processing - tripsTable = tripsTable %>% + trips_table = trips_table %>% mutate(dep_time = hour(dep_time)) %>% count(dep_time,main_mode) #plotting - fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) + fig = plot_ly(trips_table,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") fig From 174e376d570c73889b69c3b0c59ad77d526387c2 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Thu, 20 Jul 2023 13:49:07 +0200 Subject: [PATCH 73/87] fixed plot_trips_count_by_deptime_and_mainmode_linechart --- R/output_trips.R | 43 +------------------ ...count_by_deptime_and_mainmode_linechart.Rd | 14 ------ 2 files changed, 2 insertions(+), 55 deletions(-) diff --git a/R/output_trips.R b/R/output_trips.R index 2d050ae..24c063f 100644 --- a/R/output_trips.R +++ b/R/output_trips.R @@ -2585,45 +2585,6 @@ plot_distance_by_mainmode_barchart <- function(trips_table, } -#' Line plot with departure time on x-axis and number of trips on y-axis -#' -#' Takes data frame trips_output (from \link{read_output_trips()}), -#' to create a line plot of the number of trips for a specific departure time by main_mode -#' Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') -#' -#' -#' @param tripsTable tibble of trips_output (from \link{read_output_trips()}) -#' @param unite_modes vector of character strings, -#' changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), -#' using the function (\link{process_rename_mainmodes}) -#' @param united_name character string, specifies the name of the united mode -#' @return Line plot of trips count by departure time per mode -#' -#' @export -plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, - unite.columns = character(0), - united_name = "united") { - - - # If some columns should be united - trips_table <- process_rename_mainmodes(trips_table = trips_table, - unite.columns = unite.columns, - united_name = united_name) - - - #processing - trips_table = trips_table %>% - mutate(dep_time = hour(dep_time)) %>% - count(dep_time,main_mode) - - #plotting - fig = plot_ly(trips_table,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) - fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") - - fig - return(fig) -} - #' Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart #' XXXX #' @@ -2715,13 +2676,13 @@ plot_trips_count_by_deptime_and_mainmode_linechart <- function(trips_table, #processing - tripsTable = tripsTable %>% + trips_table = trips_table %>% mutate(dep_time = hour(dep_time)) %>% count(dep_time,main_mode) #plotting - fig = plot_ly(tripsTable,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) + fig = plot_ly(trips_table,x = ~dep_time,y = ~n,type = "scatter",mode = "line",linetype = ~main_mode) fig = fig %>% layout(yaxis = list(title = "Count of trips per departure Time"),barmode = "group") fig diff --git a/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd b/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd index 12b474e..24fd9d6 100644 --- a/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd +++ b/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd @@ -4,12 +4,6 @@ \alias{plot_trips_count_by_deptime_and_mainmode_linechart} \title{Line plot with departure time on x-axis and number of trips on y-axis} \usage{ -plot_trips_count_by_deptime_and_mainmode_linechart( - trips_table, - unite_modes = character(0), - united_name = "united" -) - plot_trips_count_by_deptime_and_mainmode_linechart( trips_table, unite_modes = character(0), @@ -24,19 +18,11 @@ changes names of chosen modes in the column main_mode to a new chosen name (i.e. using the function (\link{process_rename_mainmodes})} \item{united_name}{character string, specifies the name of the united mode} - -\item{tripsTable}{tibble of trips_output (from \link{read_output_trips()})} } \value{ -Line plot of trips count by departure time per mode - Line plot of trips count by departure time per mode } \description{ -Takes data frame trips_output (from \link{read_output_trips()}), -to create a line plot of the number of trips for a specific departure time by main_mode -Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') - Takes data frame trips_output (from \link{read_output_trips()}), to create a line plot of the number of trips for a specific departure time by main_mode Using the parameter unite_modes, specific modes can be renamed into one with the name specified with united_name (by default 'united') From f04228db872cbdc8afcc804635e2b01f2a2bc74b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johanna=20B=C3=A4nsch?= Date: Fri, 21 Jul 2023 09:34:03 +0200 Subject: [PATCH 74/87] added screenshots --- inst/extdata/Leipzig_map.png | Bin 0 -> 1944073 bytes .../extdata/Leipzig_modalsplit_comparison.png | Bin 0 -> 1429505 bytes .../Leipzig_modalsplit_originating.png | Bin 0 -> 1436909 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 inst/extdata/Leipzig_map.png create mode 100644 inst/extdata/Leipzig_modalsplit_comparison.png create mode 100644 inst/extdata/Leipzig_modalsplit_originating.png diff --git a/inst/extdata/Leipzig_map.png b/inst/extdata/Leipzig_map.png new file mode 100644 index 0000000000000000000000000000000000000000..f728f7831081decdf836c8d0106c633a7989c297 GIT binary patch literal 1944073 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

glt# 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�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

cnJH!1uL3N4{jYljC*om`;Sqi4Uwv!a2AE1d5d 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 literal 0 HcmV?d00001 From 76eb0cd893f79bffde7ace86a2716a4945c9299b Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Fri, 21 Jul 2023 14:51:39 +0200 Subject: [PATCH 75/87] ran after document() --- man/matsimr-deprecated.Rd | 8 +- man/plot_arrtime_by_act.Rd | 24 +- ...ot_compare_count_by_spatialcat_barchart.Rd | 26 +- ...ot_compare_distcat_by_mainmode_barchart.Rd | 8 +- man/plot_compare_mainmode_barchart.Rd | 6 +- man/plot_compare_mainmode_sankey.Rd | 6 +- ...plot_compare_travelwaittime_by_mainmode.Rd | 6 +- ...are_travelwaittime_by_mainmode_barchart.Rd | 11 +- man/plot_distance_by_mainmode_barchart.Rd | 4 +- man/plot_distance_by_spatialcat_barchart.Rd | 23 +- man/plot_distcat_by_mainmode_barchart.Rd | 4 +- man/plot_mainmode_barchart.Rd | 4 +- man/plot_mainmode_piechart.Rd | 4 +- man/plot_map_trips.Rd | 14 +- man/plot_map_trips_by_spatialcat.Rd | 15 +- man/plot_spatialtype_by_shape_piechart.Rd | 16 +- man/plot_travelwaittime_mean_barchart.Rd | 4 +- ...count_by_deptime_and_mainmode_linechart.Rd | 24 +- man/process_append_distcat.Rd | 14 +- man/process_append_spatialcat.Rd | 37 +- man/process_convert_table_to_sf.Rd | 6 +- man/process_convert_time.Rd | 20 +- man/process_filter_by_shape.Rd | 25 +- man/process_get_crs_from_config.Rd | 8 +- man/process_get_mainmode_distribution.Rd | 19 + man/process_get_od_matrix.Rd | 2 +- man/process_get_travdistance_distribution.Rd | 19 + man/process_get_travelwaittime_by_mainmode.Rd | 21 + man/process_rename_category.Rd | 16 + man/process_rename_mainmodes.Rd | 16 +- man/read_output_trips.Rd | 9 +- vignettes/Introduction.html | 394 ++++++++++++++++++ 32 files changed, 632 insertions(+), 181 deletions(-) create mode 100644 man/process_get_mainmode_distribution.Rd create mode 100644 man/process_get_travdistance_distribution.Rd create mode 100644 man/process_get_travelwaittime_by_mainmode.Rd create mode 100644 man/process_rename_category.Rd create mode 100644 vignettes/Introduction.html diff --git a/man/matsimr-deprecated.Rd b/man/matsimr-deprecated.Rd index 3b8ee2d..526717b 100644 --- a/man/matsimr-deprecated.Rd +++ b/man/matsimr-deprecated.Rd @@ -218,7 +218,7 @@ plot_deptime_by_act( ) } \arguments{ -\item{tripsTable}{tibble of trips_output (from readTripsTable())} +\item{tripsTable}{tibble of output_trips (from read_output_trips())} \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} @@ -276,7 +276,7 @@ plot_deptime_by_act( \strong{plotModalSplitBarChart} - Bar Chart plot of transport mode distribution, values given in percents -\strong{readTripsTable} - tibble of trips_output +\strong{readTripsTable} - tibble of output_trips \strong{plotAverageTravelWait} - Bar Chart plot of average time spent on travel/wait @@ -330,11 +330,11 @@ tibble of output_trips with distance category column These functions are provided for compatibility with older version of the matsimr package. They may eventually be completely removed.\cr\cr -\strong{plotModalSplitPieChart} - Takes Table trips_output (from readTripsTable()), +\strong{plotModalSplitPieChart} - Takes Table output_trips (from read_output_trips()), to plot pie chart with with values that represent percentage of using transport modes from trips -\strong{plotModalSplitBarChart} - Takes Table trips_output (from readTripsTable()), +\strong{plotModalSplitBarChart} - Takes Table output_trips (from readTripsTable()), to plot bar chart with with values that represent percentage of using transport modes from trips diff --git a/man/plot_arrtime_by_act.Rd b/man/plot_arrtime_by_act.Rd index 75953b4..a58fcdd 100644 --- a/man/plot_arrtime_by_act.Rd +++ b/man/plot_arrtime_by_act.Rd @@ -2,12 +2,11 @@ % Please edit documentation in R/output_trips.R \name{plot_arrtime_by_act} \alias{plot_arrtime_by_act} -\title{Deprecated function(s) in the matsimr package -XXXX -\strong{plot_arrtime_by_act} - Takes Table trips_output (from readTripsTable()), -to make line plot with with values that represent -count of destination activities for a specific arrival time -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united')} +\title{Line chart of the arrival time by destination activity +XXXX function still needs to be updated? +Takes the data frame output_trips (from \link{read_output_trips()}), +to create a line plot of the with the arrival times on the x-axis and the count for each destination activity on the y-axis +Using the parameter unite.activities, specific activities can be renamed into one with the name specified with united.name (by default 'united')} \usage{ plot_arrtime_by_act( trips_table, @@ -16,7 +15,7 @@ plot_arrtime_by_act( ) } \arguments{ -\item{trips_table}{tibble of trips_output (from readTripsTable())} +\item{trips_table}{tibble of output_trips (from read_output_trips())} \item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all activity types in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} @@ -30,10 +29,9 @@ plot_arrtime_by_act( \strong{plot_arrtime_by_act} - Line plot with arrival time x-axis and number end activities on y-axis } \description{ -Deprecated function(s) in the matsimr package -XXXX -\strong{plot_arrtime_by_act} - Takes Table trips_output (from readTripsTable()), -to make line plot with with values that represent -count of destination activities for a specific arrival time -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Line chart of the arrival time by destination activity +XXXX function still needs to be updated? +Takes the data frame output_trips (from \link{read_output_trips()}), +to create a line plot of the with the arrival times on the x-axis and the count for each destination activity on the y-axis +Using the parameter unite.activities, specific activities can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_compare_count_by_spatialcat_barchart.Rd b/man/plot_compare_count_by_spatialcat_barchart.Rd index d587af5..2cafc6b 100644 --- a/man/plot_compare_count_by_spatialcat_barchart.Rd +++ b/man/plot_compare_count_by_spatialcat_barchart.Rd @@ -2,12 +2,7 @@ % Please edit documentation in R/output_trips.R \name{plot_compare_count_by_spatialcat_barchart} \alias{plot_compare_count_by_spatialcat_barchart} -\title{Bar Chart with main_mode on x-axis and average travel/wait time on y-axis -XXXX -Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -time spent on traveling/waiting -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united')} +\title{Comparison bar chart with trip type on x-axis and count on y-axis} \usage{ plot_compare_count_by_spatialcat_barchart( trips_table1, @@ -18,22 +13,19 @@ plot_compare_count_by_spatialcat_barchart( ) } \arguments{ -\item{tripsTable1}{tible of trips_output (from readTripsTable())} +\item{crs}{numeric representation of the EPSG code or proj4string for the corresponding coordinate system +of the trip coordinates, can be found in network file from output directory of MATSim simulation} -\item{tripsTable2}{tible of trips_output (from readTripsTable())} +\item{tripsTable1}{tibble of output_trips (from read_output_trips())} -\item{unite.columns}{vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns} +\item{tripsTable2}{tibble of output_trips (from read_output_trips())} -\item{united.name}{character string, if columns were united, you can specify name for the resulting column in chart} +\item{shapeTable}{sf object(data.frame with geometries), can be created using st_read()} } \value{ -Bar Chart plot of average time spent on travel/wait +Bar chart comparing number of each trip type for two runs } \description{ -Bar Chart with main_mode on x-axis and average travel/wait time on y-axis -XXXX -Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -time spent on traveling/waiting -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united') +Takes two data frames (from \link{read_output_trips()}) to plot a bar chart comparing the number of each trip type (originating, destinating, inside, outside). +The shape file is used to categorize the trips. } diff --git a/man/plot_compare_distcat_by_mainmode_barchart.Rd b/man/plot_compare_distcat_by_mainmode_barchart.Rd index 807a64a..9e48959 100644 --- a/man/plot_compare_distcat_by_mainmode_barchart.Rd +++ b/man/plot_compare_distcat_by_mainmode_barchart.Rd @@ -3,7 +3,7 @@ \name{plot_compare_distcat_by_mainmode_barchart} \alias{plot_compare_distcat_by_mainmode_barchart} \title{Bar chart comparing distance traveled on x-axis and number of trips on y-axis for two different runs -Takes two data frames (from \link{readTripsTable()}), categorizes the traveled distances into pre-defined bins +Takes two data frames (from \link{read_output_trips()}), categorizes the traveled distances into pre-defined bins and plots the difference in number of trips for each bin. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united')} \usage{ @@ -23,16 +23,16 @@ using the function (\link{process_rename_mainmodes})} \item{united.name}{character string, specifies the name of the united mode} -\item{tripsTable1}{tibble of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1} +\item{tripsTable1}{tibble of output_trips (from read_output_trips()), number of trips of this table will be extracted from number of trips of tripsTable1} -\item{tripsTable2}{tibble of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted} +\item{tripsTable2}{tibble of output_trips (from read_output_trips()), from number of trips of this table number of trips of tripsTable1 will be extracted} } \value{ Bar Chart plot of count of trips among distance travelled } \description{ Bar chart comparing distance traveled on x-axis and number of trips on y-axis for two different runs -Takes two data frames (from \link{readTripsTable()}), categorizes the traveled distances into pre-defined bins +Takes two data frames (from \link{read_output_trips()}), categorizes the traveled distances into pre-defined bins and plots the difference in number of trips for each bin. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_compare_mainmode_barchart.Rd b/man/plot_compare_mainmode_barchart.Rd index 395491e..059b324 100644 --- a/man/plot_compare_mainmode_barchart.Rd +++ b/man/plot_compare_mainmode_barchart.Rd @@ -18,15 +18,15 @@ using the function (\link{process_rename_mainmodes})} \item{united.name}{character string, specifies the name of the united mode} -\item{tripsTable1}{tibble of trips_output (from readTripsTable())} +\item{tripsTable1}{tibble of output_trips (from read_output_trips())} -\item{tripsTable2}{tibble of trips_output (from readTripsTable())} +\item{tripsTable2}{tibble of output_trips (from read_output_trips())} } \value{ plots bar chart of changes in modal split } \description{ -Takes two data frames (from \link{readTripsTable()}), calculates the +Takes two data frames (from \link{read_output_trips()}), calculates the changes in mode shares and plots them as a bar chart Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_compare_mainmode_sankey.Rd b/man/plot_compare_mainmode_sankey.Rd index a144e4f..823f7b6 100644 --- a/man/plot_compare_mainmode_sankey.Rd +++ b/man/plot_compare_mainmode_sankey.Rd @@ -21,15 +21,15 @@ using the function (\link{process_rename_mainmodes})} \item{united.name}{character string, specifies the name of the united mode} -\item{tripsTable1}{tibble of trips_output (from readTripsTable())} +\item{tripsTable1}{tibble of output_trips (from read_output_trips())} -\item{tripsTable2}{tibble of trips_output (from readTripsTable())} +\item{tripsTable2}{tibble of output_trips (from read_output_trips())} } \value{ Alluvial diagram that represents changes in transport mode distribution } \description{ -Takes two data frames (from \link{readTripsTable()}) and compares the mode choice for each agent and summarizes the results, showing the modal shift. +Takes two data frames (from \link{read_output_trips()}), compares the mode choice for each agent and summarizes the results, showing the modal shift. Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') The parameter show.onlyChanges allows the visualization of only the mode shift (excluding the trips that do not change mode). Standard value is FALSE. } diff --git a/man/plot_compare_travelwaittime_by_mainmode.Rd b/man/plot_compare_travelwaittime_by_mainmode.Rd index 86ab86a..b4ec2b5 100644 --- a/man/plot_compare_travelwaittime_by_mainmode.Rd +++ b/man/plot_compare_travelwaittime_by_mainmode.Rd @@ -19,15 +19,15 @@ using the function (\link{process_rename_mainmodes})} \item{united.name}{character string, specifies the name of the united mode} -\item{tripsTable1}{tibble of trips_output (from readTripsTable())} +\item{tripsTable1}{tibble of output_trips (from read_output_trips())} -\item{tripsTable2}{tibble of trips_output (from readTripsTable())} +\item{tripsTable2}{tibble of output_trips (from read_output_trips())} } \value{ Bar chart plot comparing average time spent on travel/wait of two runs } \description{ -Takes two data frames (from \link{readTripsTable()}), +Takes two data frames (from \link{read_output_trips()}), to plot a comparison bar chart of travel and wait times. Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd b/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd index 3e8b5a4..c7b6fa8 100644 --- a/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd +++ b/man/plot_compare_travelwaittime_by_mainmode_barchart.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/output_trips.R \name{plot_compare_travelwaittime_by_mainmode_barchart} \alias{plot_compare_travelwaittime_by_mainmode_barchart} -\title{Bar Chart with main_mode on x-axis and average travel/wait time on y-axis} +\title{Comparison bar chart with main_mode on x-axis and average travel/wait time on y-axis} \usage{ plot_compare_travelwaittime_by_mainmode_barchart( trips_table1, @@ -19,15 +19,14 @@ using the function (\link{process_rename_mainmodes})} \item{united.name}{character string, specifies the name of the united mode} -\item{tripsTable1}{tibble of trips_output (from readTripsTable())} +\item{tripsTable1}{tibble of output_trips (from read_output_trips())} -\item{tripsTable2}{tibble of trips_output (from readTripsTable())} +\item{tripsTable2}{tibble of output_trips (from read_output_trips())} } \value{ -Bar Chart plot of average time spent on travel/wait +Bar chart plot of average travel/wait time } \description{ -Takes the data frame trips_output (from \link{readTripsTable()}), -to plot a bar chart of the traveling/waiting time +Takes two data frames (from \link{read_output_trips()}) to plot a bar chart of the travel/wait time for each mode. Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_distance_by_mainmode_barchart.Rd b/man/plot_distance_by_mainmode_barchart.Rd index 7500cc0..e563a9a 100644 --- a/man/plot_distance_by_mainmode_barchart.Rd +++ b/man/plot_distance_by_mainmode_barchart.Rd @@ -12,7 +12,7 @@ plot_distance_by_mainmode_barchart( ) } \arguments{ -\item{trips_table}{tibble of trips_output (from readTripsTable())} +\item{trips_table}{tibble of output_trips (from read_output_trips())} \item{unite.modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), @@ -24,7 +24,7 @@ using the function (\link{process_rename_mainmodes})} Bar Chart plot of distance traveled per mode } \description{ -Takes the data frame trips_output (from \link{readTripsTable()}), +Takes the data frame output_trips (from \link{read_output_trips()}), to plot a bar chart of the average distance traveled for each main mode, Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_distance_by_spatialcat_barchart.Rd b/man/plot_distance_by_spatialcat_barchart.Rd index d984c66..885f758 100644 --- a/man/plot_distance_by_spatialcat_barchart.Rd +++ b/man/plot_distance_by_spatialcat_barchart.Rd @@ -2,11 +2,7 @@ % Please edit documentation in R/output_trips.R \name{plot_distance_by_spatialcat_barchart} \alias{plot_distance_by_spatialcat_barchart} -\title{Bar Chart with tripType on x-axis and travelled distance on y-axis -XXXX -Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -travelled distance of each tripType related to the shapeTable} +\title{Bar chart with trip type on x-axis and traveled distance on y-axis} \usage{ plot_distance_by_spatialcat_barchart( trips_table, @@ -16,19 +12,18 @@ plot_distance_by_spatialcat_barchart( ) } \arguments{ -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} +\item{crs}{numeric representation of the EPSG code or proj4string for the corresponding coordinate system +of the trip coordinates, can be found in network file from output directory of MATSim simulation} -\item{tripsTable}{tible of trips_output (from readTripsTable())} +\item{tripsTable}{tibble of output_trips (from read_output_trips())} -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +\item{shapeTable}{sf object(data.frame with geometries), can be created using st_read()} } \value{ -Bar Chart plot of distance traveled by spatial type +Bar chart plot of the distance traveled by trip type } \description{ -Bar Chart with tripType on x-axis and travelled distance on y-axis -XXXX -Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -travelled distance of each tripType related to the shapeTable +Takes the data frame output_trips (from \link{read_output_trips()}) +to plot a bar chart of the traveled distance of each trip type (originating, destinating, inside, outside) +as identified with a shape file of the project area. } diff --git a/man/plot_distcat_by_mainmode_barchart.Rd b/man/plot_distcat_by_mainmode_barchart.Rd index bcc8d0c..14290c3 100644 --- a/man/plot_distcat_by_mainmode_barchart.Rd +++ b/man/plot_distcat_by_mainmode_barchart.Rd @@ -13,7 +13,7 @@ plot_distcat_by_mainmode_barchart( ) } \arguments{ -\item{trips_table}{tibble of trips_output (from readTripsTable())} +\item{trips_table}{tibble of output_trips (from read_output_trips())} \item{unite.modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), @@ -25,7 +25,7 @@ using the function (\link{process_rename_mainmodes})} Bar Chart plot of count of trips among distance travelled } \description{ -Takes the data frame trips_output (from \link{readTripsTable()}) and categorizes the traveled distances into pre-defined bins +Takes the data frame output_trips (from \link{read_output_trips()}) and categorizes the traveled distances into pre-defined bins to plot a histogram of the traveled distances. (Bins: 1000,2000,5000,10000,20000,50000,100000 (m)) Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_mainmode_barchart.Rd b/man/plot_mainmode_barchart.Rd index 189f356..932aa7a 100644 --- a/man/plot_mainmode_barchart.Rd +++ b/man/plot_mainmode_barchart.Rd @@ -13,7 +13,7 @@ plot_mainmode_barchart( ) } \arguments{ -\item{trips_table}{tibble of trips_output (from \link{readTripsTable()})} +\item{trips_table}{tibble of output_trips (from \link{read_output_trips})} \item{unite.modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), @@ -25,7 +25,7 @@ using the function (\link{process_rename_mainmodes})} Bar Chart plot of transport mode distribution, values given in percents } \description{ -Takes the data frame trips_output (from \link{readTripsTable()}) +Takes the data frame output_trips (from \link{read_output_trips}) to plot a bar chart of the modal split using the column main_mode. } \details{ diff --git a/man/plot_mainmode_piechart.Rd b/man/plot_mainmode_piechart.Rd index 9ec835d..c56f729 100644 --- a/man/plot_mainmode_piechart.Rd +++ b/man/plot_mainmode_piechart.Rd @@ -12,7 +12,7 @@ plot_mainmode_piechart( ) } \arguments{ -\item{trips_table}{tibble of trips_output (from \link{readTripsTable})} +\item{trips_table}{tibble of output_trips (from \link{read_output_trips})} \item{unite.modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), @@ -24,7 +24,7 @@ using the function (\link{process_rename_mainmodes})} pie chart plot of transport mode distribution, values given in percent } \description{ -Uses the dataframe trips_output (from \link{readTripsTable}), +Uses the data frame output_trips (from \link{read_output_trips}), to plot a pie chart of the modal split using the column main_mode } \details{ diff --git a/man/plot_map_trips.Rd b/man/plot_map_trips.Rd index ed20ca0..cb8b82b 100644 --- a/man/plot_map_trips.Rd +++ b/man/plot_map_trips.Rd @@ -2,22 +2,22 @@ % Please edit documentation in R/output_trips.R \name{plot_map_trips} \alias{plot_map_trips} -\title{Plots start and end coordinates of the given trips table on an osm map -XXXX} +\title{Plots start and end coordinates of a given output_trips table onto an osm map +XXXX functions uses parameter shape_table?} \usage{ plot_map_trips(trips_table, crs, optimized = FALSE, shape_table = NULL) } \arguments{ -\item{crs}{numeric representation of the EPSG code or proj4string for the corresponding coordinate system of the trip coordinates, can be found in network file from output directory of MATSim simulation} +\item{trips_table}{tibble of output_trips (from read_output_trips())#'} -\item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot} +\item{crs}{numeric representation of the EPSG code or proj4string for the corresponding coordinate system of the trip coordinates, can be found in network file from output directory of MATSim simulation} -\item{table}{tibble of trips_output (from readTripsTable())} +\item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE creates image with ggplot} } \value{ plot with trips } \description{ -Plots start and end coordinates of the given trips table on an osm map -XXXX +Plots start and end coordinates of a given output_trips table onto an osm map +XXXX functions uses parameter shape_table? } diff --git a/man/plot_map_trips_by_spatialcat.Rd b/man/plot_map_trips_by_spatialcat.Rd index c9d792e..27141b0 100644 --- a/man/plot_map_trips_by_spatialcat.Rd +++ b/man/plot_map_trips_by_spatialcat.Rd @@ -2,24 +2,23 @@ % Please edit documentation in R/output_trips.R \name{plot_map_trips_by_spatialcat} \alias{plot_map_trips_by_spatialcat} -\title{Plots every type of trips(inside, outside, origin and destinating) on map -XXXX} +\title{Plots all trips categorized by trip type (inside, outside, origin and destinating) on a map} \usage{ plot_map_trips_by_spatialcat(trips_table, shape_table, crs, optimized = FALSE) } \arguments{ -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} +\item{crs}{numeric representation of the EPSG code or proj4string for the corresponding coordinate system +of the trip coordinates, can be found in network file from output directory of MATSim simulation} -\item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot} +\item{optimized}{bool, by default FALSE and gives interactive plot using leaflet, if TRUE creates image with ggplot} -\item{table}{tibble of trips_output (from readTripsTable())} +\item{table}{tibble of output_trips (from read_output_trips())} -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +\item{shapeTable}{sf object(data.frame with geometries), can be created using st_read()} } \value{ plot that contains every trip with defined trip type } \description{ -Plots every type of trips(inside, outside, origin and destinating) on map -XXXX +Plots all trips categorized by trip type (inside, outside, origin and destinating) on a map } diff --git a/man/plot_spatialtype_by_shape_piechart.Rd b/man/plot_spatialtype_by_shape_piechart.Rd index 09efa62..2598999 100644 --- a/man/plot_spatialtype_by_shape_piechart.Rd +++ b/man/plot_spatialtype_by_shape_piechart.Rd @@ -2,22 +2,22 @@ % Please edit documentation in R/output_trips.R \name{plot_spatialtype_by_shape_piechart} \alias{plot_spatialtype_by_shape_piechart} -\title{Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart -XXXX} +\title{XXXX THE FUNCTION NAME IS NOT DESCRIPTIVE ENOUGH - what could we use instead of by shape? plot_trips_by_spatialtype?} \usage{ plot_spatialtype_by_shape_piechart(trips_table, shape_table, crs) } \arguments{ -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} +\item{crs}{numeric representation of the EPSG code or proj4string for the corresponding coordinate system +of the trip coordinates, can be found in network file from output directory of MATSim simulation} -\item{table}{tibble of trips_output (from readTripsTable())} +\item{table}{tibble of output_trips (from \link{read_output_trips()})} -\item{shapeTable}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +\item{shapeTable}{sf object(data.frame with geometries), can be created using st_read()} } \value{ -plot with percentage of each type of trips +plot with percentage of each type of trip } \description{ -Plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart -XXXX +Plots distribution of trip types (inside, outside, origin and destinating) as a pie chart based on the data frame +output_trips (from \link{read_output_trips()}) } diff --git a/man/plot_travelwaittime_mean_barchart.Rd b/man/plot_travelwaittime_mean_barchart.Rd index 310f71c..7df48ba 100644 --- a/man/plot_travelwaittime_mean_barchart.Rd +++ b/man/plot_travelwaittime_mean_barchart.Rd @@ -12,7 +12,7 @@ plot_travelwaittime_mean_barchart( ) } \arguments{ -\item{trips_table}{tibble of trips_output (from \links{readTripsTable()})} +\item{trips_table}{tibble of output_trips (from \links{read_output_trips()})} \item{unite.modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), @@ -24,7 +24,7 @@ using the function (\link{process_rename_mainmodes})} Bar Chart plot of average time spent on travel/wait } \description{ -Takes the data frame trips_output (from \links{readTripsTable()}), +Takes the data frame output_trips (from \links{read_output_trips()}), to plot a bar chart of travel and wait times. Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd b/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd index 474ff08..542c131 100644 --- a/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd +++ b/man/plot_trips_count_by_deptime_and_mainmode_linechart.Rd @@ -6,36 +6,24 @@ \usage{ plot_trips_count_by_deptime_and_mainmode_linechart( trips_table, - unite.columns = character(0), - united.name = "united" -) - -plot_trips_count_by_deptime_and_mainmode_linechart( - trips_table, - unite.columns = character(0), + unite.modes = character(0), united.name = "united" ) } \arguments{ -\item{united.name}{character string, specifies the name of the united mode} - -\item{tripsTable}{tibble of trips_output (from readTripsTable())} - \item{unite.modes}{vector of character strings, changes names of chosen modes in the column main_mode to a new chosen name (i.e. drtNorth and drtSouth to drt), using the function (\link{process_rename_mainmodes})} + +\item{united.name}{character string, specifies the name of the united mode} + +\item{tripsTable}{tibble of output_trips (from read_output_trips())} } \value{ -Line plot of trips count by departure time per mode - Line plot of trips count by departure time per mode } \description{ -Takes data frame trips_output (from \link{readTripsTable()}), -to create a line plot of the number of trips for a specific departure time by main_mode -Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') - -Takes data frame trips_output (from \link{readTripsTable()}), +Takes data frame output_trips (from \link{read_output_trips()}), to create a line plot of the number of trips for a specific departure time by main_mode Using the parameter unite.modes, specific modes can be renamed into one with the name specified with united.name (by default 'united') } diff --git a/man/process_append_distcat.Rd b/man/process_append_distcat.Rd index e0abf40..b761458 100644 --- a/man/process_append_distcat.Rd +++ b/man/process_append_distcat.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/output_trips.R \name{process_append_distcat} \alias{process_append_distcat} -\title{Adds additional \strong{dist_cat} column representing category of distance traveled based on \strong{distances_array} parameter.} +\title{Adds additional \strong{dist_cat} column based on the \strong{distances_array} parameter} \usage{ process_append_distcat( trips_table, @@ -10,11 +10,15 @@ process_append_distcat( ) } \arguments{ -\item{trips_table}{tibble of trips_output (from \link{read_output_trips})} +\item{trips_table}{tibble of output_trips (from \link{read_output_trips})} -\item{distances_array}{numeric vector, represents segments for distance categories ordered (in meters)} +\item{distances_array}{numeric vector, represents segments for distance categories ordered (in meters), +standard value: c(1000,2000,5000,10000,20000,50000,100000)} +} +\value{ +trips table with added the added column dist_cat } \description{ -Categorize column of distances based on \strong{distances_array}, each dist_cat receives relational segment from array.\cr -For example trip distance traveled is 1500, and distances array is (1000,2000), then this category is "1000-2000". +Categorizes each trip into a distance bin based on traveled distance. +E.g. distance traveled is 1500, distances array is (1000,2000), then the category is "1000-2000". } diff --git a/man/process_append_spatialcat.Rd b/man/process_append_spatialcat.Rd index 5a87d42..5c0620f 100644 --- a/man/process_append_spatialcat.Rd +++ b/man/process_append_spatialcat.Rd @@ -2,38 +2,29 @@ % Please edit documentation in R/output_trips.R \name{process_append_spatialcat} \alias{process_append_spatialcat} -\title{Appending spatial category as additional column to output_trips tibble -XXXX -Takes trips_table and shape_table(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -Please be aware that this \link{process_filter_by_shape} currently only works, when one geometry is loaded.) -transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -and adds to the output_trips from table spatial category depending on postition related to shape file: -category representing trips \strong{inside} of the given shape -category representing trips which \strong{originating} in the shape -category representing trips which \strong{destinating} in the shape -category representing trips which \strong{outside} of the given shape} +\title{Appends an additional column with the trip type to output_trips} \usage{ process_append_spatialcat(trips_table, shape_table, crs) } \arguments{ -\item{trips_table}{tibble of trips_output (from readTripsTable())} +\item{trips_table}{tibble of output_trips (from read_output_trips())} -\item{shape_table}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +\item{crs}{numeric representation of the EPSG code or proj4string for the corresponding coordinate system +of the trip coordinates, can be found in network file from output directory of MATSim simulation} -\item{crs}{numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation} +\item{shapeTable}{sf object(data.frame with geometries), can be created using st_read()} } \value{ -tibble, with additional spatial column related to given shape +tibble, with additional column containing the trip type } \description{ -Appending spatial category as additional column to output_trips tibble -XXXX -Takes trips_table and shape_table(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +Using a shape_file of the project area an additional column is created, categorizing all trips into the following categories. +inside: trips that start and end inside the given shape +originating: trips that start inside the shape and end outside of the shape +destinating: trips that end inside the shape and start outside of the shape +outside: trips that start and end outside of the shape +} +\details{ +XXXX Can this be deleted? Is this relevant here? Please be aware that this \link{process_filter_by_shape} currently only works, when one geometry is loaded.) -transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -and adds to the output_trips from table spatial category depending on postition related to shape file: -category representing trips \strong{inside} of the given shape -category representing trips which \strong{originating} in the shape -category representing trips which \strong{destinating} in the shape -category representing trips which \strong{outside} of the given shape } diff --git a/man/process_convert_table_to_sf.Rd b/man/process_convert_table_to_sf.Rd index eeb5f13..b1a8031 100644 --- a/man/process_convert_table_to_sf.Rd +++ b/man/process_convert_table_to_sf.Rd @@ -2,12 +2,12 @@ % Please edit documentation in R/output_trips.R \name{process_convert_table_to_sf} \alias{process_convert_table_to_sf} -\title{Transforms the data frame trips_output (from \links{readTripsTable}) from tibble to sf (table with geometry features)} +\title{Transforms output_trips from tibble to sf (table with geometry features)} \usage{ process_convert_table_to_sf(table, crs, geometry.type = st_multipoint()) } \arguments{ -\item{table}{tibble trips_output (from readTripsTable())} +\item{table}{tibble output_trips (from read_output_trips())} \item{crs}{numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file} @@ -20,7 +20,7 @@ process_convert_table_to_sf(table, crs, geometry.type = st_multipoint()) sf object (data frame with geometries depending on geometry.type) } \description{ -Transforms the data frame trips_output (from \links{readTripsTable}) into an sf object using start_x, end_x, start_y, end_y as geometry features.\cr +Transforms the data frame output_trips (from \links{read_output_trips}) into an sf object using start_x, end_x, start_y, end_y as geometry features.\cr If geometry.type = st_multipoint() or geometry.type = st_linestring() it adds one geometry column (wkt format),\cr if geometry.type = st_point() it adds the geometry columns start_wkt and end_wkt.\cr Added column/columns are projected to given CRS (coordinate reference system).\cr diff --git a/man/process_convert_time.Rd b/man/process_convert_time.Rd index 5802e1e..1f764bf 100644 --- a/man/process_convert_time.Rd +++ b/man/process_convert_time.Rd @@ -2,7 +2,11 @@ % Please edit documentation in R/output_trips.R \name{process_convert_time} \alias{process_convert_time} -\title{Converts time column specified in \strong{time_column} to numeric representation of minutes, hours or seconds} +\title{Converts time column specified in \strong{time_column} to numeric representation of minutes, hours or seconds +XXXX here minute, hour and second don't have an s? +Default output_trips table time columns(\strong{dep_time}, \strong{trav_time}, \strong{wait_time}) are in 'hms' format. +To convert this type to numeric, specify \strong{time_column} to be converted, +and the unit \strong{time_format}. Acceptable units are "hour", "minute" and "second".} \usage{ process_convert_time( trips_table, @@ -11,17 +15,19 @@ process_convert_time( ) } \arguments{ -\item{trips_table}{tibble of trips_output (from \link{read_output_trips})} +\item{trips_table}{tibble of output_trips (from \link{read_output_trips})} -\item{time_format}{char, defines time format to be used(takes "hour", "minute", "second")} +\item{time_format}{char, defines time unit to be used ("hour", "minute", "second")} -\item{time_column}{char, name of the column from table to be converted(takes \strong{dep_time}, \strong{trav_time}, \strong{wait_time})} +\item{time_column}{char, name of the column from table to be converted (\strong{dep_time}, \strong{trav_time}, \strong{wait_time})} } \value{ tibble, containing column with specified time_format } \description{ -Default output_trips table time columns(\strong{dep_time}, \strong{trav_time}, \strong{wait_time}) are in 'hms' format, -that isn't convenient for use in some cases. To convert this type to numeric with different, specify \strong{time_column} to be converted, -and \strong{time_format} which will represent time(takes "hour", "minute", "second") +Converts time column specified in \strong{time_column} to numeric representation of minutes, hours or seconds +XXXX here minute, hour and second don't have an s? +Default output_trips table time columns(\strong{dep_time}, \strong{trav_time}, \strong{wait_time}) are in 'hms' format. +To convert this type to numeric, specify \strong{time_column} to be converted, +and the unit \strong{time_format}. Acceptable units are "hour", "minute" and "second". } diff --git a/man/process_filter_by_shape.Rd b/man/process_filter_by_shape.Rd index 89d40b9..b9ca500 100644 --- a/man/process_filter_by_shape.Rd +++ b/man/process_filter_by_shape.Rd @@ -3,28 +3,29 @@ \name{process_filter_by_shape} \alias{process_filter_by_shape} \title{XXXX finish when code revision is done -Filters trips_table(from ,\link{readTripsTable}) depending by location using a shapefile} +Filters data frame (from \link{read_output_trips}) by location using a shapefile} \usage{ process_filter_by_shape(trips_table, shape_table, crs, spatial_type = "inside") } \arguments{ -\item{trips_table}{tibble of trips_output (from readTripsTable())} +\item{trips_table}{tibble of output_trips (from read_output_trips())} -\item{shape_table}{sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)} +\item{crs}{numeric representation of the EPSG code or proj4string for the corresponding coordinate system +of the trip coordinates, can be found in network file from output directory of MATSim simulation} -\item{crs}{numeric, coordinate system in the form of the EPSG code or proj4string, can be found in the MATSim network file} +\item{spatial_type}{bool, defines trips to conclude (see description)} -\item{spatial_type}{bool, defines trips to conclude (see Description)} +\item{shapeTable}{sf object(data.frame with geometries), can be created using st_read()} } \value{ -tibble, with filtered trips depending on shapeTable and special flags (see Description) +tibble, with filtered trips depending on shapeTable and spatial types (see description) } \description{ -Uses trips_table and an sf object (can be created using the function st_read()), +Uses output_trips and an sf object (can be created using the function st_read()), transforms both objects to match a mutual coordinate system (crs) -and filters the trips from trips_table depending on spatial_type flags:\cr -if spatial_type="inside" return table that contains trips inside given shape\cr -if spatial_type="originating" return table that contains trips which starts in shape and ends out of the shape\cr -if spatial_type="destinating" return table that contains trips which ends in shape and starts out of the shape\cr -if spatial_type="outside" return table that contains trips which starts and ends our of the given shape +and filters the trips from output_trips depending on their spatial type flags:\cr +if spatial_type="inside" returns a table that contains trips inside given shape\cr +if spatial_type="originating" returns a table that contains trips which start inside the shape and end outside of the shape\cr +if spatial_type="destinating" returns a table that contains trips which end inside shape and start outside of the shape\cr +if spatial_type="outside" returns a table that contains trips which start and end outside of the given shape } diff --git a/man/process_get_crs_from_config.Rd b/man/process_get_crs_from_config.Rd index 8ea3032..4839d7c 100644 --- a/man/process_get_crs_from_config.Rd +++ b/man/process_get_crs_from_config.Rd @@ -2,8 +2,7 @@ % Please edit documentation in R/output_trips.R \name{process_get_crs_from_config} \alias{process_get_crs_from_config} -\title{Reads the coordinate reference system from an MATSim output directory -(output_config.xml)} +\title{Reads the coordinate reference system from a MATSim output directory (output_config.xml)} \usage{ process_get_crs_from_config(config_path) } @@ -11,9 +10,8 @@ process_get_crs_from_config(config_path) \item{config_path}{specifies path to configuration file} } \value{ -code of coordinate reference system +EPSG code of coordinate reference system } \description{ -Reads the coordinate reference system from an MATSim output directory -(output_config.xml) +Reads the coordinate reference system from a MATSim output directory (output_config.xml) } diff --git a/man/process_get_mainmode_distribution.Rd b/man/process_get_mainmode_distribution.Rd new file mode 100644 index 0000000..40ed37f --- /dev/null +++ b/man/process_get_mainmode_distribution.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_get_mainmode_distribution} +\alias{process_get_mainmode_distribution} +\title{Calculates the count or percentage for each mode} +\usage{ +process_get_mainmode_distribution(trips_table, percentage = FALSE) +} +\arguments{ +\item{trips_table}{tibble of output_trips (from read_output_trips())} + +\item{percentage}{boolean, standard value FALSE (calculates the count)} +} +\value{ +tibble including the count or percentage +} +\description{ +Calculates the count or percentage for each mode in the column main_mode +} diff --git a/man/process_get_od_matrix.Rd b/man/process_get_od_matrix.Rd index 1aec2cd..6fa0613 100644 --- a/man/process_get_od_matrix.Rd +++ b/man/process_get_od_matrix.Rd @@ -26,7 +26,7 @@ process_get_od_matrix( \item{outer}{boolean, determines if flows outside of the shapefile are used, standard value is FALSE} -\item{tripsTable}{tibble of trips_output (from \link{readTripsTable})} +\item{tripsTable}{tibble of output_trips (from \link{read_output_trips})} \item{shapePath}{string, full path to the shapefile (.shp) (shape files are made up of several files with the same name and the folder also needs to include a .dbf file)} } diff --git a/man/process_get_travdistance_distribution.Rd b/man/process_get_travdistance_distribution.Rd new file mode 100644 index 0000000..b1dd93a --- /dev/null +++ b/man/process_get_travdistance_distribution.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_get_travdistance_distribution} +\alias{process_get_travdistance_distribution} +\title{Calculates the average distance for each mode} +\usage{ +process_get_travdistance_distribution(trips_table, euclidean = FALSE) +} +\arguments{ +\item{trips_table}{tibble of output_trips (from read_output_trips())} + +\item{euclidean}{boolean, specifies if euclidean or traveled distance should be used} +} +\value{ +a tibble of main modes and their average distance +} +\description{ +Calculates the average distance for each mode +} diff --git a/man/process_get_travelwaittime_by_mainmode.Rd b/man/process_get_travelwaittime_by_mainmode.Rd new file mode 100644 index 0000000..5801ee7 --- /dev/null +++ b/man/process_get_travelwaittime_by_mainmode.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_get_travelwaittime_by_mainmode} +\alias{process_get_travelwaittime_by_mainmode} +\title{Calculates the average travel and wait time +XXXX minute_ but hourS and secondS?} +\usage{ +process_get_travelwaittime_by_mainmode(trips_table, time_format = "minute") +} +\arguments{ +\item{trips_table}{tibble of output_trips (from read_output_trips())} + +\item{time_format}{standard value is "minute", can also be "hours" or "seconds"} +} +\value{ +tibble with main modes and their average wait and travel time +} +\description{ +Calculates the average travel and wait time +XXXX minute_ but hourS and secondS? +} diff --git a/man/process_rename_category.Rd b/man/process_rename_category.Rd new file mode 100644 index 0000000..12e63ec --- /dev/null +++ b/man/process_rename_category.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/output_trips.R +\name{process_rename_category} +\alias{process_rename_category} +\title{XXXX} +\usage{ +process_rename_category( + trips_table, + unite_template = character(0), + united_name = "united", + column = "main_mode" +) +} +\description{ +XXXX +} diff --git a/man/process_rename_mainmodes.Rd b/man/process_rename_mainmodes.Rd index e35bc72..7537282 100644 --- a/man/process_rename_mainmodes.Rd +++ b/man/process_rename_mainmodes.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/output_trips.R \name{process_rename_mainmodes} \alias{process_rename_mainmodes} -\title{XXXX} +\title{Renames modes in the column main_mode} \usage{ process_rename_mainmodes( trips_table, @@ -10,6 +10,18 @@ process_rename_mainmodes( united.name = "united" ) } +\arguments{ +\item{trips_table}{tibble of output_trips (from read_output_trips())} + +\item{unite.modes}{vector of character strings, +changes names of chosen modes in the column main_mode to a new chosen name} + +\item{united.name}{character string, specifies the name of the united mode} +} +\value{ +trips_table with adjused mode names +} \description{ -XXXX +Changes the name of modes in the column main_mode to a new name called united.name. +E.g. "drtNorth" and "drtSouth" can be renamed to "drt" allowing them to be analyzed together. } diff --git a/man/read_output_trips.Rd b/man/read_output_trips.Rd index b7cd76c..f05e2ff 100644 --- a/man/read_output_trips.Rd +++ b/man/read_output_trips.Rd @@ -2,19 +2,18 @@ % Please edit documentation in R/output_trips.R \name{read_output_trips} \alias{read_output_trips} -\title{Load MATSIM output_trips table into memory} +\title{Load MATSim output_trips table into memory} \usage{ read_output_trips(input_path = ".", n_max = Inf) } \arguments{ -\item{input_path}{character string, path to the MATSim output directory or http link to the file.} +\item{input_path}{character string, path to the MATSim output directory or http link to the file} \item{n_max}{optional, integer, maximum number of lines to read, standard value is Inf} } \value{ -tibble of trips_output +tibble of output_trips } \description{ -Loads a MATSim CSV output_trips from file or archive, -creating a tibble with columns as in csv file +Loads MATSim output_trips.csv from file or archive creating a tibble } diff --git a/vignettes/Introduction.html b/vignettes/Introduction.html new file mode 100644 index 0000000..e9d1278 --- /dev/null +++ b/vignettes/Introduction.html @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + +Introduction for Matsim R Library + + + + + + + + + + + + + + + + + + + + + + + + + + +

Introduction for Matsim R Library

+ + + +
library(matsim)
+#> Warning: vorhergehender Import 'ggplot2::last_plot' durch 'plotly::last_plot'
+#> während des Ladens von 'matsim' ersetzt
+#> Warning: vorhergehender Import 'lubridate::stamp' durch 'reshape::stamp'
+#> während des Ladens von 'matsim' ersetzt
+#> Warning: vorhergehender Import 'plotly::rename' durch 'reshape::rename' während
+#> des Ladens von 'matsim' ersetzt
+#> Warning: vorhergehender Import 'purrr::discard' durch 'scales::discard' während
+#> des Ladens von 'matsim' ersetzt
+#> Warning: vorhergehender Import 'readr::col_factor' durch 'scales::col_factor'
+#> während des Ladens von 'matsim' ersetzt
+#> Warning: vorhergehender Import 'reshape::expand' durch 'tidyr::expand' während
+#> des Ladens von 'matsim' ersetzt
+

#Introduction Welcome to the matsim package! This +vignette will guide you through the process of creating plots using the +functions provided by our library. matsim is a powerful R package +designed for data process and visualization, with providing a wide range +of functions to create high-quality and adjustable plots from processed +data.

+

##Overall concept

+
+ +

Data flow and concept of matsim r package

+
+

##Installation Matsim is not still available at +CRAN, so to install matsim we use github, you can use the following +code:

+
devtools::install_github("matsim-vsp/matsim-r")
+

However if you want to have some specific branch in your Rstudio you +can specify this branch in the code:

+
devtools::install_github("matsim-vsp/matsim-r", ref = "{name of the branch}")
+

##Loading the package Once installed, you can load +the matsim package using the library() function:

+
library(matsim)
+ + + + + + + + + + + From 041d99886eeb313d1b1f01c7e4e9a84aa2aa8c56 Mon Sep 17 00:00:00 2001 From: Sasha Soboliev Date: Fri, 21 Jul 2023 15:14:34 +0200 Subject: [PATCH 76/87] renamed vignette file --- vignettes/{Example project.Rmd => Exampleproject.Rmd} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename vignettes/{Example project.Rmd => Exampleproject.Rmd} (98%) diff --git a/vignettes/Example project.Rmd b/vignettes/Exampleproject.Rmd similarity index 98% rename from vignettes/Example project.Rmd rename to vignettes/Exampleproject.Rmd index 943cccd..f84699b 100644 --- a/vignettes/Example project.Rmd +++ b/vignettes/Exampleproject.Rmd @@ -1,8 +1,8 @@ --- -title: "Example project: Leipzig" +title: "Example project" output: rmarkdown::html_vignette vignette: > - %\VignetteIndexEntry{Example project: Leipzig} + %\VignetteIndexEntry{Example project} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- From 39d6b1fe2985092b9ec2dfd36e9a93f1cfe9c259 Mon Sep 17 00:00:00 2001 From: Billy Charlton Date: Fri, 21 Jul 2023 15:27:51 +0200 Subject: [PATCH 77/87] bump version to 0.2.0 --- DESCRIPTION | 2 +- Makefile | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index c6924e4..b21ecda 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: matsim Type: Package Title: R library for interfacing with MATSim agent-based microsimulation model -Version: 0.1.9 +Version: 0.2.0 Authors@R: c( person("Billy", "Charlton", email = "charlton@vsp.tu-berlin.de", role=c("aut","cre")), person("Oleksandr", "Soboliev", role="aut")) diff --git a/Makefile b/Makefile index a67f997..2e9a6d7 100644 --- a/Makefile +++ b/Makefile @@ -29,4 +29,5 @@ docs: .sentinel-make-docs clean: > rm -rf docs > rm -rf man +> rm .sentinel* .PHONY: clean From 60d37e70ca80ad1a6874c8c19559e7e09300c70c Mon Sep 17 00:00:00 2001 From: Billy Charlton Date: Fri, 21 Jul 2023 15:28:48 +0200 Subject: [PATCH 78/87] updated docs build --- docs/404.html | 18 +- docs/LICENSE.html | 14 +- docs/articles/Exampleproject.html | 225 +++++ docs/articles/Introduction.html | 254 ++++++ docs/articles/Namings.html | 119 +++ docs/articles/index.html | 80 ++ docs/authors.html | 18 +- .../bootstrap-5.2.2/bootstrap.bundle.min.js | 7 - .../bootstrap.bundle.min.js.map | 1 - docs/deps/bootstrap-5.2.2/bootstrap.min.css | 6 - docs/deps/data-deps.txt | 4 +- docs/index.html | 26 +- docs/pkgdown.yml | 11 +- ...docs.html => boxplotScoreDifferences.html} | 49 +- docs/reference/compareAverageTravelWait.html | 122 --- docs/reference/compareBasePolicyOutput.html | 105 --- .../compareBasePolicyShapeOutput.html | 115 --- .../compareModalDistanceDistribution.html | 122 --- docs/reference/createCountScatterPlot.html | 28 +- docs/reference/deriveODMatrix.html | 118 --- docs/reference/filterByRegion.html | 129 --- docs/reference/generateXYHexagonYaml.html | 20 +- docs/reference/getCrsFromConfig.html | 92 --- docs/reference/index.html | 215 +++-- docs/reference/matsimr-deprecated.html | 781 ++++++++++++++++++ docs/reference/mergeCountsAndLinks.html | 36 +- docs/reference/plotActivityEndTimes.html | 120 --- .../plotArrivalTimesPerTripPurpose.html | 120 --- docs/reference/plotAverageTravelWait.html | 117 --- .../plotDepartureTimesPerTripPurpose.html | 117 --- docs/reference/plotMapWithTrips.html | 134 --- docs/reference/plotMapWithTripsType.html | 98 --- .../plotModalDistanceDistribution.html | 117 --- docs/reference/plotModalShiftBar.html | 123 --- docs/reference/plotModalShiftSankey.html | 127 --- docs/reference/plotModalSplitBarChart.html | 120 --- docs/reference/plotModalSplitPieChart.html | 120 --- .../reference/plotStartActCountByDepTime.html | 117 --- docs/reference/plotTripCountByDepTime.html | 117 --- docs/reference/plotTripDistanceByMode.html | 117 --- docs/reference/plotTripDistancedByType.html | 109 --- docs/reference/plotTripTypesPieChart.html | 94 --- docs/reference/plot_arrtime_by_act.html | 115 +++ ..._compare_count_by_spatialcat_barchart.html | 121 +++ ..._compare_distcat_by_mainmode_barchart.html | 141 ++++ .../plot_compare_mainmode_barchart.html | 119 +++ .../plot_compare_mainmode_sankey.html | 124 +++ ...ot_compare_travelwaittime_by_mainmode.html | 124 +++ ...e_travelwaittime_by_mainmode_barchart.html | 124 +++ ...BarChart.html => plot_deptime_by_act.html} | 63 +- .../plot_distance_by_mainmode_barchart.html | 119 +++ ...plot_distance_by_spatialcat_barchart.html} | 62 +- .../plot_distcat_by_mainmode_barchart.html | 124 +++ docs/reference/plot_mainmode_barchart.html | 121 +++ docs/reference/plot_mainmode_piechart.html | 116 +++ ...ountByArrTime.html => plot_map_trips.html} | 60 +- .../plot_map_trips_by_spatialcat.html | 115 +++ .../plot_spatialtype_by_shape_piechart.html | 108 +++ .../plot_travelwaittime_mean_barchart.html | 120 +++ ...unt_by_deptime_and_mainmode_linechart.html | 114 +++ ...omparisonSimwrapperDashboardFromTable.html | 24 +- .../prepareSimwrapperDashboardFromFolder.html | 26 +- .../prepareSimwrapperDashboardFromTable.html | 22 +- .../processDtvEstimationQuality.html | 35 +- .../processLinkStatsDtvDistribution.html | 24 +- docs/reference/process_append_distcat.html | 105 +++ docs/reference/process_append_spatialcat.html | 119 +++ .../process_convert_table_to_sf.html | 117 +++ docs/reference/process_convert_time.html | 130 +++ docs/reference/process_filter_by_shape.html | 128 +++ ....html => process_get_crs_from_config.html} | 51 +- .../process_get_mainmode_distribution.html | 106 +++ docs/reference/process_get_od_matrix.html | 132 +++ ...process_get_travdistance_distribution.html | 98 +++ ...rocess_get_travelwaittime_by_mainmode.html | 98 +++ docs/reference/process_rename_category.html | 123 +++ docs/reference/process_rename_mainmodes.html | 118 +++ docs/reference/readCounts.html | 18 +- docs/reference/readLinkStats.html | 32 +- docs/reference/readPersonsTable.html | 20 +- docs/reference/readTripsTable.html | 89 -- docs/reference/read_config.html | 101 +++ .../{loadNetwork.html => read_network.html} | 20 +- docs/reference/read_output_trips.html | 98 +++ docs/reference/symlog_trans.html | 14 +- docs/reference/transformToSf.html | 117 --- docs/search.json | 2 +- docs/sitemap.xml | 106 ++- 88 files changed, 5353 insertions(+), 3292 deletions(-) create mode 100644 docs/articles/Exampleproject.html create mode 100644 docs/articles/Introduction.html create mode 100644 docs/articles/Namings.html create mode 100644 docs/articles/index.html delete mode 100644 docs/deps/bootstrap-5.2.2/bootstrap.bundle.min.js delete mode 100644 docs/deps/bootstrap-5.2.2/bootstrap.bundle.min.js.map delete mode 100644 docs/deps/bootstrap-5.2.2/bootstrap.min.css rename docs/reference/{generate_html_docs.html => boxplotScoreDifferences.html} (60%) delete mode 100644 docs/reference/compareAverageTravelWait.html delete mode 100644 docs/reference/compareBasePolicyOutput.html delete mode 100644 docs/reference/compareBasePolicyShapeOutput.html delete mode 100644 docs/reference/compareModalDistanceDistribution.html delete mode 100644 docs/reference/deriveODMatrix.html delete mode 100644 docs/reference/filterByRegion.html delete mode 100644 docs/reference/getCrsFromConfig.html create mode 100644 docs/reference/matsimr-deprecated.html delete mode 100644 docs/reference/plotActivityEndTimes.html delete mode 100644 docs/reference/plotArrivalTimesPerTripPurpose.html delete mode 100644 docs/reference/plotAverageTravelWait.html delete mode 100644 docs/reference/plotDepartureTimesPerTripPurpose.html delete mode 100644 docs/reference/plotMapWithTrips.html delete mode 100644 docs/reference/plotMapWithTripsType.html delete mode 100644 docs/reference/plotModalDistanceDistribution.html delete mode 100644 docs/reference/plotModalShiftBar.html delete mode 100644 docs/reference/plotModalShiftSankey.html delete mode 100644 docs/reference/plotModalSplitBarChart.html delete mode 100644 docs/reference/plotModalSplitPieChart.html delete mode 100644 docs/reference/plotStartActCountByDepTime.html delete mode 100644 docs/reference/plotTripCountByDepTime.html delete mode 100644 docs/reference/plotTripDistanceByMode.html delete mode 100644 docs/reference/plotTripDistancedByType.html delete mode 100644 docs/reference/plotTripTypesPieChart.html create mode 100644 docs/reference/plot_arrtime_by_act.html create mode 100644 docs/reference/plot_compare_count_by_spatialcat_barchart.html create mode 100644 docs/reference/plot_compare_distcat_by_mainmode_barchart.html create mode 100644 docs/reference/plot_compare_mainmode_barchart.html create mode 100644 docs/reference/plot_compare_mainmode_sankey.html create mode 100644 docs/reference/plot_compare_travelwaittime_by_mainmode.html create mode 100644 docs/reference/plot_compare_travelwaittime_by_mainmode_barchart.html rename docs/reference/{compareTripTypesBarChart.html => plot_deptime_by_act.html} (51%) create mode 100644 docs/reference/plot_distance_by_mainmode_barchart.html rename docs/reference/{plotTripsByDistance.html => plot_distance_by_spatialcat_barchart.html} (62%) create mode 100644 docs/reference/plot_distcat_by_mainmode_barchart.html create mode 100644 docs/reference/plot_mainmode_barchart.html create mode 100644 docs/reference/plot_mainmode_piechart.html rename docs/reference/{plotEndActCountByArrTime.html => plot_map_trips.html} (59%) create mode 100644 docs/reference/plot_map_trips_by_spatialcat.html create mode 100644 docs/reference/plot_spatialtype_by_shape_piechart.html create mode 100644 docs/reference/plot_travelwaittime_mean_barchart.html create mode 100644 docs/reference/plot_trips_count_by_deptime_and_mainmode_linechart.html create mode 100644 docs/reference/process_append_distcat.html create mode 100644 docs/reference/process_append_spatialcat.html create mode 100644 docs/reference/process_convert_table_to_sf.html create mode 100644 docs/reference/process_convert_time.html create mode 100644 docs/reference/process_filter_by_shape.html rename docs/reference/{plotDistanceTraveledByType.html => process_get_crs_from_config.html} (66%) create mode 100644 docs/reference/process_get_mainmode_distribution.html create mode 100644 docs/reference/process_get_od_matrix.html create mode 100644 docs/reference/process_get_travdistance_distribution.html create mode 100644 docs/reference/process_get_travelwaittime_by_mainmode.html create mode 100644 docs/reference/process_rename_category.html create mode 100644 docs/reference/process_rename_mainmodes.html delete mode 100644 docs/reference/readTripsTable.html create mode 100644 docs/reference/read_config.html rename docs/reference/{loadNetwork.html => read_network.html} (57%) create mode 100644 docs/reference/read_output_trips.html delete mode 100644 docs/reference/transformToSf.html diff --git a/docs/404.html b/docs/404.html index d882c2d..3d712f7 100644 --- a/docs/404.html +++ b/docs/404.html @@ -7,10 +7,10 @@ Page not found (404) • matsim - - + + - + GNU General Public License • matsimGNU General Public License • matsim @@ -10,7 +10,7 @@ matsim - 0.1.8 + 0.2.0 + + + + + +
+ + + + +
+
+ + + +

The data used in this example project can be found on the [public +repository] (https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/) +from VSP Berlin. There you can also find other MATSim scenarios.

+
+

Introduction +

+

This vignette offers an example workflow from MATSim output to +thematic plots and maps. For a general overview of the package and its +structure please read the introduction.

+

A short recap however: functions are divided into four categories and +start with a respective prefix. Read_, process_, plot_ or compare_ and +in the future simwrapper_. To better understand the naming conventions +(for example to create your own functions) consult this vignette +[LINK].

+
+
+

Installation +

+

MATSim R is not yet available at CRAN, so to install MATSim R using +github, use the following code.

+
+devtools::install_github("matsim-vsp/matsim-r")
+
+
+

Loading the package +

+

Once installed, you can load the MATSim R package using the library() +function:

+ +
+
+

Loading data +

+

The data we’ll use in this example project is the result of a Leipzig +run which you can find under the following link. (https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/leipzig/projects/namav/base-case/)

+

If you want to follow along, download a copy of the folder.

+

To start, we will load the output_trips.csv.gz file. It is a zipped +file, but that is okay, the functions can handle that. We will also load +a shape file, which can be found here. (https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/leipzig/leipzig-v1.1/input/shp/)

+
+ trips_file_path <- "paste_file_path_here"
+ 
+ # if you don't want to immediately load the whole file, the function read_output_trips has the option to only load the first n lines 
+ output_trips <- read_output_trips(trips_file_path, n_max = 5000)
+
+
+

Plot a modal split +

+

There are two functions to calculate and plot modal splits: +plot_mainmode_piechart() and +plot_mainmode_piechart(). As the name suggests the first +one plots the modal split as a pie chart and the second one as a bar +chart. To do this, they use the processing function +process_get_mainmode_distribution() and plot the resulting +table. The processing function can also be used on its own to just get +the raw numbers.

+

We are going to plot a bar chart:

+
+ plot_mainmode_barchart(output_trips)
+

The resulting bar chart looks like this:

+
+

Leipzig modal split

+
+
+
+

Spatial filter +

+

In a next step we want to spatially filter our data. So far we have +been looking at all the trips in the simulation, now we want to focus on +those that touch our project area.

+

To do this we can use the function +process_filter_by_shape() and the shape file we’ve already +loaded. The parameter crs is the coordinate system number +and the spatial_type describes the way the trips interact with the +project area. The four options are inside, outside, originating and +destinating. In this case we will look at the originating trips.

+
+trips_originating <- process_filter_by_shape(output_trips, leipzig_shp, crs = 25832, spatial_type = "originating" )
+

Using plot_mainmode_barchart() on the 507 originating +trips, results in the following chart:

+
+

Leipzig modal split - trips originating in project +area

+
+
+
+

Comparison plots +

+

In a next step we will compare the modal split of this base model +with the modal split of a scenario. To do this we need to load the +output_trips file from a scenario, e.g. this one. https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/leipzig/projects/namav/drt-outskirts/

+
+#loading the scenario data
+output_trips_scenario <- read_output_trips(trips_file_scenario_path, n_max = 5000)
+
+#filtering the scenario data
+trips_scenario_originating <- process_filter_by_shape(output_trips_scenario, leipzig_shp, crs = 25832, spatial_type = "originating")
+
+#creating the comparison plot
+plot_compare_mainmode_barchart(trips_originating, trips_scenario_originating)
+

The resulting plot looks like this: Leipzig modal split comparison

+
+
+

Maps +

+

The package also allows the plotting of spatial data. As an example +we can plot the trips originating in the project area to see where they +end.

+
+plot_map_trips(trips_originating, crs = 25832)
+

The result is an interactive map using leaflet, showing the places of +origin in blue and the destinations in red. (The following image is a +screenshot)

+
+

Leipzig - originating trips

+
+
+
+
+ + + +
+ + + +
+
+ + + + + + + diff --git a/docs/articles/Introduction.html b/docs/articles/Introduction.html new file mode 100644 index 0000000..e3499f0 --- /dev/null +++ b/docs/articles/Introduction.html @@ -0,0 +1,254 @@ + + + + + + + + +Introduction to MATSim R Library: analyzing transport simulations • matsim + + + + + + + + + + Skip to contents + + +
+ + + + +
+
+ + + + +
+

Introduction +

+

Welcome to the MATSim R package! MATSim R is an R package designed +for data processing and visualization and provides a wide range of +functions to create adjustable plots from processed data. This vignette +will give you an overview of the structure of the package and quickly +guide you through the process of creating plots using the functions +provided by the library.

+
+
+

Overall concept +

+

The purpose of this package is to provide a comprehensive set of +tools to efficiently analyze the output of MATSim runs. The package +primarily processes output data stored in CSV and XML files, especially +the so called “output_trips”, “legs” and “persons” files. By adhering to +this standardized naming convention, the package offers a streamlined +functionality for reading, processing, plotting and YAML file creation +for use in Simwrapper. XXXX LINK TO SIMWRAPPER GITHUB xxxx

+
+

Data flow and concept of matsim r package

+
+

The package is organized into four categories, each serving a +specific purpose:

+

Reading Functions: These functions begin with the +prefix “read_” and are designed to read and import the simulation +output. Field types are automatically set and a tibble is created.

+

Processing Functions: Functions with the prefix +“process_” form the core of the package’s data manipulation +capabilities. Users can apply a variety of transformations and +calculations to the loaded tibbles, allowing for advanced processing and +analysis tailored to their specific needs. Spatial input/output is also +supported, enabling users to manipulate and analyze the data on a +spatial level as well.

+

Plotting Functions: The plotting functions with the +prefix “plot_” enable users to create visualizations based on the +processed output data. These functions offer a range of plotting +options, allowing users to explore patterns, trends, and relationships +within the simulation results. The plotting functions encompass two +additional subcategories, namely mapping and +comparing. Within the mapping subcategory, +users can generate visualizations that overlay simulation results onto +geographical maps, providing insights into spatial patterns and +distributions. The comparing subcategory offers tools to compare +different simulation outputs, allowing analysis and understanding of +variations between scenarios or data sets.

+

Simwrapper: The simwrapper category is a specialized +group within the package that facilitates plotting using YAML files in +Simwrapper. This feature allows users to define complex plots and +visualizations in the YAML format, providing a convenient and efficient +way to generate custom visual representations of their simulation +data.

+

With this structure MATSim R aims to simplify the analysis of MATSim +runs. It provides users with an intuitive workflow, from reading and +processing the simulation output to generating informative plots and +leveraging the power of YAML-based configurations.

+
+
+

Installation +

+

MATSim R is not yet available at CRAN, so to install MATSim R using +github, you can use the following code:

+
+devtools::install_github("matsim-vsp/matsim-r")
+

However if you want to use a specific branch it can be specified like +so:

+
+devtools::install_github("matsim-vsp/matsim-r", ref = "{name of the branch}")
+
+
+

Loading the package +

+

Once installed, you can load the MATSim R package using the library() +function:

+ +
+
+

Loading Data +

+

The first step in analyzing your transport simulations is to load the +output data into your R environment. MATSim provides several functions +with the “read_” prefix for this purpose. Let’s take a look at how you +can load your simulation output stored in a CSV file:

+
+# Specify the file path to your simulation output. 
+# It can be a directory path or direct path to a file
+output_file <- "path/to/your/output_trips.csv"
+
+# Use the read_csv_trips() function to read the simulation data
+trips_data <- read_output_trips(output_file)
+

You can now proceed to explore and analyze the loaded data.

+
+
+

Data Processing +

+

MATSim R offers a range of processing functions, prefixed with +“process_”, to manipulate and transform your simulation data. These +functions allow you to perform various operations, such as filtering, +aggregating, and calculating additional metrics. Let’s see an example of +applying a transformation to our loaded data: XXXX IS THE EXAMPLE +CORRECT? - filter by shape?? XXXX

+
+# Filter the trips data to include only weekday trips
+weekday_trips <- process_filter_by_shape(trips_data)
+
+# Calculate the average trip duration
+average_duration <- process_get_travelwaittime_by_mainmode(weekday_trips)
+

Feel free to explore the different processing functions available in +the package to suit your specific analysis requirements.

+
+
+

Plotting +

+

Visualizing your simulation data is crucial for gaining insights and +effectively communicating your findings. MATSim R provides a wide range +of plotting functions to help you create informative visualizations. +Let’s create a scatter plot to visualize the relationship between trip +distance and trip duration:

+
+# Create a scatter plot of trip distance among different main modes
+plot_distance_by_mainmode_barchart(trips_data, x = "distance", y = "duration")
+

You can customize the plot appearance and explore other plot types, +such as line plots, bar charts, and spatial maps, using the various +plotting functions provided by MATSim R.

+
+
+

Advanced Features (still in development) +

+
    +
  • still in development -
  • +
+
+
+

Conclusion +

+

In this vignette, we introduced you to the MATSim R package, designed +specifically for analyzing MATSim outputs. We hope that you’ll have a +great experience using this library and we are glad to receive feedback +at https://github.com/matsim-vsp/matsim-r/tree/master +or at mail

+

For more details and specific usage examples, refer to the package +documentation and other vignettes available. Happy analyzing with MATSim +R!

+
+
+
+ + + +
+ + + +
+
+ + + + + + + diff --git a/docs/articles/Namings.html b/docs/articles/Namings.html new file mode 100644 index 0000000..3f4f380 --- /dev/null +++ b/docs/articles/Namings.html @@ -0,0 +1,119 @@ + + + + + + + + +Namings • matsim + + + + + + + + + + Skip to contents + + +
+ + + + +
+
+ + + +
+library(matsim)
+#> Warning: replacing previous import 'ggplot2::last_plot' by 'plotly::last_plot'
+#> when loading 'matsim'
+#> Warning: replacing previous import 'lubridate::stamp' by 'reshape::stamp' when
+#> loading 'matsim'
+#> Warning: replacing previous import 'plotly::rename' by 'reshape::rename' when
+#> loading 'matsim'
+#> Warning: replacing previous import 'purrr::discard' by 'scales::discard' when
+#> loading 'matsim'
+#> Warning: replacing previous import 'readr::col_factor' by 'scales::col_factor'
+#> when loading 'matsim'
+#> Warning: replacing previous import 'reshape::expand' by 'tidyr::expand' when
+#> loading 'matsim'
+
+
+ + + +
+ + + +
+
+ + + + + + + diff --git a/docs/articles/index.html b/docs/articles/index.html new file mode 100644 index 0000000..930b158 --- /dev/null +++ b/docs/articles/index.html @@ -0,0 +1,80 @@ + +Articles • matsim + Skip to contents + + +
+
+
+ + +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/authors.html b/docs/authors.html index f200719..29685d7 100644 --- a/docs/authors.html +++ b/docs/authors.html @@ -1,5 +1,5 @@ -Authors and Citation • matsimAuthors and Citation • matsim @@ -10,7 +10,7 @@ matsim - 0.1.8 + 0.2.0 - - - - - -
-
-
- -
-

Takes Table trips_output (from readTripsTable()), -to plot bar chart with with values that represent -time spent on traveling/waiting -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united')

-
- -
-

Usage

-
compareAverageTravelWait(
-  tripsTable1,
-  tripsTable2,
-  unite.columns = character(0),
-  united.name = "united",
-  dump.output.to = matsimDumpOutputDirectory,
-  only.files = FALSE
-)
-
- -
-

Arguments

-
tripsTable1
-

tible of trips_output (from readTripsTable())

- - -
tripsTable2
-

tible of trips_output (from readTripsTable())

- - -
unite.columns
-

vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns

- - -
united.name
-

character string, if columns were united, you can specify name for the resulting column in chart

- - -
dump.output.to
-

folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored

- - -
only.files
-

boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly

- -
-
-

Value

- - -

Bar Chart plot of average time spent on travel/wait

-
- -
- - -
- - - -
- - - - - - - diff --git a/docs/reference/compareBasePolicyOutput.html b/docs/reference/compareBasePolicyOutput.html deleted file mode 100644 index e871395..0000000 --- a/docs/reference/compareBasePolicyOutput.html +++ /dev/null @@ -1,105 +0,0 @@ - -Chooses a function to compare output_trips from the folders. -baseFolder contains all base outputs, policyFolder contains all policy outputs. — compareBasePolicyOutput • matsim - Skip to contents - - -
-
-
- -
-

Chooses a function to compare output_trips from the folders. -baseFolder contains all base outputs, policyFolder contains all policy outputs.

-
- -
-

Usage

-
compareBasePolicyOutput(
-  baseFolder,
-  policyFolder,
-  dump.output.to = matsimDumpOutputDirectory
-)
-
- -
-

Arguments

-
baseFolder
-

specifies data source folder with multiple base output_trips

- - -
policyFolder
-

specifies data source folder with multiple policy output_trips

- - -
dump.output.to
-

that saves result of all comparisons between each base and each policy. -For now it creates plotModalShiftBar() for the output_trips

- -
-
-

Value

- - -

list of tibbles, list of all base and policy output_trips as tibble

-
- -
- - -
- - - -
- - - - - - - diff --git a/docs/reference/compareBasePolicyShapeOutput.html b/docs/reference/compareBasePolicyShapeOutput.html deleted file mode 100644 index 493410e..0000000 --- a/docs/reference/compareBasePolicyShapeOutput.html +++ /dev/null @@ -1,115 +0,0 @@ - -Chooses a function to compare output_trips from the folders. -baseFolder contains all base outputs, policyFolder contains all policy outputs. — compareBasePolicyShapeOutput • matsim - Skip to contents - - -
-
-
- -
-

Chooses a function to compare output_trips from the folders. -baseFolder contains all base outputs, policyFolder contains all policy outputs.

-
- -
-

Usage

-
compareBasePolicyShapeOutput(
-  baseFolder,
-  policyFolder,
-  shapeFilePath,
-  crs,
-  dump.output.to = matsimDumpOutputDirectory
-)
-
- -
-

Arguments

-
baseFolder
-

specifies data source folder with multiple base output_trips

- - -
policyFolder
-

specifies data source folder with multiple policy output_trips

- - -
shapeFilePath
-

specifies shapeFile used for comparison

- - -
crs
-

numeric of EPSG code or proj4string, can be found in network/config file from output directory of MATSim simulation

- - -
dump.output.to
-

that saves result of all comparisons between each base and each policy. -For now it creates plotModalShiftBar() for the output_trips

- -
-
-

Value

- - -

list of tibbles, list of all base and policy output_trips as tibble

-
- -
- - -
- - - -
- - - - - - - diff --git a/docs/reference/compareModalDistanceDistribution.html b/docs/reference/compareModalDistanceDistribution.html deleted file mode 100644 index 83bfb2b..0000000 --- a/docs/reference/compareModalDistanceDistribution.html +++ /dev/null @@ -1,122 +0,0 @@ - -Bar Chart with distance travelled on x-axis and difference of number of trips on y-axis — compareModalDistanceDistribution • matsim - Skip to contents - - -
-
-
- -
-

Takes 2 Tables trips_output (from readTripsTable()), -to plot bar chart with with values that represent -difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled -Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united.name(by default 'united')

-
- -
-

Usage

-
compareModalDistanceDistribution(
-  tripsTable1,
-  tripsTable2,
-  unite.columns = character(0),
-  united.name = "united",
-  dump.output.to = matsimDumpOutputDirectory,
-  only.files = FALSE
-)
-
- -
-

Arguments

-
tripsTable1
-

tible of trips_output (from readTripsTable()), number of trips of this table will be extracted from number of trips of tripsTable1

- - -
tripsTable2
-

tible of trips_output (from readTripsTable()), from number of trips of this table number of trips of tripsTable1 will be extracted

- - -
unite.columns
-

vector of character strings, that represent patterns of columns to be united, changes name of all transport modes in the tibble copy to united.name = "united" that matches PATTERNS given in unite.columns

- - -
united.name
-

character string, if columns were united, you can specify name for the resulting column in chart

- - -
dump.output.to
-

folder that saves and configures yaml for simwrapper dashboard. folder where png of plot is stored

- - -
only.files
-

boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly

- -
-
-

Value

- - -

Bar Chart plot of count of trips among distance travelled

-
- -
- - -
- - - -
- - - - - - - diff --git a/docs/reference/createCountScatterPlot.html b/docs/reference/createCountScatterPlot.html index c4b28f0..0d87f90 100644 --- a/docs/reference/createCountScatterPlot.html +++ b/docs/reference/createCountScatterPlot.html @@ -1,12 +1,12 @@ Creates a Via-Style scatterplot for each run — createCountScatterPlot • matsimCreates a Via-Style scatterplot for each run — createCountScatterPlot • matsimCreates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper — deriveODMatrix • matsim - Skip to contents - - -
-
-
- -
-

Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper

-
- -
-

Usage

-
deriveODMatrix(
-  tripsTable,
-  shapePath,
-  crs,
-  dump.output.to = matsimDumpOutputDirectory,
-  simwrapper = FALSE,
-  colnames = "numeric",
-  outer = FALSE
-)
-
- -
-

Arguments

-
tripsTable
-

table of output trips(from readTripsTable) or path to trips_output file

- - -
shapePath
-

full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name)

- - -
crs
-

numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation

- - -
dump.output.to
-

path to a folder to save csv file of ODMatrix

- - -
simwrapper
-

create output in a simwrapper form if set to path of the shapefile

- - -
colnames
-

if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values

- - -
outer
-

logical that represent if the table should contain outside flow of the shape, it isn't

- -
-
-

Value

- - -

tibble of origin/destination matrix

-
- -
- - -
- - - -
- - - - - - - diff --git a/docs/reference/filterByRegion.html b/docs/reference/filterByRegion.html deleted file mode 100644 index d2ab757..0000000 --- a/docs/reference/filterByRegion.html +++ /dev/null @@ -1,129 +0,0 @@ - -Filtering of trips_table(from readTripsTable) depending on how they located in given shape — filterByRegion • matsim - Skip to contents - - -
-
-
- -
-

Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). -Please be aware that this filterByRegion currently only works, when one geometry is loaded.) -transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) -and filters the trips from table depending on *.inshape flags: -if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape -if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape -if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape -if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape

-
- -
-

Usage

-
filterByRegion(
-  tripsTable,
-  shapeTable,
-  crs,
-  start.inshape = TRUE,
-  end.inshape = TRUE
-)
-
- -
-

Arguments

-
tripsTable
-

tibble of trips_output (from readTripsTable())

- - -
shapeTable
-

sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)

- - -
crs
-

numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation

- - -
start.inshape
-

bool, defines trips to conclude (see Description)

- - -
end.inshape
-

bool, defines trips to conclude (see Description)

- -
-
-

Value

- - -

tibble, with filtered trips depending on shapeTable and special flags (see Description)

-
- -
- - -
- - - -
- - - - - - - diff --git a/docs/reference/generateXYHexagonYaml.html b/docs/reference/generateXYHexagonYaml.html index 7050b32..a789568 100644 --- a/docs/reference/generateXYHexagonYaml.html +++ b/docs/reference/generateXYHexagonYaml.html @@ -1,5 +1,5 @@ -Creates/adds XY hexagon definition of output trips to a summary dashboard — generateXYHexagonYaml • matsimCreates/adds XY hexagon definition of output trips to a summary dashboard — generateXYHexagonYaml • matsim @@ -10,7 +10,7 @@ matsim - 0.1.8 + 0.2.0 - - - - - -
-
-
- -
-

Reads an coordinate referenec system of MATSim output directory -from output_config.xml

-
- -
-

Usage

-
getCrsFromConfig(folder)
-
- -
-

Arguments

-
folder
-

specifies path to find config

- -
-
-

Value

- - -

code of coordinate reference system

-
- -
- - -
- - - -
- - - - - - - diff --git a/docs/reference/index.html b/docs/reference/index.html index 2de7a3c..71ad4e0 100644 --- a/docs/reference/index.html +++ b/docs/reference/index.html @@ -1,5 +1,5 @@ -Function reference • matsimFunction reference • matsim @@ -10,7 +10,7 @@ matsim - 0.1.8 + 0.2.0 + + + + + +
+
+
+ +
+

loadNetwork - Loads a MATSim XML network file, creating a nodes tibble and a links tibble. +Any node and link attribute records in the network are stored as +additional columns in the respective node and link tibbles.
+The links table is automatically joined with the nodes table so that +node x/y coordinates (and any other node attributes) are available on the +links table without additional processing.

+

These functions are provided for compatibility with older version of +the matsimr package. They may eventually be completely +removed.

plotModalSplitPieChart - Takes Table trips_output (from read_output_trips()), +to plot pie chart with with values that represent +percentage of using transport modes from trips

+

plotModalSplitBarChart - Takes Table trips_output (from read_output_trips()), +to plot bar chart with with values that represent +percentage of using transport modes from trips

+

readTripsTable - Loads a MATSim output_trips file from file or archive path, +creating a tibble

+

plotAverageTravelWait - Takes Table trips_output (from read_output_trips()), +to plot bar chart with with values that represent +time spent on traveling/waiting +Using parameters unite.columns, specific columns could be given, +to unite them in 1 mode with the name united_name(by default 'united')

+

plotModalDistanceDistribution - Takes Table trips_output (from read_output_trips()), +to plot bar chart with with values that represent +number of trips ~ distance travelled +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united')

+

compareModalDistanceDistribution - Takes 2 Tables trips_output (from read_output_trips()), +to plot bar chart with with values that represent +difference of number of trips between tripsTable2 and tripsTable1 ~ distance travelled +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united')

+

plotTripDistanceByMode - Takes Table trips_output (from read_output_trips()), +to plot bar chart with with values that represent +average distance traveled ~ main mode used +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united')

+

plotTripCountByDepTime - Takes Table trips_output (from read_output_trips()), +to make line plot with with values that represent +count of trips for a specific departure time by main_mode +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united')

+

plotActivityEndTimes - Takes Table trips_output (from read_output_trips()), +to make line plot with with values that represent the +number of activities ending at a specific time. +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united')

+

plotArrivalTimesPerTripPurpose - Takes Table trips_output (from read_output_trips()), +to make line plot with with values that represent +count of destination activities for a specific arrival time +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united')

+

plotDepartureTimesPerTripPurpose - Takes Table trips_output (from read_output_trips()), +to make line plot with with values that represent +count of destination activities for a specific arrival time +Using parameters unite.columns, specific columns could be given, to unite them in 1 mode with the name united_name(by default 'united')

+

plotTripDistancedByType - Takes Table trips_output (from read_output_trips()), +to plot bar chart with with values that represent +travelled distance of each tripType related to the shapeTable

+

plotModalShiftSankey - Takes two trips_table (from readTripsTable), and collects +changes between transport mode distribution of these tables +to make alluvial diagram from this data
+Function calculates number of each transport mode used in +first and second table, and draws plot that represent how +distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) +Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united_name is "united") +Using parameter show.onlyChanges

+

plotModalShiftBar - Takes two trips_table (from readTripsTable), and collects +changes between transport mode distribution of these tables +to make bar chart diagram with dodging positioning from this data
+Function calculates number of each transport mode used in +first and second table, and draws plot that represent how +distribution of transport mode has changed (f. e. what part of concrete trasport mode changed to another) +Using parameter unite.columns transport modes that match PATTERN in unite.columns can be united in 1 transport mode type (by default united_name is "united") +Using parameter show.onlyChanges

+

plotMapWithFilteredTrips - Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file)) +transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +and filters the trips from table depending on *.inshape flags:
+if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape +
if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape +
if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape +
if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape +
result of filtering is plotted on map of shapeTable where green points are startpoints of trip and red points are endpoints of trip

+

plotMapWithTrips - Plots start and end coordinates of the given trips table on an osm map

+

plotTripTypesPieChart - plots distribution of every type of trips(inside, outside, origin and destinating) in Pie Chart

+

compareTripTypesBarChart - Creates BarChart of changing trip types(originating,transit etc) between 2 tables +and saves output to dump.output.to

+

plotMapWithTripsType - plots every type of trips(inside, outside, origin and destinating) on map

+

compareBasePolicyOutput - Chooses a function to compare output_trips from the folders. +baseFolder contains all base outputs, policyFolder contains all policy outputs.

+

compareBasePolicyShapeOutput - Chooses a function to compare output_trips from the folders. +baseFolder contains all base outputs, policyFolder contains all policy outputs.

+

appendDistanceCategory - adds to trips output tibble additional column that represent distance as category

+

filterByRegion - Filtering of trips_table(from readTripsTable) depending on how they located in given shape
+Takes trips_table and shapeTable(sf object from file representing geographical data, can be received by using function st_read(path_to_file). +Please be aware that this filterByRegion currently only works, when one geometry is loaded.) +transforms both objects to match mutual CRS(network.xml from MATSimOutputDirectory) +and filters the trips from table depending on *.inshape flags:
+if start.inshape = TRUE & end.inshape = TRUE return table that contains trips inside given shape
+if start.inshape = TRUE & end.inshape = FALSE return table that contains trips which starts in shape and ends out of the shape
+if start.inshape = FALSE & end.inshape = TRUE return table that contains trips which ends in shape and starts out of the shape
+if start.inshape = FALSE & end.inshape = FALSE return table that contains trips which starts and ends our of the given shape

+

deriveODMatrix - Creates an instance of ODMatrix(origin/destination) in conventional form or for the simwrapper

+

getCrsFromConfig - Reads an coordinate reference system of MATSim output directory +from output_config.xml

+

transformToSf - Transforms trips_table tibble (from readTripsTable) from tibble to sf (table with attribute features and geometry feature)
+Takes trips_table (from readTripsTable) and transforms trips_table to sf object using start_x, end_x, start_y, end_y as a geometry features +deletes from resulting data.frame start_x, end_x, start_y, end_y.
+And adds wkt column, if geometry.type = st_mulitpoint(), or geometry.type = st_linestring()
+Or adds start_wkt and end_wkt, if geometry.type = st_point()
+Added column/columns projected to given CRS (coordinate reference system), +that can be taken from network file of MATSimOutputDirectory
+Function also sets attribute geometry.type to resulting table to character value of "POINT","MULTIPOINT","LINESTRING" +to get which type of table was generated, if it is needed

+
+ +
+

Usage

+
loadNetwork(filename)
+
+plotModalSplitPieChart(
+  tripsTable,
+  unite.columns = character(0),
+  united.name = "united",
+  dump.output.to = matsimDumpOutputDirectory,
+  only.files = FALSE
+)
+
+plotModalSplitBarChart(
+  tripsTable,
+  unite.columns = character(0),
+  united.name = "united",
+  dump.output.to = matsimDumpOutputDirectory,
+  only.files = FALSE
+)
+
+readTripsTable(input_path = ".", n_max = Inf)
+
+plotAverageTravelWait(
+  tripsTable,
+  unite.columns = character(0),
+  united.name = "united",
+  dump.output.to = matsimDumpOutputDirectory,
+  only.files = FALSE
+)
+
+compareAverageTravelWait(
+  tripsTable1,
+  tripsTable2,
+  unite.columns = character(0),
+  united.name = "united",
+  dump.output.to = matsimDumpOutputDirectory,
+  only.files = FALSE
+)
+
+plotModalDistanceDistribution(
+  tripsTable,
+  unite.columns = character(0),
+  united.name = "united",
+  dump.output.to = matsimDumpOutputDirectory,
+  only.files = FALSE
+)
+
+compareModalDistanceDistribution(
+  tripsTable1,
+  tripsTable2,
+  unite.columns = character(0),
+  united.name = "united",
+  dump.output.to = matsimDumpOutputDirectory,
+  only.files = FALSE
+)
+
+plotTripDistanceByMode(
+  tripsTable,
+  unite.columns = character(0),
+  united.name = "united",
+  dump.output.to = matsimDumpOutputDirectory,
+  only.files = FALSE
+)
+
+plotTripCountByDepTime(
+  tripsTable,
+  unite.columns = character(0),
+  united.name = "united",
+  dump.output.to = matsimDumpOutputDirectory,
+  only.files = FALSE
+)
+
+plotActivityEndTimes(
+  tripsTable,
+  unite.columns = character(0),
+  united.name = "united",
+  dump.output.to = matsimDumpOutputDirectory,
+  only.files = FALSE
+)
+
+plotArrivalTimesPerTripPurpose(
+  tripsTable,
+  unite.columns = character(0),
+  united.name = "united",
+  dump.output.to = matsimDumpOutputDirectory,
+  only.files = FALSE
+)
+
+plotDepartureTimesPerTripPurpose(
+  tripsTable,
+  unite.columns = character(0),
+  united.name = "united",
+  dump.output.to = matsimDumpOutputDirectory,
+  only.files = FALSE
+)
+
+plotTripDistancedByType(
+  tripsTable,
+  shapeTable,
+  crs,
+  dump.output.to = matsimDumpOutputDirectory
+)
+
+plotModalShiftSankey(
+  tripsTable1,
+  tripsTable2,
+  show.onlyChanges = FALSE,
+  unite.columns = character(0),
+  united.name = "united",
+  dump.output.to = matsimDumpOutputDirectory
+)
+
+plotModalShiftBar(
+  tripsTable1,
+  tripsTable2,
+  unite.columns = character(0),
+  united.name = "united",
+  dump.output.to = matsimDumpOutputDirectory,
+  output.name = "modalShiftBarChart"
+)
+
+plotMapWithFilteredTrips(
+  table,
+  shapeTable,
+  crs,
+  start.inshape = TRUE,
+  end.inshape = TRUE,
+  optimized = FALSE
+)
+
+plotMapWithTrips(table, crs, optimized = FALSE)
+
+plotTripTypesPieChart(table, shapeTable, crs)
+
+compareTripTypesBarChart(
+  tripsTable1,
+  tripsTable2,
+  shapeTable,
+  crs,
+  dump.output.to = matsimDumpOutputDirectory
+)
+
+plotMapWithTripsType(table, shapeTable, crs, optimized = FALSE)
+
+compareBasePolicyOutput(
+  baseFolder,
+  policyFolder,
+  dump.output.to = matsimDumpOutputDirectory
+)
+
+compareBasePolicyShapeOutput(
+  baseFolder,
+  policyFolder,
+  shapeFilePath,
+  crs,
+  dump.output.to = matsimDumpOutputDirectory
+)
+
+appendDistanceCategory(tripsTable)
+
+filterByRegion(
+  tripsTable,
+  shapeTable,
+  crs,
+  start.inshape = TRUE,
+  end.inshape = TRUE
+)
+
+deriveODMatrix(
+  tripsTable,
+  shapePath,
+  crs,
+  dump.output.to = matsimDumpOutputDirectory,
+  simwrapper = FALSE,
+  colnames = "numeric",
+  outer = FALSE
+)
+
+getCrsFromConfig(folder)
+
+transformToSf(table, crs, geometry.type = st_multipoint())
+
+ +
+

Arguments

+
filename
+

File to load. Can be XML or gzipped XML

+ + +
tripsTable
+

table of output trips(from readTripsTable) or path to trips_output file

+ + +
unite.columns
+

vector of character string, changes name of all transport modes in the tibble copy to united_name = "united" that matches PATTERNS given in unite.columns

+ + +
united.name
+

if columns were united, you can specify name for the resulting column in plot

+ + +
dump.output.to
+

path to a folder to save csv file of ODMatrix

+ + +
only.files
+

boolean, that represent if plotting inside project is needed, by default FALSE - means function gives out a plot by plot_ly

+ + +
input_path
+

character string, path to MATSim output directory or http link to the file.

+ + +
n_max
+

integer, maximum number of lines to read within output_trips

+ + +
tripsTable1
+

tibble of trips_output (from read_output_trips(),f.e. base case)

+ + +
tripsTable2
+

tibble of trips_output (from read_output_trips(),f.e. policy case)

+ + +
shapeTable
+

sf object(data.frame with geometries), can be received by using st_read(path_to_geographical_file)

+ + +
crs
+

numeric of EPSG code or proj4string, can be found in network file from output directory of MATSim simulation

+ + +
show.onlyChanges
+

boolean, if it is set to TRUE => sankey diagram only contains changes on axes

+ + +
table
+

tibble of trips_output (from read_output_trips())

+ + +
start.inshape
+

bool, defines trips to conclude (see Description)

+ + +
end.inshape
+

bool, defines trips to conclude (see Description)

+ + +
optimized
+

bool, by default FALSE and gives interactive plot using leaflet, if TRUE using image with ggplot

+ + +
baseFolder
+

specifies data source folder with multiple base output_trips

+ + +
policyFolder
+

specifies data source folder with multiple policy output_trips

+ + +
shapeFilePath
+

specifies shapeFile used for comparison

+ + +
shapePath
+

full path to shapefile (if simwrapper TRUE, folder with shapeFile should contain also .dbf with the same name)

+ + +
simwrapper
+

create output in a simwrapper form if set to path of the shapefile

+ + +
colnames
+

if the specific shapefile contains known columns, they could be specified as name for columns OD. If not given then they get numeric values

+ + +
outer
+

logical that represent if the table should contain outside flow of the shape, it isn't

+ + +
folder
+

specifies path to find config

+ + +
geometry.type
+

function of sf transformation, geometry.type can be (by default is st_multipoint())
+!!!st_point()-resulting table contains 2 geometries start_wkt and end_wkt, representing start and end POINTs, and have type POINT!!! or
+!!!st_multipoint()-resulting table contains 1 geometry wkt, representing start and end POINTS as MULTIPOINT!!! or
+!!!st_linestring() - resulting table contains 1 geometry wkt, representing line between start and end points as LINESTRING!!!

+ +
+
+

Value

+ + +

loadNetwork - "nodes" and "links" tibbles in a list object.

+ + +

plotModalSplitPieChart - Pie Chart plot of transport mode distribution, values given in percents

+ + +

plotModalSplitBarChart - Bar Chart plot of transport mode distribution, values given in percents

+ + +

readTripsTable - tibble of output_trips

+ + +

plotAverageTravelWait - Bar Chart plot of average time spent on travel/wait

+ + +

plotModalDistanceDistribution Bar Chart plot of count of trips among distance travelled

+ + +

compareModalDistanceDistribution - Bar Chart plot of count of trips among distance travelled

+ + +

plotTripDistanceByMode - Bar Chart plot of distance traveled per mode

+ + +

plotTripCountByDepTime - Line Chart plot of trips count by departure mode per mode

+ + +

plotActivityEndTimes Line plot with departure time x-axis and number start activities on y-axis

+ + +

plotArrivalTimesPerTripPurpose - Line plot with arrival time x-axis and number end activities on y-axis

+ + +

plotDepartureTimesPerTripPurpose - Line plot with arrival time x-axis and number end activities on y-axis

+ + +

plotTripDistancedByType - Bar Chart plot of distance traveled by type

+ + +

plotModalShiftSankey - Alluvial diagram that represents changes in transport mode distribution of trip tables

+ + +

plotModalShiftBar - plots Bar Chart of transport mode changes with additional files for simwrapper

+ + +

plotMapWithFilteredTrips - plot with trips filtered depending on flags *.inshape on map from shapeTable

+ + +

plotMapWithTrips - plot with trips

+ + +

plotTripTypesPieChart - plot with percentage of each type of trips

+ + +

compareTripTypesBarChart - plot with percentage of each type of trips between 2 tables

+ + +

plotMapWithTripsType - plot that contains every trip with defined trip type

+ + +

compareBasePolicyOutput - list of tibbles, list of all base and policy output_trips as tibble

+ + +

compareBasePolicyShapeOutput - list of tibbles, list of all base and policy output_trips as tibble

+ + +

tibble of output_trips with distance category column

+ + +

filterByRegion - tibble, with filtered trips depending on shapeTable and special flags (see Description)

+ + +

deriveODMatrix - tibble of origin/destination matrix

+ + +

getCrsFromConfig - code of coordinate reference system

+ + +

transformToSf - sf object (data.frame with geometries depending to geometry.type)

+
+
+

Details

+ + +

plotModalSplitPieChart now a synonym for plot_mainmode_piechart
plotModalSplitBarChart now a synonym for plot_mainmode_barchart
plotAverageTravelWait now a synonym for plot_travelwaittime_mean_barchart
plotModalDistanceDistribution now a synonym for plot_distcat_by_mainmode_barchart
plotTripDistanceByMode now a synonym for plot_distance_by_mainmode_barchart
plotTripCountByDepTime now a synonym for plot_trips_count_by_deptime_and_mainmode_linechart
plotActivityEndTimes not part of package(contained false logic)
plotArrivalTimesPerTripPurposenow a synonym for plot_arrtime_by_act
plotDepartureTimesPerTripPurpose now a synonym for plot_deptime_by_act
plotTripTypesPieChart now a synonym for plot_spatialtype_by_shape_piechart
plotMapWithFilteredTripsnot part of package, you can filter before drawing a map
plotMapWithTripsnow a synonym for plot_map_trips
plotMapWithTripsType now a synonym for plot_map_trips_by_spatialcat
plotTripDistancedByType now a synonym for plot_distance_by_spatialcat_barchart
plotModalShiftBar now a synonym for plot_compare_mainmode_barchart
plotModalShiftSankey now a synonym for plot_compare_mainmode_sankey
compareAverageTravelWait now a synonym for plot_compare_travelwaittime_by_mainmode_barchart
compareTripTypesBarChartnow a synonym for plot_compare_count_by_spatialcat_barchart
compareModalDistanceDistribution now a synonym for plot_compare_distcat_by_mainmode_barchart
compareBasePolicyOutput is not used in new package version, and is prepared to be completely removed from package + If you would like to keep it in new package, write at soboliev@campus.tu-berlin.de
compareBasePolicyShapeOutput is not used in new package version, and is prepared to be completely removed from package + If you would like to keep it in new package, write at soboliev@campus.tu-berlin.de
appendDistanceCategorynow a synonym for process_append_distcat
filterByRegion now a synonym for process_filter_by_shape
deriveODMatrix now a synonym for process_get_od_matrix
getCrsFromConfignow a synonym for process_get_crs_from_config
transformToSf now a synonym for process_convert_table_to_sf
readTripsTablenow a synonym for read_output_trips
readConfig now a synonym for read_config

+
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/mergeCountsAndLinks.html b/docs/reference/mergeCountsAndLinks.html index 8b2b047..26a1f1f 100644 --- a/docs/reference/mergeCountsAndLinks.html +++ b/docs/reference/mergeCountsAndLinks.html @@ -1,7 +1,7 @@ -Load Counts, a limited number of Linkstats and Network links as joined tibble into memory — mergeCountsAndLinks • matsimJoin counts and linkstats to the network, creating a tibble into memory — mergeCountsAndLinks • matsim @@ -12,7 +12,7 @@ matsim - 0.1.8 + 0.2.0
aggr_to
-

Determinates if data should be aggregated to hour values or DTV, can either be "day" or "hour"

+

Determines if data should be aggregated into hourly bins or as daily traffic volume, can either be "day" or "hour"

earliest
-

Lower limit to filter link stats by time, default is 0

+

Integer. Lower limit to filter link stats by time, default = 0.

latest
-

Upper limit to filter link stats by time, default is 86400 (midnight)

+

Integer. Upper limit to filter link stats by time, default = 86400 (midnight).

Value

-

Long-format tibble with MATSim link id as key ("loc_id"), traffic volume from MATSim runs and link type

+

Long-format tibble with MATSim link id as key ("loc_id"), traffic volumes from MATSim runs and link type