Ускорение st_buffer на многих сегментах линии

#r #sf

Вопрос:

Я занимаюсь буферизацией дорожной сети со множеством небольших линейных сегментов, и это занимает много времени. Когда я попытался использовать профилировщик, чтобы узнать, из-за чего это заняло так много времени, большую часть времени занимал «.Call». Поэтому мне интересно, что происходит в .Раздел вызовов и могу ли я что-нибудь сделать, чтобы ускорить этот процесс?

Вот воспроизводимый пример:

 library(sf)
my_linestring_sfc <- st_sfc(
  st_linestring(matrix(c(-10, -10, -1, -1, 0, 0), ncol = 2, byrow = TRUE)), 
  st_linestring(matrix(c(10, -10, 1, -1, 0, 0), ncol = 2, byrow = TRUE)), 
  st_linestring(matrix(c(0, 0, 0, 1, 0, 10), ncol = 2, byrow = TRUE))
)

line_lst <- map(1:10000 *5, ~my_linestring_sfc   .x)

lins <- do.call(c, line_lst)

profvis::profvis({st_buffer(lins, 100)})
 

И как выглядит график пламени профиля для меня:
огнемет

Ответ №1:

Обратите внимание, что это .Call относится к внутреннему вызову внутри st_buffer . Вероятно, он вызывает c библиотеки или другой оптимизированный скомпилированный код. Вряд ли вам удастся легко ускорить это. Упрощение ваших линий может быть одним из способов ускорить процесс, практически не ухудшая качество вашего результата, это можно сделать с st_simplify помощью .

Немного подробнее, если вы посмотрите на код sf:::st_buffer.sfc , который вы видите, он вызывает: sf:::CPL_geos_op который сам по себе в основном является оболочкой для вызова внутренней скомпилированной функции.

Комментарии:

1. Превосходно! сократите время на 1/4. Если другим нужны указания по параметру dTolerance в st_simplify, см. Этот вопрос