В одной прошлых публикации про "где бы вы точно не жили и не остановились даже на время, если бы знали и выбирали на основе фактов" получил массу полезных коментариев от читателей. Среди них просили "кроме плохих районов было бы интересно увидеть и хорошие".
Честно скажу, что определить какие хорошие непросто. Ведь у каждого свое понятие о том что такое хорошо и нужен доступ к данным, которого у нас нет. Поэтому давайте посмотрим где жить "неплохо". Не жить рядом с тем, что влияет на качество воздуха, уровень шума, ежедневное memento mori, близость к промышленности, безопасность. Найдем группы домов в Москве в пределах МКАД, отдаленные на 150м от перечисленных факторов. Если живете в Москве, то удивитесь - вашего дома скорее всего не будет на этой карте
Про техническую часть, где скачать данные и как загрузить и обработать я недавно рассказывал на Хабре. В этот раз опустим основные технические подробности и не буду повторяться: посмотрим на данные на карте. Ведь карты не врут??
Что учитывается, а что нет
В основе моя субъективная модель, которая отговаривает меня жить в определенных местах. Главный её фильтр - расстояние по прямой от жилья на котором учитываются негативные факторы. И в ней не учитываются автомобильные пробки и транспортная доступность, количество солнечных дней в году, рейтинги поликлиник, наличие школ и садиков, недоступна информация которой сейчас нет и возможно и не будет на OpenStreetMap.
Модель - это всего лишь грубое приближение реальности, тем более что данные о материалах дома и реальное качество строительства не учитываются. Как и года постройки здания, название типового проекта. Не учитывается слышимость из соседних квартир и с улицы. Так же как нерасчитывается затухание шума на деревьях/ на шумозащитном экране у трассы( детальная информация о высоте деревьев и плотности их размещения на OpenStreetMap отсутствует), какие соседи из каких квартир уходят в запой и поколачивают свою семью, где есть агрессивные к другим людям индивиды во дворах и парках, качество водоснабжения и можно ли безопасно пить воду из-под крана. Живут ли в доме тараканы. Работает ли вентиляционная труба или ее замуровал сосед сверху расширив за ее счет объем свей жилплощади. Как часто ломает лифт сосед перегружая его до потолка стройматериалами. Есть ли хулиганы жгущие пластиковые кнопки в лифте и побелку в подъезде, изрисовывают ли стены дома. И многое другое не менее важное для комфорта остается вне модели.
Но, даже не смотря на такое упрощение результаты работы модели даже на неполных исходных данных лучше, чем полное неведение об окрестностях жилья или только позитивная информация о районе. Рядом с жильем, ближе чем в 150м не хотел бы видеть, нюхать и слышать влияющее на:
качество воздуха: Станция перевалки мусора, Свалка, Террикон, Коровник, Свинарник, Жидкий навоз, Очистка сточных вод, Дымовая труба, Крематорий
уровень шума: Стройка, Железнодорожные пути, Взлётно-посадочная полоса, Вертолётная площадка. Автомобильные дороги регионального значения, дороги с более чем 2мя полосами движения, Автомобильные дороги федерального значения, Стадион
индустриальное настроение: Промышленные площади, Подстанции, Генератор, ТЭЦ, Карьер
скорбь: Кладбище, Морг, Место для проведения похоронной церемонии
опасность: Контейнер, содержащий жидкости или сжатые газы, Магазин пиротехники, Опасность, Территория подвержена стихийным бедствиям, Район или дорога, подверженная затоплению
комары: Заболоченые участки
Те жилые здания, что не разметила модель в черте МКАД, будем считать "неплохими" Как пошутили в коментарии "Как говорят врачи, здоровых нет, есть недообследованные.". Вот и посмотрим на те группы домов, которые стоит изучить подробнее, погулять по району и поискать дополнительную информацию.
Как будем группировать дома? Избегаем шума квантования
Поскольку зданий не так много и они находятся в анклавах мест подверженых негативным факторам, то усреднение по гексагональной решетке иерархического индекса H3 не сработает, я проверял. Воспользуемся функцией ST_ConcaveHull для создания групп домов на основе встроенного в PostGIS алгоритма кластиризации.
ST_ClusterDBSCAN - это функция для кластеризации географических данных, основанная на алгоритме DBSCAN (Density-Based Spatial Clustering of Applications with Noise). DBSCAN - это алгоритм кластеризации, который может выявлять кластеры точек на основе их плотности в пространстве, а также определять выбросы (шум - группы классифицированные со значением NULL). По факту это оконная функция, размечает каждую строчку в результате запроса номером вычисленного кластера
Результат выполнения функции ST_ConcaveHull на данных функции ST_ClusterDBSCAN будет содержать оболочку, которая лучше соответствует форме исходных геометрических объектов с учетом указанной вторым параметром степени вогнутости. ST_ConcaveHull это агрегатная функция - работает на группе объектов, создавая для них оболочку. Можно думать о вогнутой оболочке как о «упаковке в термоусадочную пленку» набора точек. Это отличается от выпуклой оболочки, которая больше похожа на обертывание кончиков резинкой. Вогнутая оболочка обычно имеет меньшую площадь и представляет собой более естественную границу для входных точек.
create table cluster as
select ST_ConcaveHull(ST_Collect(array_agg(geom)),0.3,false) geom
from
(
select geom, ST_ClusterDBSCAN(st_centroid(geom), eps := .0025, minpoints := 3) over () house_group
from notbad_house
) cluster
where house_group is not null
group by house_group;
Параметр eps := .0025,
подобран опытным путем, учитывая плотность реальных данных по интересующим нас группам зданий. В группу объединяются от 3х домов minpoints := 3.
Степени вогнутости 0.3 ST_ConcaveHull так же подобран по данным.
ST_ConcaveHull может "сходить с ума" на некоторых группах домов.
ERROR: lwgeom_intersection_prec: GEOS Error: TopologyException: Input geom 0 is invalid: Self-intersection at 37.484006900000004 55.798911600000004
CONTEXT: PL/pgSQL function st_concavehull(geometry,double precision,boolean) line 103 at assignment
ERROR: lwgeom_intersection_prec: GEOS Error: TopologyException: Input geom 0 is invalid: Self-intersection at 37.594739199999999 55.637465300000002
CONTEXT: PL/pgSQL function st_concavehull(geometry,double precision,boolean) line 103 at assignment
ERROR: lwgeom_intersection_prec: GEOS Error: TopologyException: Input geom 0 is invalid: Self-intersection at 37.857355362616403 55.687783421550613
CONTEXT: PL/pgSQL function st_concavehull(geometry,double precision,boolean) line 103 at assignment
И эти группы пришлось вставлять в таблицу вручную, с другими параметрами:
insert into cluster(geom) select ST_ConcaveHull(ST_Collect(array_agg(geom)),1,false) geom from (select * from pre_cluster where house_group=54) g;
insert into cluster(geom) select ST_ConcaveHull(ST_Collect(array_agg(geom)),1,false) geom from (select * from pre_cluster where house_group=297) g;
insert into cluster(geom) select ST_ConcaveHull(ST_Collect(array_agg(geom)),1,false) geom from (select * from pre_cluster where house_group=216) g;
Сохраню результат кластеризации в GeoJSON файл и загружу его в gist на GitHub.
\copy (select json_build_object('type', 'FeatureCollection','features', json_agg(json_build_object('type', 'Feature','geometry', st_AsGeoJSON(geom)::json))) FROM cluster) to 'maybecomfortable_moscow.json.geojson';
Результат
Кластеризация геоданных показывает что в Серебряном Бору и Покровских Холмах жить "не плохо" и в этом я согласен с моей моделью. Так же в выборку попали дома в спальных районах в черте МКАД. Полную выгрузку, с возможностью масштабирования карты можете посмотреть здесь или загрузить .
UPD: Все эти факторы, с возможностью настройки расстояний доступны на интерактивной карте https://igor-suhorukov.github.io так же как и транспортная доступность и близость жилья к магазинам, детсадам, школам, университетам.