在R中,从数千个外部文件中有效并尽可能快地计算数据帧

问题描述 投票:0回答:1

我正在构建一个Shiny应用程序,其中需要使用大量外部源文件来一遍又一遍地计算大型ggplot2增强的数据帧。我正在寻找最快,最有效的方法。在下面的段落中,我将进一步研究到目前为止的主题和代码,并提供输入数据以帮助您提供帮助。

我使用的是赫尔辛基地区旅行时间矩阵2018,这是由赫尔辛基大学研究小组Digital Geography Lab提供的数据集。该数据使用赫尔辛基首都地区的广义地图,在250 x 250米的像元中(在我的代码grid_f中),通过以下方式计算地图中所有像元之间的旅行时间(网格ID称为YKR_ID,n = 13231)公共交通,私家车,自行车和步行。计算结果存储在定界的.txt文件中,该文本文件是到特定单元格ID的所有传播时间的一个文本文件。数据可供下载at this website, under "Download the data"。注意,解压缩后的数据大小为13.8 GB。

这里是从数据集中的文本文件中选择的内容:

from_id;to_id;walk_t;walk_d;bike_s_t;bike_f_t;bike_d;pt_r_tt;pt_r_t;pt_r_d;pt_m_tt;pt_m_t;pt_m_d;car_r_t;car_r_d;car_m_t;car_m_d;car_sl_t
5785640;5785640;0;0;-1;-1;-1;0;0;0;0;0;0;-1;0;-1;0;-1
5785641;5785640;48;3353;51;32;11590;48;48;3353;48;48;3353;22;985;21;985;16
5785642;5785640;50;3471;51;32;11590;50;50;3471;50;50;3471;22;12167;21;12167;16
5785643;5785640;54;3764;41;26;9333;54;54;3764;54;54;3764;22;10372;21;10370;16
5787544;5785640;38;2658;10;7;1758;38;38;2658;38;38;2658;7;2183;7;2183;6

[我的兴趣是使用ggplot2可视化此250x250m赫尔辛基地区地图,用于一种行驶模式,即私家车,使用任何可能的13231个单元格ID(如果用户愿意),可以重复进行。因此,重要的是尽可能快且高效地提取数据帧。对于这个问题,让我们集中精力从外部文件中获取和处理数据,并仅使用一个特定的id值。

概括地说,在我生成250 x 250米网格空间数据集ggplot2::fortify()grid_f版本之后,

  • 我需要浏览所有13231 Travel Time Matrix 2018文本文件
  • 仅选择每个文件中的相关列(from_idto_idcar_r_tcar_m_tcar_sl_t)>
  • 在每个文件中使用from_id(在这种情况下为origin_id <- "5985086")选择相关行
  • 将结果行添加到强化的空间数据grid_f
  • 我的代码如下:

# Libraries
library(ggplot2)
library(dplyr)
library(rgdal)
library(data.table)
library(sf)
library(sp)

# File paths. ttm_path is the folder which contains the unchanged Travel
# Time Matrix 2018 data from the research group's home page
ttm_path <- "HelsinkiTravelTimeMatrix2018"
gridpath <- "MetropAccess_YKR_grid_EurefFIN.shp"


#### Import grid cells
# use this CRS information throughout the app
app_crs <- sp::CRS("+init=epsg:3067")

# Read grid shapefile and transform
grid_f <- rgdal::readOGR(gridpath, stringsAsFactors = TRUE) %>%
  sp::spTransform(., app_crs) %>%
  # preserve grid dataframe data in the fortify
  {dplyr::left_join(ggplot2::fortify(.),
                    as.data.frame(.) %>%
                      dplyr::mutate(id = as.character(dplyr::row_number() - 1)))} %>%
  dplyr::select(-c(x, y))

以上代码仅可运行一次。下面的代码或多或少会以不同的origin_id来重复运行。

#### Fetch TTM18 data
origin_id <- "5985086"
origin_id_num <- as.numeric(origin_id)

# column positions of columns from_id, to_id, car_r_t, car_m_t, car_sl_t
col_range <- c(1, 2, 14, 16, 18)

# grid_f as data.table version
dt_grid <- as.data.table(grid_f)

# Get filepaths of all of the TTM18 data. Remove metadata textfile filepath.
all_files <- list.files(path = ttm_path, 
                        pattern = ".txt$", 
                        recursive = TRUE, 
                        full.names = TRUE)
all_files <- all_files[-length(all_files)]

# lapply function
TTM18_fetch <- function(x, col_range, origin_id) {
  res <- fread(x, select = col_range)
  res <- subset(res, from_id == origin_id)
  return(res)
}

# The part of the code that needs to be fast and efficient
result <- 
  lapply(all_files, FUN = TTM18_fetch, col_range, origin_id_num) %>%
  data.table::rbindlist(., fill = TRUE) %>%
  data.table::merge.data.table(dt_grid, ., by.x = "YKR_ID", by.y = "to_id")

数据框result应具有66155行的12个变量,每个250x250米的网格单元为5行。列为YKR_IDlonglatorderholepieceidgroupfrom_idcar_r_tcar_m_tcar_sl_t

我当前的lapply()data.table::fread()解决方案大约需要2-3分钟才能完成。我认为这已经是一个不错的成就,但是我无能为力,认为有更好,更快的方法可以完成此任务。到目前为止,我已经尝试了以下替代方法:

  • 传统的for循环:这显然是一个缓慢的解决方案
  • 我试图教给我更多关于R中的向量化函数的知识,但这并没有引向任何地方。 Used this link
  • 尝试与with()失败,using this SO questioninspired by this SO question
  • 由于我使用的是Windows环境,因此查看了parallel包,但最终没有利用它
  • 试图寻找其他方法来解决apply()sapply()的问题,但值得注意的是。>
  • 关于为什么我没有对ggplot2::fortify之前的数据进行全部处理,我只是发现使用SpatialPolygonsDataFrame麻烦。

    谢谢您的时间。

我正在构建一个Shiny应用程序,其中需要使用大量外部源文件来一遍又一遍地计算大型ggplot2增强的数据帧。我正在寻找最快的...

r ggplot2 data.table spatial data-import
1个回答
1
投票

[无论何时我试图弄清楚如何提高R的性能功能上,我一般采用以下方法。首先,我寻找任何可能不必要的函数调用或标识多个位置的函数函数调用可以简化为一个。然后,我在我的地方寻找地方通过对每个代码进行基准测试而产生最大时间损失的代码分开分开。使用microbenchmark package可以轻松完成此操作。

例如,我们可以问是否有更好的性能管道

© www.soinside.com 2019 - 2024. All rights reserved.