Как извлечь и визуализировать данные из файла OSM в Python

Я загрузил файл OpenStreetMap на свой рабочий стол и использовал свой OSM-файл в блокноте jupyter.

Мой код:

import xml.etree.cElementTree as ET
osm_file = "ahmedabad_india.osm"

for event, elem in ET.iterparse(osm_file, events=("start",)):
     print(elem)
     # prints the Element 'osm' at 0x03A7DC08>
     #<Element 'bounds' at 0x03A7DDA0>
     #<Element 'node' at 0x03A7DE90>
     #<Element 'tag' at 0x03A7DF08> and so on ...

Я хотел бы увидеть содержимое всех tags т.е. <'node', 'id', 'name', ...> и так далее.

Я пытался с помощью elem тег, но ничего не печатает.

Может ли кто-нибудь помочь мне выяснить, кто получить содержимое тегов, таких как узел, пути и т. Д.

2 ответа

Вы можете извлечь все данные из .osm файл через PyOsmium (быстрая и гибкая библиотека C++ для работы с данными OpenStreetMap) и затем обрабатывает его с помощью Pandas:

Код:

import osmium as osm
import pandas as pd

class OSMHandler(osm.SimpleHandler):
    def __init__(self):
        osm.SimpleHandler.__init__(self)
        self.osm_data = []

    def tag_inventory(self, elem, elem_type):
        for tag in elem.tags:
            self.osm_data.append([elem_type, 
                                   elem.id, 
                                   elem.version,
                                   elem.visible,
                                   pd.Timestamp(elem.timestamp),
                                   elem.uid,
                                   elem.user,
                                   elem.changeset,
                                   len(elem.tags),
                                   tag.k, 
                                   tag.v])

    def node(self, n):
        self.tag_inventory(n, "node")

    def way(self, w):
        self.tag_inventory(w, "way")

    def relation(self, r):
        self.tag_inventory(r, "relation")


osmhandler = OSMHandler()
# scan the input file and fills the handler list accordingly
osmhandler.apply_file("muenchen.osm")

# transform the list into a pandas DataFrame
data_colnames = ['type', 'id', 'version', 'visible', 'ts', 'uid',
                 'user', 'chgset', 'ntags', 'tagkey', 'tagvalue']
df_osm = pd.DataFrame(osmhandler.osm_data, columns=data_colnames)
df_osm = tag_genome.sort_values(by=['type', 'id', 'ts'])

Выход:

введите описание изображения здесь

Вот полное объяснение загрузки функций из OSM и их визуализации на Python. Я не рекомендую писать Python для чтения файлов, потому что существует множество простых в использовании программ (например, GDAL), которые сделают это за вас.

Вам не нужно индивидуально обрабатывать узлы, пути и связи, чтобы использовать данные OpenStreetMap.

1. Выберите объект из OpenStreetMap.

Все функции помечены метаданными, такими как имя ( name=Starbucks), тип здания () или часы работы ( opening_hours=Mo-Fr 08:00-12:00,13:00-17:30) . Например, римский Колизей помечен так:

Чтобы загрузить подмножество функций OSM, сначала определите список ключей тегов и (необязательно) значений для фильтрации. Например, все рестораны с названиями будут отфильтрованы поamenity=restaurantиname=*.

Полезными ресурсами для изучения тегов, подходящих для вашего случая использования, являются веб-сайт OSM TagInfo и OSM Wiki.

В этом примере мы загрузим и визуализируемbuilding=university.

2. Загрузите соответствующие функции

Существует три основных способа загрузки данных из OpenStreetMap, каждый из которых имеет свои плюсы и минусы.

а. Загрузка функций из OpenStreetMap с использованием API

Этот метод наименее ресурсоемкий (не требуется сервер), не требует установки GDAL и может быть реализован на всей планете. Требуется бесплатный ключ API для стороннего API извлечения OSM .

  1. curl/wgetдо конечной точки и укажите функции для загрузки
      curl --get 'https://osm.buntinglabs.com/v1/osm/extract' \
     --data "tags=building=university" \
     --data "api_key=YOUR_API_KEY" \
     -o university_buildings.geojson

При этом загружаются все функции на планете, удовлетворяющие вашемуtags=фильтровать как GeoJSON дляuniversity_buildings.geojson.

Вам не нужно конвертировать файлы разных форматов. Если вам нужен небольшой отрывок, вы можете передатьbbox=параметр и создайте ограничивающую рамку в bboxfinder .

б. Загрузите регион как и вручную извлеките его локально.

Этот метод можно выполнить на 100% локально, но для этого потребуется использовать небольшой регион (максимум ~10 районов) и .

  1. Увеличьте масштаб и загрузите файл из OpenStreetMap Extract . Это будет большой файл, поскольку он в формате XML.

  2. Файл фильтра для функций, которые вы хотите сохранить. См. ниже (c.), например, сosmium.

  3. Используйте ogr2ogr для преобразования в . Этот шаг сложен, поскольку GDAL хранит точки, линии и полигоны как отдельные полигоны. В этом уроке показано, как конвертировать.osmк , или см., например, ниже (c.).

в. Скачать планету как.osm.pbfи извлечь на сервер

Этот метод ресурсоемок и требует более 100 ГБ дискового пространства, ~2 дня обработки и более 64 ГБ оперативной памяти. Однако он позволяет вам обыскивать всю планету. Требуется установить GDALустановка GDAL .

  1. Торрентplanet.osm.pbfили загрузите выдержку региона из Geofabrik Extracts.

  2. Отфильтруйте целевые функции, используяosmium-tags-filter:

      osmium tags-filter -o university_buildings.osm.pbf planet.osm.pbf nwr/building=university
  1. Преобразуйтеuniversity_buildings.osm.pbfфайл в.geojson

В зависимости от размера выходного файла он может быть слишком большим для GeoJSON (текстового), и вместо этого вам следует использовать GeoPackage (.gpkg) или FlatGeobuf (.fgb).

      ogr2ogr -f GeoJSON output_points.json input.osm.pbf points
ogr2ogr -f GeoJSON output_lines.json input.osm.pbf lines
# ... continue for multilinestrings, multipolygons and other_relations

Тогда присоединяйтесь кoutput_points.json,output_lines.jsonи т. д. сogrmerge.py.

3. Визуализация функций

После загрузки рекомендуется загрузить данные в geopandas — расширение pandas со встроенной пространственной поддержкой. Это самый простой способ визуализации пространственных данных в Python.

Мы загрузим данные вGeoDataFrameа затем постройте его с помощью matplotlib :

      import matplotlib.pyplot as plt
import geopandas as gpd

# Read our downloaded file from earlier
gdf = gpd.read_file('university_buildings.geojson', driver='GeoJSON')

# Plot and individually add each building name
ax = gdf.plot()
for x, y, label in zip(gdf.centroid.x, gdf.centroid.y, gdf.name):
    ax.annotate(label, xy=(x, y), xytext=(3, 3), textcoords="offset points")

plt.show()

Это дает такой результат:

Другие вопросы по тегам