Мгэи сф: высшее экономическое и юридическое образование в Москве
СФ МГЭИ, факультет экономики и права — контактная информация — Учёба.ру
Колледж экономических международных связей
Для выпускников 9 и 11 классов.
Высшее образование онлайн
Федеральный проект дистанционного образования.
Я б в нефтяники пошел!
Пройди тест, узнай свою будущую профессию и как её получить.
Технологии будущего
Вдохновитесь идеей стать крутым инженером, чтобы изменить мир
Студенческие проекты
Студенты МосПолитеха рассказывают о своих изобретениях
Химия и биотехнологии в РТУ МИРЭА
120 лет опыта подготовки
Международный колледж искусств и коммуникаций
МКИК — современный колледж
Английский язык
Совместно с экспертами Wall Street English мы решили рассказать об английском языке так, чтобы его захотелось выучить.
15 правил безопасного поведения в интернете
Простые, но важные правила безопасного поведения в Сети.
Олимпиады для школьников
Перечень, календарь, уровни, льготы.
Первый экономический
Рассказываем о том, чем живёт и как устроен РЭУ имени Г.В. Плеханова.
Билет в Голландию
Участвуй в конкурсе и выиграй поездку в Голландию на обучение в одной из летних школ Университета Радбауд.
Цифровые герои
Они создают интернет-сервисы, социальные сети, игры и приложения, которыми ежедневно пользуются миллионы людей во всём мире.
Работа будущего
Как новые технологии, научные открытия и инновации изменят ландшафт на рынке труда в ближайшие 20-30 лет
Профессии мечты
Совместно с центром онлайн-обучения Фоксфорд мы решили узнать у школьников, кем они мечтают стать и куда планируют поступать.
Экономическое образование
О том, что собой представляет современная экономика, и какие карьерные перспективы открываются перед будущими экономистами.
Гуманитарная сфера
Разговариваем с экспертами о важности гуманитарного образования и областях его применения на практике.
Молодые инженеры
Инженерные специальности становятся всё более востребованными и перспективными.
Табель о рангах
Что такое гражданская служба, кто такие госслужащие и какое образование является хорошим стартом для будущих чиновников.
Карьера в нефтехимии
Нефтехимия — это инновации, реальное производство продукции, которая есть в каждом доме.
МГЭИ (СФ), Ставрополь, Россия
Страна
Город
Учебное заведение
Имя
Фамилия
Факультет
Кафедра
Год окончания
Расширенный поиск
Джимиев Руслан
Санкт-Петербург, Россия
Подробнее
Лебедь Александра
Ставрополь, Ставропольский край, Россия
Подробнее
Тихонов Виталик
Краснодар, Краснодарский край, Россия
Подробнее
Зимин Сергей
Ставрополь, Ставропольский край, Россия
Возраст: 46, (28 декабря 1976)
Подробнее
Давоян Диана
Ставрополь, Ставропольский край, Россия
Подробнее
Grig Fran
Ставрополь, Ставропольский край, Россия
Подробнее
Nickolaxp Nk
Москва, Россия
Возраст: 36, (6 сентября 1986)
Подробнее
Слепенко Алексей
Ставрополь, Ставропольский край, Россия
Подробнее
Поклонник Тайный
Ставрополь, Ставропольский край, Россия
Возраст: 39, (1 февраля 1984)
Подробнее
Енина Таня
Ставрополь, Ставропольский край, Россия
Подробнее
Вишенка Стася
Ставрополь, Ставропольский край, Россия
Подробнее
Гринченко Нина (Келасьева)
Ставрополь, Ставропольский край, Россия
Возраст: 35, (21 июня 1987)
Подробнее
Багаев Алан
Владикавказ, Россия
Подробнее
Артющенко Инна (Лынникова)
Ставрополь, Ставропольский край, Россия
Подробнее
Паслер Светлана
Ставрополь, Ставропольский край, Россия
Подробнее
Скотарева Елена
Ставрополь, Ставропольский край, Россия
Подробнее
Переверзев Алексей
Черкесск, Россия
Возраст: 46, (18 августа 1976)
Подробнее
Нозадзе Анна
Ставрополь, Ставропольский край, Россия
Подробнее
Морозова Ирина
Ставрополь, Ставропольский край, Россия
Возраст: 39, (16 августа 1983)
Подробнее
Губина Елена
Ставрополь, Ставропольский край, Россия
Подробнее
Подсолнух Семечка
Ставрополь, Ставропольский край, Россия
Подробнее
Никонова Анастасия
Ставрополь, Ставропольский край, Россия
Возраст: 38, (19 апреля 1984)
Подробнее
Григорян Давид
Ставрополь, Ставропольский край, Россия
Возраст: 33, (6 августа 1989)
Подробнее
Васильченко Алиса
Ставрополь, Ставропольский край, Россия
Возраст: 32, (6 октября 1990)
Подробнее
Волкова Юлия (Патерикина)
Ставрополь, Ставропольский край, Россия
Возраст: 43, (6 января 1980)
Подробнее
Akinina Мария
Ставрополь, Ставропольский край, Россия
Возраст: 35, (18 июля 1987)
Подробнее
Паньков Николай
Ставрополь, Ставропольский край, Россия
Возраст: 38, (30 сентября 1984)
Подробнее
Пертина Александра
Ставрополь, Ставропольский край, Россия
Возраст: 43, (18 июля 1979)
Подробнее
Зубцова Елена
Ставрополь, Ставропольский край, Россия
Возраст: 34, (10 марта 1988)
Подробнее
Евдошенко Леша
Ставрополь, Ставропольский край, Россия
Возраст: 33, (3 августа 1989)
Подробнее
Факультеты
- Бухгалтерский учет, анализ и аудит
- Менеджмент организации
- Психология
- Финансы и кредит
- Экономический
- Юриспруденция
Как далеко до ближайшей больницы? • Martin Geissmann
Запрос времени в пути
Нам нужно облако точек, из которых мы хотим узнать кратчайшее время в пути до ближайшей больницы. Мы могли бы использовать равномерно распределенную матрицу точек или, как это делается далее, точки, выбранные случайным образом. Это будет основой для интерполяции позже.
Во-первых, давайте определим крайности, в которых должны находиться точки, здесь крайности Швейцарии. Они взяты из Википедии.
лонмин <- 5,956303 лонмакс <- 10,491944 латиница <- 45.818031 latmax <- 47.808264
Затем мы создаем случайно распределенное облако из 100 точек и добавляем их на ранее созданную карту листовок.
н <- 100 сет.сид(123) randompts <- табличка (id=1:n, lon = runif(n, min = lonmin, max = lonmax), lat = runif (n, min = latmin, max = latmax)) базовая карта %>% addCircleMarkers(data = randompts, lng = ~lon, lat = ~lat, color = "red", radius = 6, group = "Случайные точки") %>% addLayersControl(overlayGroups = c("Больницы", "Случайные точки"))
Чтобы запросить время в пути с нашего сервера OSRM, мы используем osrm::osrmTable(src, dst)
, где src
— это источники (наши случайные точки), а dst
— пункты назначения (больницы). Он рассчитает время в пути от каждого источника до каждого пункта назначения. В показанном здесь случае это 8200 наблюдений (100 случайных источников, 82 больницы).
Конечно, не имеет особого смысла вычислять время в пути, скажем, из Цюриха в больницу скорой помощи в Лугано, которая находится в 200 км. Это можно решить, разделив карту на несколько (перекрывающихся) областей и снова объединив их в конце. Однако, поскольку ответы от нашего собственного (низкоспециализированного!) сервера OSRM все равно приходят очень быстро (<1 секунды), мы не беспокоимся.
Также обратите внимание, что нам нужно ввести кадры данных со столбцами id
/ lon
/ lat
. Тибблс не работал.
randompoints_df <- randompts %>% as.data.frame() Hospitals_df <- Emergency_hospitals_geocoded %>% dplyr::select(id = Inst, долгота, широта) %>% as.data.frame() t0 <- Sys.time() DistanceTable <- osrmTable (src = randompoints_df, dst = Hospitals_df) Sys.time () - t0 Distancetable %> % summary()
Затем мы извлекаем минимальное время в пути (до следующей больницы) и добавьте его на карту. Обратите внимание, что некоторые точки перемещены, потому что фактическая исходная точка — это ближайшая дорога из региона, для которого мы загрузили карту (Швейцария).
minddistances <- bind_cols(distancetable$sources, mintime = apply(distancetable$durations, 1, мин)) %>% as_tibble() %>% мутировать (mintime_str = as.character (mintime)) %>% отчетливый() binpal <- colorBin("Красные", домен = 0:max(mindistances["mintime"])) базовая карта %>% addCircleMarkers(data = minddistances, lng = ~lon, lat = ~lat, radius = 10, цвет = ~ binpal (mintime), всплывающее окно = ~ mintime_str, group = "Время в пути") %>% addLayersControl(overlayGroups = c("Больницы", "Время в пути"))
Для интерполяции нам понадобится более 100 точек. Поскольку у нас есть собственный сервер, это не проблема. Тем не менее, в настройках по умолчанию он выдает ошибку, когда делается слишком много запросов. Есть возможность разрешить больше запросов, но мне это не помогло.
Всего было бы 10 000 баллов (100 запросов по 100 в каждом).
nruns <- 100 п <- 100 сет.сид(13) для (r в 1:nruns) { randompts <- табличка (id=1:n, lon = runif(n, min = lonmin, max = lonmax), lat = runif (n, min = latmin, max = latmax)) randompoints_df <- randompts %>% as.data.frame() Hospitals_df <- Emergency_hospitals_geocoded %>% dplyr::select(id = Inst, долгота, широта) %>% as.data.frame() # запросить сервер OSRM t0 <- Sys.time() DistanceTable <- osrmTable (src = randompoints_df, dst = Hospitals_df) rrt <- as.numeric(Sys.time() - t0, unit = "secs") %> % round(3) mindistances_i <- bind_cols(distancetable$sources, mintime = apply(distancetable$durations, 1, мин)) %>% as_tibble() %>% мутировать (mintime_str = as.character (mintime)) minddistances <- bind_rows(mindistances, minddistances_i) print(str_c("run: ", r, ", время ответа на запрос: ", rrt, "secs")) }
Это не займет много времени. Удалим дубликаты и сохраним. Перед этим мы также добавляем координаты самих больниц с
mintime
of 0.
mindistances <- bind_rows(mindistances, Hospitals_df %>% dplyr::select(долгота, широта) %>% мутировать (mintime = 0, mintime_str = "0")) разумные расстояния <- разумные расстояния %>% отчетливый() minddistances %>% write_rds("data/mindistances.RDS")
Обратите внимание, что многие записи были удалены. Это связано с тем, что OSRM обрабатывает входные точки за пределами границы загруженного набора данных как точки с ближайшими координатами внутри границы страны. Вот где чаще всего происходит перекрытие.
nrow(mindistances)
## [1] 5500
Посмотрим на нашу карту.
binpal <- colorBin("Красные", домен = 0:max(mindistances["mintime"])) базовая карта %>% addCircleMarkers(data = minddistances, lng = ~lon, lat = ~lat, radius = 5, цвет = ~ binpal (mintime), всплывающее окно = ~ mintime_str, группа = "Время в пути", непрозрачность = 0,1) %>% addLegend(data = minddistances, pal = binpal, values = ~mintime, group = "Время в пути", title = "Время в минутах до ближайшей больницы") %> % addLayersControl(overlayGroups = c("Больницы", "Время в пути")) %>% hideGroup("Больницы")
Далее мы интерполируем точки и создадим растровый слой, который будет отображаться над картой.
Интерполяция
Для этого подготовим следующую функцию. Мы используем алгоритм ближайших соседей (k = 100).
библиотека(сп) библиотека(растр)
## ## Прикрепление пакета: 'raster'
## Следующий объект замаскирован от 'package:dplyr': ## ## select
## Следующий объект замаскирован из 'package:tidyr': ## ## экстракт
библиотека(sf)
## Связывание с GEOS 3.6.2, GDAL 2.2.3, PROJ 4.9.3
библиотека(gstat) interpolateSurface <- функция (данные, gridRes = 500) { # Создать новый набор данных, который будет пространственным - sp::class data_sp <- данные %>% as.data.frame() # Превратить данные в пространственный объект - spacePointsDataFrame координаты(data_sp) <- ~долгота+широта # Определяем CRS - систему отсчета координат proj4string(data_sp) <- crs("+init=epsg:4326") # Сделать его объектом sf::class crs <- "+init=epsg:4326" координаты <- c("долгота", "широта") # (sf: Простой набор функций) data_sf <- st_as_sf(data_sp, координаты = координаты, crs = crs) # WEB проекция Меркатора data_sp_mp <- spTransform(data_sp, CRSobj = "+init=epsg:3857") # Ограничительная рамка, разрешение и сетка для интерполяции boxx = data_sp_mp@bbox deltaX = as. integer((boxx[1,2] - boxx[1,1]) + 1,5) deltaY = as.integer((boxx[2,2] - boxx[2,1]) + 1,5) gridSizeX = deltaX / gridRes gridSizeY = deltaY / gridRes grd = GridTopology(boxx[1], c(gridRes,gridRes), c(gridSizeX,gridSizeY)) pts = SpatialPoints (координаты (grd)) proj4string(pts) <- crs("+init=epsg:3857") # Интерполировать ячейки сетки Ближайший сосед r.raster <- raster::raster() экстент(r.raster) <- экстент(pts) # установить экстент res(r.raster) <- gridRes # 500 # установить размер ячейки crs(r.raster) <- crs("+init=epsg:3857") # установить CRS gs <- gstat(формула = mintime~1, местоположения = data_sp_mp, nmax = 100, установить = список (IDP = 0)) nn <- интерполировать (r.raster, gs) # Растры результата - поверхности data_list <- список(data_sf, nn) имена(список_данных) <- c("данные", "nn") возврат (список_данных) }
Аргумент gridRes
определяет разрешение растра. Более высокое значение приведет к более пикселизированному растру, более низкое значение приведет к очень длительному времени вычислений.
# # Не беги! # попытки <- seq(400, 5000, by = 200) # # ц = с() # for (попробовать несколько раз) { # t0 <- Sys.time() # # interpolateSurface(mindistances, gridRes = try) # # tsi <- as.numeric(Sys.time() - t0, unit = "secs") # # ts <- добавить(ts, tsi) # } # # cpttimes_plotdata <- tibble (gridRes = попытки, секунды = ts) # # cpttimes_plotdata %>% # ggplot(aes(x = gridRes, y = секунды)) + # геом_точка() + # geom_line(color = "red", alpha = 0.5) + # labs(title = "Время вычисления для interpolateSurface()", # subtitle = "используя наши данные с ~5500 баллами")
Теперь, когда у нас есть функция и известно время вычислений, давайте запустим ее в последний и окончательный раз с gridRes = 500
и сохраним ее для дальнейшего использования.
minraster <- interpolateSurface(mindistances, gridRes = 500) minraster %>% write_rds("data/minraster.RDS")
Наконец, прежде чем добавить его на интерактивную карту, мы хотим разрезать его по границам страны. Для этого мы используем шейп-файл из GADM, который мы можем автоматически загрузить в R с помощью
raster::getData("GADM", страна, уровень)
. Затем мы используем raster::mask()
, чтобы соответствующим образом обрезать растр.
библиотека (rgdal)
## rgdal: версия: 1.4-8, (версия SVN 845) ## Расширения библиотеки абстракции геопространственных данных для R успешно загружены ## Загруженная среда выполнения GDAL: GDAL 2.2.3, выпущенная 20 ноября 2017 г. ## Путь к общим файлам GDAL: /usr/share/gdal/2.2 ## Двоичный файл GDAL, созданный с помощью GEOS: TRUE ## Загруженная среда выполнения PROJ.4: Rel. 4.9.3, 15 августа 2016 г., [PJ_VERSION: 493] ## Путь к общим файлам PROJ.4: (определяется автоматически) ## Ссылка на версию sp: 1.4-0
# switzerland <- getData("GADM", country = "CHE", level = 0) # швейцария %>% saveRDS("postdata/время вождения/швейцария.RDS") швейцария <- readRDS("postdata/время вождения/швейцария.RDS") switzerland_t <- spTransform(Швейцария, CRSobj = "+init=epsg:3857") minraster_shape <- mask(minraster$nn, switzerland_t)
binpal <- colorBin("Красные", domain = 0:max(mindistances["mintime"])) базовая карта %>% addRasterImage(minraster_shape, group = "Время в пути", opacity = 0,8, цвета = "Красные") %>% addLayersControl(overlayGroups = c("Больницы", "Время в пути"))
Определение среднего расстояния ходьбы до ближайшего бара в Аккре
Где лучше всего жить в Аккре или любом другом городе? Ну, явно район с большим количеством доступных баров или, по крайней мере, бар в нескольких минутах ходьбы. Это небольшой эксперимент для меня, чтобы попытаться построить тепловую карту пешеходного расстояния до ближайшего бара в R. Это включает в себя получение данных из OSM, планирование пешеходных маршрутов и времени в OSRM, построение графика в брошюре
и ggplot2
, используя пакеты sp
, sf
, raster
, jstat
, osmdata
и osrm
.
Этот код сильно вдохновлен и содержит некоторый прямой код из этих источников, все заслуги этих авторов. Пожалуйста, взгляните на то, что они сделали, и на некоторые из замечательных руководств, которые они написали:
- https://rcarto.github.io/caRtosm/index.html
- https://mtmx.github.io/blog/bistrographie /
- https://dieghernan.github.io/cartographyvignette/
- https://rpubs.com/mgei/drivingtimes
- https://www.user2019.fr/static/pres/lt257361.pdf
В этом проекте используются следующие пакеты:
библиотека (tidyverse) библиотека (osmdata) библиотека (сф) библиотека (спатстат) библиотека (маптулс) библиотека (растр) библиотека (RColorBrewer) библиотека (буклет) библиотека (сп) библиотека (гстат) библиотека (osrm) библиотека (ggmap) библиотека (ггтекст) библиотека (картография) библиотека (показать текст) # Растровый пакет переопределяет функцию выбора dplyr, поэтому assign я назначил ее обратно выберите <- dplyr::select
loc <- "Accra Ghana" # Это город, для которого я хочу создать карту.bounding_box <- getbb(loc) # эта функция ищет квадратную рамку для этого города. accra_boundries <-bounding_box %>% opq() %>% add_osm_feature (ключ = 'имя', значение = "Метрополитен Аккры") %>% osmdata_sp() accra_boundries <- accra_boundries$osm_multipolygons[1,]
С помощью команды available_tags('amenity')
мы можем увидеть, какие типы различных удобств различает OSM.
available_tags('удобства')
## [1] "животное_посадка" "животное_приют" ## [3] "arts_centre" "банкомат" ## [5] "baby_hatch" "baking_oven" ## [7] "банк" "бар" ## [9] "барбекю" "скамейка" ## [11] "bicycle_parking" "bicycle_rental" ## [13] "bicycle_repair_station" "biergarten" ## [15] "boat_rental" "boat_sharing" ## [17] "бордель" "бюро_де_обмена" ## [19] "bus_station" "кафе" ## [21] "car_rental" "car_sharing" ## [23] "автомойка" "казино" ## [25] "зарядная_станция" "уход за детьми" ## [27] "кинотеатр" "клиника" ## [29] "часы" "колледж" ## [31] "community_centre" "conference_centre" ## [33] "здание суда" "крематорий" ## [35] "стоматолог" "dive_centre" ## [37] "врачи" "питьевая_вода" ## [39] "вождение_школа" "посольство" ## [41] "fast_food" "ferry_terminal" ## [43] "fire_station" "firepit&action=edit&redlink=1" ## [45] "food_court" "фонтан" ## [47] "топливо" "азартные игры" ## [49] "give_box" "grave_yard" ## [51] "grit_bin" "тренажерный зал" ## [53] "больница" "hunting_stand" ## [55] "мороженое" "интернет_кафе" ## [57] "детский сад" "кухня" ## [59] "kneipp_water_cure" "language_school" ## [61] "библиотека" "торговая площадка" ## [63] "monastery" "motorcycle_parking" ## [65] "музыкальная_школа" "ночной клуб" ## [67] "дом престарелых" "парковка" ## [69] "parking_entrance" "parking_space" ## [71] "аптека" "фото_киоск" ## [73] "место поклонения" "планетарий" ## [75] "полиция" "почтовый ящик" ## [77] "post_depot" "post_office" ## [79] "тюрьма" "паб" ## [81] "public_bath" "public_bookcase" ## [83] "public_building" "ranger_station" ## [85] "переработка" "refugee_site" ## [87] "ресторан" "санитарная_свалка_станция" ## [89] "сауна" "школа" ## [91] "приют" "душ" ## [93] "социальный_центр" "социальное_сооружение" ## [95] "стрипклуб" "студия" ## [97] "свингерклуб" "такси" ## [99] "телефон" "театр" ## [101] "туалеты" "ратуша" ## [103] "toy_library" "университет" ## [105] "осмотр_транспортного средства" "торговый_автомат" ## [107] "ветеринария" "мусорная_корзина" ## [109] "утилизация_отходов" "станция_перегрузки_отходов" ## [111] "water_point" "watering_place"
Для этого проекта я просто выберу «биргартен» (не думаю, что в Аккре их слишком много), «паб», «бар» и «ночной клуб».
# выберите соответствующие удобства bars_accra <- st_bbox(accra_boundries) %>% opq() %>% add_osm_feature (ключ = «удобства», value = c("пивной сад", "паб", "бар", "ночной клуб")) %>% osmdata_sp() # выбираем только точки локации bar_locations <- bars_accra$osm_points %>% as_tibble() %>% выберите (osm_id, имя, долгота, широта) # подмножить только те точки, которые попадают в городские границы Аккры accra_boundries <- sp::spTransform(accra_boundries, CRS("+proj=longlat")) координаты (bar_locations) <- ~ долгота + широта proj4string(bar_locations) <- proj4string(accra_boundries) bars_accra_data_frame <- bind_cols(over(bar_locations, accra_boundries) %>% select(type), as_tibble(bar_locations) %>% select(osm_id, имя, долгота, широта)) %>% фильтр(!is.na(тип)) %>% as_tibble() %>% мутировать (через (где (есть.фактор), ~ as.character (.))) %>% выберите (-тип)
Давайте посмотрим первые 5 результатов:
bars_accra_data_frame %>% head(5)
## # Буквы: 5 x 4 ## osm_id имя долгота широта #### 1 373239152 Спот Epo -0,185 5,56 ## 2 1151761364 Блум Бар -0,180 5,56 ## 3 1270558373 Бумеранг -0,217 5,58 ## 4 1368374881 Роксбери -0,204 5,57 ## 5 1616146876 Жимолость - Лабоне -0,173 5,57
Это несколько излишество, можно просто построить столбцы как точки в ggplot2
и использовать geom_density2d()
для построения плотности ядра. Однако, поскольку я работаю с геопространственными точками, этот вариант предлагает немного больше гибкости и немного лучше выглядит. Это также означает, что я могу нанести полученную оценку плотности на карту
листовки
, что позволяет мне наводить курсор на столбцы, чтобы увидеть их названия.
# правильную пространственную привязку для Ганы можно найти здесь: https://spatialreference.org/ref/ CRS_string <- "+proj=aea +lat_1=20 +lat_2=-23 +lat_0=0 +lon_0=25 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs" # перейти от объекта sp к объекту st и изменить ссылку на проекцию accra_boundries_st <- st_transform(st_as_sf(accra_boundries), CRS_string) # устанавливаем координаты баров на одну и ту же ссылку координаты (bars_accra_data_frame) <- ~ долгота + широта proj4string(bars_accra_data_frame) <- proj4string(accra_boundries) bar_locations_crs <- st_transform(st_as_sf(bars_accra_data_frame), CRS_string) # Преобразовать их в пространственные объекты (SpatialPointsDataFrames) bar_locations_spatial <- as(bar_locations_crs, "Пространственный") accra_boundries_spatial <- as.owin(as(accra_boundries_st, "Пространственное")) # извлекаем только координаты баров bar_locations_spatial_points <- координаты (bar_locations_spatial) # используя функцию ppp() из пакета spatstat # для создания набора данных точечного шаблона в двумерной плоскости. bars.ppp <- ppp(x = bar_locations_spatial_points[1], y = bar_locations_spatial_points[2], окно = accra_boundries_spatial) # создаем плотность этого паттерна, используя тот же пакет density_bars <-density.ppp(x = bars.ppp, сигма = 500, eps = с (10,10), диггл = ИСТИНА) # преобразовать эту плотность в растровый объект raster_density_bars<- растр(density_bars) * 1000 * 1000 raster_density_bars <- raster_density_bars + 1 # перепроецировать этот растровый объект в правильную пространственную привязку проекция (raster_density_bars) <- CRS_string
Теперь я могу построить как этот растр плотности, так и фактическое расположение столбцов в Аккре
color_breaks <- getBreaks(values(raster_density_bars), nclass = 8, method = "equal") cols <- brewer.pal(9, "Зеленые") # Я скачал эту иконку с https://fontawesome.com/ (CC BY 4.0) icons <- iconList( bar = makeIcon("beer-solid.svg", iconWidth = 8, iconHeight = 8))
листовка( опции = листовкаОпции( attributionControl = FALSE)) %>% addProviderTiles(провайдеры$CartoDB.Positron) %>% добавитьМаркеры(данные=bars_accra_data_frame, значок = значки["бар"], метка = ~имя) %>% addRasterImage(raster_density_bars, непрозрачность = 0,6, цвета = "Зеленый") %>% addLegend(labels = round(rev(color_breaks),0), цвета = столбцы, title = "Плотность баров (KDE)
sigma=500m
(баров на км2)")
В Аккре есть две очень разные группы баров. Они существуют не потому, что это зоны ночной жизни, а потому, что они были частью проекта по точному нанесению на карту определенных областей в Аккре. Более подробную информацию об этом проекте можно найти здесь и здесь. Это важное ограничение этих данных и любых других данных OSM, которые можно использовать
. я не очень привередлив к барам). Чтобы рассчитать это расстояние ходьбы, мне нужно запросить какой-либо сервис маршрутизации, чтобы рассчитать расстояние ходьбы (или фактическое время ходьбы) от заданного места до ближайшего бара. Карты Google были бы одним из вариантов использования, но это не бесплатный API, поэтому машина маршрутизации с открытым исходным кодом (OSRM) является более подходящей альтернативой с открытым исходным кодом. Доступна демонстрационная онлайн-версия, но ее будет недостаточно для количества пеших расстояний, которые я хочу рассчитать.
OSRM
Для запуска OSRM на компьютере с Windows в идеале должен быть установлен Docker Desktop (https://www.docker.com/products/docker-desktop). Для этого вам потребуется более новая версия Windows 10 (версия 2004 или более поздняя, выпущенная в мае 2020 г.). Инструкцию по установке можно найти здесь.
После установки рабочего стола Docker вы также должны убедиться, что у вас установлена команда wget
для Windows (если вы используете операционную систему Windows).
здесь. Теперь просто откройте программу Docker Desktop и интерфейс командной строки (введите «CMD» в строку поиска Windows, чтобы открыть интерфейс командной строки).
После установки Docker необходимо установить OSRM Бэкэнд OSRM можно найти здесь.
docker pull osrm/osrm-backend
Во-вторых, перейдите в папку, из которой вы хотите запустить этот проект, с помощью команды cd
cd ИМЯ_ПАПКИ\ИМЯ_ПАПКИ_ПАПКИ\ETC
Затем загрузите карту страны, которую вы хотите использовать в данном случае Гана.
wget http://download.geofabrik.de/africa/ghana-latest.osm.pbf
Теперь извлеките данные из этого файла (эти команды предназначены для Windows, специальные команды для Linux см. в OSRM).
обучающую страницу). Поскольку меня интересуют пешеходные расстояния, я использую opt/foot.lua
вместо opt/car.lua
.
docker run -t -v %cd%:/data osrm/osrm-backend osrm-extract -p /opt/foot.lua /data/ghana-latest.osm.pbf #docker run -t -v %cd%:/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/ghana-latest.osm.pbf
Это закончится чем-то вроде этого:
[info] ok, после 15.887s [info] Обработано 2214859 ребер [info] Расширение: 103744 узлов/сек и 31209 ребер/сек [информация] Чтобы подготовить данные для маршрутизации, запустите: ./osrm-contract "/data/ghana-latest.osrm" [информация] ОЗУ: пиковое количество использованных байтов: 1406402560
Теперь вам нужно разделить данные с помощью этой команды:
docker run -t -v %cd%:/data osrm/osrm-backend osrm-partition /data/ghana-latest.osrm
Что даст вам вывод, подобный этому:
[info] Уровень 1 #cells 4479 #boundary nodes 102100, источники: avg. 15, направления: ср. 22, записей: 1923670 (15389360 байт) [info] Уровень 2 #cells 370 #boundary nodes 14768, источники: avg. 26, направления: ср. 39, записей: 492861 (3942888 байт) [info] Уровень 3 #cells 23 #boundary nodes 1300, источники: avg. 37, направления: ср.54, записей: 60780 (486240 байт) [информация] Уровень 4 #ячейки 1 #граничные узлы 0, источники: ср. 0, направления: ср. 0, записей: 0 (0 байт) [info] Бисекция заняла 13,7743 секунды. [информация] ОЗУ: пиковое количество использованных байтов: 487546880
Теперь вам нужно настроить данные с помощью этой команды:
docker run -t -v %cd%:/data osrm/osrm-backend osrm-customize /data/ghana-latest.osrm
Что даст вам вывод, похожий на этот:
[info] Написание настройки MLD заняло 0,421035 секунд [info] Написание графика заняло 0,503969 секунды [информация] ОЗУ: пиковое количество использованных байтов: 400687104
Теперь вы готовы использовать OSRM, для запуска программы просто запустите:
docker run -t -i -p 5000:5000 -v %cd%:/data osrm/osrm-backend osrm-routed --algorithm mld --max-table-size 10000 /data/ghana-latest.osrm
Что даст вам примерно такой вывод:
[информация] запуск двигателей, v5.22.0 [информация] Тем: 8 [информация] IP-адрес: 0.0.0.0 [информация] IP-порт: 5000 [информация] сжатие http 1.1 обрабатывается zlib версии 1.2.8 [информация] Прослушивание: 0.0.0.0:5000 [info] работает и ждет запросов
Чтобы сообщить R, что я использую свой собственный сервер, задайте следующую команду:
options(osrm.server = "http://localhost:5000/", osrm.profile = "walk")
У меня есть расположение баров в Аккре, следующим шагом будет получение координатной сетки, откуда рассчитываются расстояния. Я мог бы просто взять случайную выборку координат, лежащих в пределах Аккры, и рассчитать расстояние ходьбы от этих точек до ближайшего бара, но более эффективно создать сетку координат. Это означает, что каждые 0,001 градуса по долготе и 0,001 градуса по широте в ограничивающей рамке Аккры создается координата. (Я знаю, что разница в долготе в один градус не равна разнице в километрах в один градус широты. Кроме того, позже я интерполирую данные, чтобы любые крошечные пробелы были сглажены.)
См.
эта отличная статья о том, как вычисляется скорость ходьбы в OSRM. Таким образом, базовая скорость пешехода установлена на уровне 5 км/ч, а штрафные множители используются для различных типов дорог и дорожных покрытий. Например, ступеньки имеют множитель 0,5, что означает, что скорость ходьбы по ступенькам не 5 км/ч, а $5\cdot0,5 = 2,5$ км/ч.
# Ввод функции osrm разрешает только эти 3 столбца bar_locations_lat_long <- as_tibble(bars_accra_data_frame) %>% мутировать (id = 1:n()) %>% выберите (идентификатор, долгота, широта) # создаем сетку, используя expand.grid() сетка <- expand.grid(seq(bounding_box[1,1], bounding_box[1,2], by = 0,001), seq(bounding_box[2,1], bounding_box[2,2], by = .001)) %>% as_tibble() %>% мутировать (id = 1:n()) %>% переместить (идентификатор) %>% setNames(c("id", "долгота", "широта")) # сделать границы Аккры доступными для построения в ggplot2, accra_boundries_poly <- укрепить (accra_boundries) # построим сетку на фоне шейп-файла Accra ggplot() + geom_polygon (данные = accra_boundries_poly, aes (x = долгота, y = широта, группа = группа), fill = NA, col = "черный") + geom_point (данные = сетка, aes (х = долгота, у = широта), col = "красный", размер = .001)
nrow(сетка)
## [1] 103041
В этой ограничительной рамке 103041 различных точек, но не все они попадают в пределы города Аккра. Для подмножества только тех точек, которые попадают в Аккру, я использую следующий код, используя команду over()
из пакета sp
.
координаты (сетка) <- ~ долгота + широта proj4string(сетка) <- proj4string(accra_boundries) # выбираем только те точки, которые лежат в черте города points_in_polygon <- bind_cols(over(grid, accra_boundries) %>% select(osm_id), as_tibble(grid) %>% select(id, lon, lat)) %>% фильтр(!is.na(osm_id)) %>% as_tibble() %>% выберите (-osm_id) %>% мутировать (id = 1: n ()) # построим это снова ggplot() + geom_polygon (данные = accra_boundries_poly, aes (x = долгота, y = широта, группа = группа), fill = NA, col = "черный") + geom_point (данные = points_in_polygon, aes (х = долгота, у = широта), col = "красный", размер = 0,001)
nrow(points_in_polygon)
## [1] 13601
Теперь осталось всего 13 601 точка. Выполнение следующей части кода потребует некоторого времени, так как ему необходимо рассчитать расстояние/время в пути от 13 601 местоположения до 315 баров (всего 4 284 315 маршрутов) и выбрать кратчайшее время в пути. Определенно есть способы оптимизировать этот код (например, я мог бы решить рассчитать маршрут только до 10 ближайших баров на расстоянии большого круга и рассчитать время в пути из них). Но я собираюсь запустить этот код только один раз, а компьютеры терпеливы. Я разделяю точки на несколько разных разделов, чтобы немного ограничить сложность сервера OSRM.
# Разделить данные на куски по 500 points_in_polygon$section <- rep(1:ceiling(nrow(points_in_polygon)/500), each=500)[1:nrow(points_in_polygon)] # создать пустой список list_points <- список() # итерация различных чанков по 500 точек for(i в уникальном(points_in_polygon$section)){ # выбрать текущий чанк data_points <- points_in_polygon %>% фильтр (раздел == i) %>% выберите (-раздел) # это функция OSRM, которая вычисляет время в пути travel_time_story <- osrmTable(src = data_points, dst = bar_locations_lat_long, мера = "длительность") # для каждой точки функция вычисляет время в пути до каждого бара # Мне нужно только сохранить продолжительность ходьбы до ближайшего бара list_points[[i]] <- bind_cols(travel_time_story$sources, mintime = применить (длительность путешествия_время_истории $, 1, мин)) %>% as_tibble() } # для точек с расстоянием более 1 часа ходьбы я ограничиваю их 1 часом (для построения графика) # Я также привязываю продолжительность путешествия к исходной сетке points_in_polygon_with_travel_times <- data.table::rbindlist(list_points) %>% mutate(mintime_capped = ifelse(mintime > 60, 60, mintime)) %>% bind_cols (points_in_polygon %>% выберите (долгота, широта) %>% переименовать(lon.org = lon, лат.орг = лат))
Если я нарисую это, вот как это выглядит. Это начинает напоминать то, что я ищу.
ggplot() + geom_polygon (данные = accra_boundries_poly, aes (x = долгота, y = широта, группа = группа), fill = NA, col = "черный") + geom_point (данные = points_in_polygon_with_travel_times, aes(x = lon.org, y = lat.org, col = mintime_capped), размер = .1) + viridis::scale_color_viridis (опция = "магма", направление = -1) + geom_point (данные = bar_locations_lat_long, aes(x = долгота, y = широта), col = "синий", size = 3, shape = 10)
Среднее и медианное время ходьбы (в минутах) от любой заданной точки в Аккре, Гана, до ближайшего бара от этой точки можно рассчитать как:
## [1] 17.13582
медиана (points_in_polygon_with_travel_times$mintime)
## [1] 12,8
Неплохо!
Теперь мне нужно сделать из этих точек растровый файл, выполнить интерполяцию между точками, спроецировать его на реальную карту Аккры и сделать график немного красивее.
# установить разрешение разрешение сетки <- 5 # преобразовать данные в SpatialPointsDataFrame с проекцией долготы/широты data_sp <- points_in_polygon_with_travel_times координаты (data_sp) <- ~lon.org+lat.org proj4string(data_sp) <- crs("+init=epsg:4326") координаты <- c("долгота", "широта") data_sf <- st_as_sf(data_sp, coords = coords, crs = proj4string(data_sp)) # Сбросить его на проекцию Ганы data_sp_mp <- spTransform(data_sp, CRSobj = CRS_string) # Здесь я устанавливаю ограничивающую рамку, которую хочу использовать (плюс немного поля) # Я также создаю новую сетку, которая используется для интерполяции boxx = data_sp_mp@bbox deltaX = as.integer((boxx[1,2] - boxx[1,1]) + 1,5) deltaY = as.integer((boxx[2,2] - boxx[2,1]) + 1,5) gridSizeX = deltaX / gridRes gridSizeY = deltaY / gridRes grd = GridTopology(boxx[1], c(gridRes,gridRes), c(gridSizeX,gridSizeY)) pts = SpatialPoints (координаты (grd)) # Сбросить его на проекцию Ганы proj4string(pts) <- crs(CRS_string) # создаем пустой растр r.raster <- raster::raster() # установить экстент растра в точки данных, которые я использовал экстент (r.raster) <- экстент (pts) # устанавливаем разрешение (размер ячейки) res(r.raster) <- gridRes # установить правильный crs crs(r.raster) <- crs(CRS_string) # # Интерполировать ячейки сетки Функция ближайшего соседа (k = 20) с помощью пакета gstat gs <- gstat (формула = mintime_capped~1, местоположения = data_sp_mp, nmax = 20, установить = список (IDP = 0)) # Это может занять некоторое время raster_object <- интерполировать (r.raster, gs) # добавить оба объекта в список минрастр <- список(data_sf, raster_object) имена(минрастр) <- c("данные", "растровый_объект") accra_boundries_t <- spTransform(accra_boundries, CRSobj = CRS_string) minraster_shape <- маска (minraster$raster_object, accra_boundries_t)
Чтобы построить это в ggplot2
Мне нужно сделать полигональный объект из растрового объекта.
# вы можете использовать этот код для ускорения печати. minraster_ shape_aggr <- совокупность (minraster_ shape, факт = 4) # опять же, запуск этой функции может занять некоторое время # если это занимает много времени, установите более высокий коэффициент агрегации # или более высокая сетка # или меньше баллов minraster_ shape_rtp <- rasterToPolygons (minraster_ shape_aggr) # вернуться к стандартной долготной/широтной проекции для построения графиков minraster_ shape_rtp <- spTransform (minraster_ shape_rtp, CRS("+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0")) # Теперь я укрепляю эти данные, чтобы построить их minraster_shape_rtp@data$id <- 1:nrow(minraster_ shape_rtp@data) minraster_ shape_fort <- укрепить (minraster_ shape_rtp, данные = minraster_shape_rtp@data) minraster_ shape_fort <- слияние (minraster_ shape_fort, minraster_shape_rtp@data, by.x = 'идентификатор', by.y = 'идентификатор')
Я хотел бы иметь реальную карту в качестве фона, поэтому я загружаю ее с Stamenmap и использовать функцию, которую я нашел здесь, чтобы обрезать многоугольник и построить результат.
# скачать плитки фоновой карты # для этого уровня масштабирования вам, возможно, придется выполнить эту команду несколько раз Accra_city_map <- get_stamenmap(bbox = accra_boundries@bbox, maptype = "terrain", масштаб = 15, кадрирование = F) # загружаем функцию для создания растрового файла из тайлов ggmap_rast <- функция (карта) { map_bbox <- attr(карта, 'bb') .extent <- степень (as.numeric (map_bbox [c (2,4,1,3)])) my_map <- растр (.extent, nrow= nrow(карта), ncol = ncol(карта)) rgb_cols <- setNames(as.data.frame(t(col2rgb(карта))), c('красный','зеленый','синий')) красный <- my_map значения (красный) <- rgb_cols[['красный']] зеленый <- my_map значения (зеленый) <- rgb_cols[['зеленый']] синий <- my_map значения (синий) <- rgb_cols[['синий']] стек (красный, зеленый, синий) } # сделать растровый файл из карт Accra_city_map_rast <- ggmap_rast(Accra_city_map) # обрезаем растровый файл Accra_city_map_crop_masked <- маска (Accra_city_map_rast, accra_boundries, inverse=F) # создать геопространственный фрейм данных из растрового файла Accra_city_map_crop_masked_df <- data.frame(rasterToPoints(Accra_city_map_crop_masked)) sysfonts::font_add_google("Notable", "Notable") # это шрифт, который я буду использовать #Они необходимы для рендеринга шрифтов показатьтекст_авто() х11() # создаем карту в ggplot static_map <- ggplot() + geom_point (данные = Accra_city_map_crop_masked_df, аэс (х = х, у = у, col = rgb (layer.1/255, пласт.2/255, пласт.3/255))) + scale_color_identity() + geom_polygon (данные = minraster_ shape_fort, aes (x = длинный, у = широта, группа = группа, заполнить = var1.пред, альфа = var1.пред), размер = 0) + карта_координат() + scale_fill_gradient2 (высокий = «темно-красный», середина = "оранжевый", низкий = "белый", середина = среднее (точки_в_многоугольнике_с_путешествием_время$mintime), name = "Время ходьбы до ближайшего бара в минутах", пределы = с (0, 60), разрывы = с (0, 30, 60), labels = c("0","30 минут", "+1ч"), направляющая = направляющая_цветная полоса ( направление = "горизонтальное", barheight = единица (10, единицы = «мм»), ширина полосы = единица (9, единицы = "дюйм"), рисовать.
ulim = T, title.position = 'сверху', title.hjust = 0,5, метка.hjust = 0,5, legend.location="внизу"))+ scale_alpha_continuous (руководство = "нет", диапазон = c(0.2,.9)) + geom_point (данные = bar_locations_lat_long, aes(x = lon, у = широта), столбец = "#193264FF", размер = 3, форма = 16) + ggthemes::theme_map() + тема (легенда.позиция = "внизу", plot.title = element_markdown(family = "Известный", размер = 60, лицо = "жирный", hюст = 0,5, цвет = "темно-красный", маржа = маржа (t = 20, b = 2)), legend.title = element_markdown (семейство = «Известное», цвет = «темно-красный», размер = 35), легенда.
![]()