Привет, Хабр! Я историк, работаю над историко-географическими базами данных в российском генеалогическом сервисе familio.org. В этой статье расскажу, как мы сделали карту исторических промыслов Костромской губернии для фестиваля семейной истории в Кинешме. Надеюсь, что материал будет интересен не только любителям исторической географии, но и тем, кто интересуется визуализацией своих данных на карте.
![Карту можно посмотреть (и при желании скачать в формате kml) на Google картах. Карту можно посмотреть (и при желании скачать в формате kml) на Google картах.](https://habrastorage.org/getpro/habr/upload_files/fdd/7ad/b5d/fdd7adb5d7b3d59f5663901c59bf34ee.png)
Наша команда собирает, обрабатывает и публикует в электронном виде исторические данные, которые полезны для генеалогического поиска. Особое место среди них занимают списки населённых мест (прим. «населённое место» — это то же самое, что и «населённый пункт», но до 1920-х годов преимущественно использовался первый термин). Эти списки в большинстве случаев издавались в губерниях, из-за чего у них значительно варьируется формат и содержимое.
К примеру, есть замечательный список населённых мест по Витебской губернии 1906 года, в котором для каждого населённого пункта указано к какому церковному приходу тот относился — а это ключевая информация для генеалогического поиска, т.к. в церквях велись все записи о рождениях, браках и смертях.
Во многих случаях списки населённых мест составлялись по результатам земских социально-экономических исследований (прим. земство — дореволюционный орган местного самоуправления). К одному из таких изданий относится и список населённых мест Костромской губернии 1907 года, в нём содержатся сведения о местных промыслах. Оригинал справочника, вернее, его скан, с которого начинается вся работа, выглядит следующим образом.
![](https://habrastorage.org/getpro/habr/upload_files/e5f/b3b/903/e5fb3b90332b9583f64fccc19f970639.png)
Этот текст из справочника мы распознаём в формате таблицы, приводим к единому формату нашей базы данных, а потом связываем с существующей базой населённых пунктов, в основу которой положены современные реестры ОКТМО и АГКГН (они покрывают примерно до двух третей от общего количества исторически существовавших на территории России населённых пунктов в течение последних двух-трёх веков). Связывание записей с н/п — процедура довольно трудоёмкая, т.к. многие населённые пункты, упоминаемые в дореволюционных документах, ныне уже не существуют, но используя данные о расстояниях (прим. одна из наиболее часто встречающихся характеристик в подобных изданиях — расстояние от деревни до города, волостного правления и т.д.) большую часть подобных лакун удаётся реконструировать и нанести отсутствующие метки на карту. Этим у нас занимаются специально подготовленные люди, которые умеют работать со старыми картами, например, с ресурсом etomesto.ru. Сильно помогают и деревни с уникальными названиями, например, Выхино в Российской империи было только одно.
![В результате этого кропотливого труда у нас получается набор таблиц с деревнями, их характеристиками и связями с вышестоящими уровнями (волостями и уездами), а также с населёнными пунктами из базы. В результате этого кропотливого труда у нас получается набор таблиц с деревнями, их характеристиками и связями с вышестоящими уровнями (волостями и уездами), а также с населёнными пунктами из базы.](https://habrastorage.org/getpro/habr/upload_files/842/674/aec/842674aec51a2ed4fc219e300157ec20.png)
Теперь у нас есть данные, с которыми можно работать в табличных, текстовых и ГИС-редакторах. Для начала просто устроим перекрёстную проверку и посмотрим насколько хорошо были привязаны деревни к базе населённых пунктов. Для этого открываем QGIS, добавляем osm-подложку, и загружаем через CTRL+SHIFT+T единую таблицу с координатами и вышестоящими уровнями. Потом кликаем правой мышкой на слой и отрываем Properties этого слоя, где указываем Symbology как Categorized, где последовательно выбираем разные атрибуты (уезд, волость, дистанцию и прочее).
![Так выглядит карта, если метки деревень автоматически раскрасить в цвета уездов. Если какая-то метка «улетает» далеко от своих цветовых собратьев, то, скорее всего, эта связь установлена ошибочно и нуждается в ревизии в базе данных. Так выглядит карта, если метки деревень автоматически раскрасить в цвета уездов. Если какая-то метка «улетает» далеко от своих цветовых собратьев, то, скорее всего, эта связь установлена ошибочно и нуждается в ревизии в базе данных.](https://habrastorage.org/getpro/habr/upload_files/5f1/da9/219/5f1da92198972cae0392e73c142d3382.jpg)
Теперь нужно стандартизировать промыслы. Костромская губерния наряду с соседней Ярославской была одной из самых развитых губерний в плане промыслов, огромное количество местных крестьян уходило на заработки в столицу и другие города. Сводная таблица показывает, что уникальных значений в колонке с промыслами под 2000 объектов, причем во многих случаях сокращения неодинаковые и зачастую в ячейке перечислено несколько промыслов таким образом. Нам, конечно, нужен только самый популярный, но терять информацию жалко, поэтому надо развернуть все промыслы построчно. Делается это следующим образом: заменяем запятую с пробелом на разделитель "|", притягиваем через такой же разделитель уникальный идентификатор записи (у нас в этом качестве используется uuid-4), а после в текстовом редакторе при помощи регулярных выражений заменяем все разделители на перенос строки. Далее в экселе в каждой строке формулой дублируем идентификаторы до следующего встречного идентификатора.
![Видно, что в третьей строке разделителем служил просто пробел, но поменять все пробелы на разделители нельзя, поскольку название многих промыслов содержит пробел. Видно, что в третьей строке разделителем служил просто пробел, но поменять все пробелы на разделители нельзя, поскольку название многих промыслов содержит пробел.](https://habrastorage.org/getpro/habr/upload_files/d7c/938/732/d7c938732e7c2c86748c95594f5ed8bb.png)
Теперь предстоит унифицировать эти значения, и когда они все развёрнуты построчно, то сделать это уже гораздо проще. Сортируем по алфавиту получившиеся уникальные значения и приводим к единому значению («пл.», «плот.», «плотн.» → «плотники»). Перед сортировкой не забываем сохранить оригинальный порядок в отдельную табличку, так как нам интересен именно самый распространенный промысел, т. е. первый в списке для каждой деревни. В результате всех этих операций получается набор в виде 11 607 населённых пунктов с координатами, на которые приходится 111 доминирующих там промыслов: от ассенизаторов до штукатуров.
![Деревни Костромской губернии, раскрашенные в цвет самого распространенного в тех местах промысла Деревни Костромской губернии, раскрашенные в цвет самого распространенного в тех местах промысла](https://habrastorage.org/getpro/habr/upload_files/3d9/0cc/fd2/3d90ccfd2e0c3b0e87dec811d4873140.png)
Карта уже становится достаточно интересной: видны большие кластеры фабричных рабочих на юго-западе (современная Ивановская область), маляров в окрестностях Галича, а также портных около Неи. Но для удобства восприятия хорошо бы как-то закрасить и объединить промежуточные области. Для этого отлично подходит диаграмма Вороного, её можно найти в QGIS в разделе Vector → Geometry Tools → Voronoi Polygons. Получившейся диаграмме присваиваем атрибуты деревень через Vector → Data Management Tools → Join Attributes by Location.
![](https://habrastorage.org/getpro/habr/upload_files/5db/8cc/66a/5db8cc66af31342f9ec4c42747b3b974.png)
Обрезаем получившийся результат через Vector → Geoprocessing Tools → Intersection по примерной границе Костромской губернии.
![](https://habrastorage.org/getpro/habr/upload_files/8bf/3b9/ca9/8bf3b9ca971dcf4d9340163892ff931a.png)
А после объединяем отдельные полигоны через Vector → Geoprocessing Tools → Dissolve, указав в качестве критерия поле с промыслом. При использовании диаграммы Вороного часто получаются довольно «рваные» границы с резкими углами, поэтому мы генерируем гексагональную сетку через Vector → Research Tools → Create Grid с шагом в километр, а потом присваиваем ей атрибуты с диаграммы Вороного через Vector → Data Management Tools → Join Attributes by Location.
![](https://habrastorage.org/getpro/habr/upload_files/49d/225/9ae/49d2259ae0f807d3b3eaf9d1f5a7a591.png)
Получившуюся карту уже вполне можно показывать, но этот момент до фестиваля остаётся всего-ничего времени, а хочется как-нибудь быстро сделать доступную онлайн карту, чтобы слушатели могли прямо во время презентации её посмотреть и приблизить интересующие их места. Вариантов тут не очень много, основных два: Google карты и Яндекс карты. Яндекс, к сожалению, отпадает сразу, т.к. такие большие объекты импортировать нельзя.
![](https://habrastorage.org/getpro/habr/upload_files/c44/7e6/383/c447e63831027f06f71f040553cdce78.png)
Остаются Google карты, в которых также выяснятся, что импортировать kml файл размером больше 5 МБ нельзя.
![](https://habrastorage.org/getpro/habr/upload_files/66b/dda/b44/66bddab444aedf0fae83f8c040653ba0.png)
А у нас как раз получилась карта немногим больше 5 МБ, обидно! Начинаем смотреть начинку kml файла в поисках того, что можно пустить под нож и обнаруживаем излишне длинные координаты в 12–13 символов после запятой (в нашем случае 5 символов после запятой хватит с запасом). Возвращаемся в QGIS и экспортируем kml ещё раз с ограничением символов после запятой. Получается 3 МБ, файл успешно импортируется, и после небольшой раскраски карта наконец готова!
![Карту можно посмотреть (и при желании скачать в формате kml) по ссылке. Карту можно посмотреть (и при желании скачать в формате kml) по ссылке.](https://habrastorage.org/getpro/habr/upload_files/d0f/472/6d3/d0f4726d3cb1ed26134346ca9d964473.png)
Теперь проделанной работой можно любоваться. Некоторые избранные места на карте:
![Большое «море» плотников в Галичском уезде и окрестностях. Уходили в основном на заработок в Санкт-Петербург, где заработали себе хорошую репутацию. Большое «море» плотников в Галичском уезде и окрестностях. Уходили в основном на заработок в Санкт-Петербург, где заработали себе хорошую репутацию.](https://habrastorage.org/getpro/habr/upload_files/cba/22d/31b/cba22d31b50e957ea5f828f0b5fe57e7.png)
![Профессиональные нищие в деревеньке Ивановской области. И такое бывало. Профессиональные нищие в деревеньке Ивановской области. И такое бывало.](https://habrastorage.org/getpro/habr/upload_files/ee9/71d/8dd/ee971d8dd334593b633023b2d3501f9e.png)
![Серпозубы (пришлось гуглить, кто такие) в окрестностях Сусанино — путешествуют и предлагают заточить сельхозинвентарь Серпозубы (пришлось гуглить, кто такие) в окрестностях Сусанино — путешествуют и предлагают заточить сельхозинвентарь](https://habrastorage.org/getpro/habr/upload_files/df9/0f1/b3b/df90f1b3b7a655ea34e4b4c8b98c4c21.png)
![Ассенизаторы в окрестностях Костромы (интересно, сохранила ли местная история рассказы о славном промысловом прошлом). Ассенизаторы в окрестностях Костромы (интересно, сохранила ли местная история рассказы о славном промысловом прошлом).](https://habrastorage.org/getpro/habr/upload_files/a3f/41f/a3e/a3f41fa3ec89d48a656306bf82bf5036.png)
![Кошатный промысел в селе Холм (заготавливают кошачий мех для городских модниц). Кошатный промысел в селе Холм (заготавливают кошачий мех для городских модниц).](https://habrastorage.org/getpro/habr/upload_files/22d/564/99e/22d56499efd4471d6bcdb02bf0d12b9b.png)
![Профессиональные изготовители кренделей из деревни Рылово. Профессиональные изготовители кренделей из деревни Рылово.](https://habrastorage.org/getpro/habr/upload_files/9d4/3cd/6d2/9d43cd6d27edbf8c31dbffab499c9a63.png)
Думаю, что читатель, дошедший до этого места, и сам найдёт на карте интересные места.
Спасибо за чтение!