Versuchen Sie, GeoSpark (Apache Sedona) in einer Python-Umgebung zu installieren

0. Hintergrund

Beim Umgang mit GeoSpatial-Daten in Python verwende ich häufig GeoPandas für kleine bis mittlere Daten, aber beim Umgang mit großen Daten gibt es Grenzen. .. Dann scheint es, dass die Erweiterungsfunktion von PostgreSQL PostGIS häufig verwendet wird, und wenn es sich um NoSQL handelt, kann der Geometrietyp beispielsweise auch in MongoDB verwendet werden. Ja (Referenz), aber ich habe eine Datenbank gestartet, ein Schema vorbereitet und eine Tabelle oder Sammlung erstellt. Ist ziemlich mühsam und ich interessiere mich für diesen Bereich, aber ich habe ihn noch nicht berührt.

Persönlich verwende ich häufig pyspark für die Datenverarbeitung in großem Maßstab. Kann ich also etwas damit anfangen? Als ich suchte, fand ich etwas namens GeoSpark.

Es scheint, dass sich die Bibliothek noch entwickelt, aber wie Sie sehen können, im Jahr 2020-07-19 (* Datum des Artikelschreibens: 2020-08-08) unter dem Namen Apache Sedona, [Apache Incubator](https: //) Es ist in inkubator.apache.org/) registriert. (Ich bin nicht sehr vertraut damit, aber es scheint, dass wenn es gut anfängt, es ein formelles Apache-Projekt wird. Da das Management auf die Apache-Seite verlagert wird, denke ich, dass die oben genannten Repository-Dokumente auch bald verschoben werden. .)

Es scheint ziemlich interessant zu sein, Daten mit einem Gefühl zu verarbeiten, das Pandas und Geopandas relativ nahe kommt (es kann mit einem geeigneten Gefühl ohne Schemadesign verwendet werden), während ich die Möglichkeit habe, große Datenmengen zu verarbeiten, also habe ich ein wenig damit gespielt. ist.

1. Umweltbau

Umwelt zur Hand: Linux(Ubuntu20.04) (Obwohl weggelassen, können Sie es unter Windows in fast der gleichen Atmosphäre machen.)

Ich habe die Python-Umgebung mit pyenv + miniconda3 (dh conda) vorbereitet, aber ich denke, alles ist in Ordnung.

1-1. Erstellen einer virtuellen Umgebung

Bereiten Sie beispielsweise die folgende YAML-Datei vor:

create_env.yml


name: geospark_demo
channels:
  - conda-forge
  - defaults
dependencies:
  - python==3.7.*
  - pip
  - jupyterlab  # for test
  - pyspark==2.4.*
  - openjdk==8.*
  - pyarrow
  - pandas
  - geopandas
  - folium      # for test
  - matplotlib  # for test
  - descartes   # for test
  - pip:
    - geospark

mit diesem

conda env create -f create_env.yml

#Geben Sie die erstellte virtuelle Umgebung ein
conda activate geospark_demo 

Anschließend können Sie eine virtuelle Conda-Umgebung mit dem Namen "geospark_demo" erstellen. (Informationen zu verschiedenen Anpassungen wie Paketen und Namen virtueller Umgebungen finden Sie beispielsweise unter hier. ) (Ich denke, Sie können das gleiche tun, ohne Conda zu verwenden)

1-2. Einstellungen der Umgebungsvariablen

Im obigen Beispiel (unter Verwendung der virtuellen Umgebung von conda) werden die Einstellungen "PATH" und "JAVA_HOME" ohne Erlaubnis vorgenommen, es müssen jedoch einige zusätzliche Umgebungsvariablen festgelegt werden.

Zunächst bezieht sich Geospark manchmal intern auf "SPARK_HOME". Legen Sie daher den Installationsort von Apache Spark mit der Umgebungsvariablen fest. Wenn Apache Spark wie in diesem Beispiel mit conda usw. installiert wird, kann es außerdem schwierig sein zu wissen, wo sich der Hauptteil von Spark befindet, z. B. hier. How-to-Find-Funken-Installationsverzeichnis)

#Überprüfen Sie den Installationsort von Apache Spark
echo 'sc.getConf.get("spark.home")' | spark-shell

# SPARK_HOME-Einstellungen
export SPARK_HOME=<Der Weg, der oben herauskam>

Stellen Sie so ein. Der Autor sieht aus wie "SPARK_HOME = / home / /. Pyenv / Version / Miniconda3-neueste / envs / geospark_demo / lib / python3.7 / site-packages / pyspark".

Wenn die installierte "Pyarrow" -Version 0.15 oder höher ist, [hier](https://spark.apache.org/docs/2.4.6/sql-pyspark-pandas-with-arrow.html#compatibiliy " -setting-for-pyarrow - 0150-and-spark-23x-24x)

export ARROW_PRE_0_15_IPC_FORMAT=1

Es muss eingestellt werden (Einstellung für die pyspark 2.x-Serie erforderlich). Alternativ können Sie "pyarrow == 0.14. *" Angeben, um es zu installieren.

Es ist mühsam, es von Hand zu machen, also schreibe ich es persönlich in eine Datei und mache es zu "Quelle" oder setze es mit Docker unter Verwendung von "ENV" usw.

2. Funktionsprüfung

Jupyter Notebook für Python und die erforderlichen Testdaten (gespeichert in python / data /) werden auf Official GitHub abgelegt. Verwenden Sie sie also, um sicherzustellen, dass es gut funktioniert. Zum Beispiel

#Wechseln Sie in das Arbeitsverzeichnis
cd /path/to/workdir

#Laden Sie das Notizbuch von github herunter
wget https://raw.githubusercontent.com/DataSystemsLab/GeoSpark/master/python
/GeoSparkCore.ipynb
wget https://raw.githubusercontent.com/DataSystemsLab/GeoSpark/master/python/GeoSparkSQL.ipynb

#Laden Sie mit svn nur bestimmte Verzeichnisse von github herunter
svn export https://github.com/DataSystemsLab/GeoSpark/trunk/python/data/

Sie können es so bekommen. Sie können das Verzeichnis von GitHub mit svn hier oder hier herunterladen. Ich bezog mich auf.

Starten Sie danach jupyter lab oder jupyter notebook und führen Sie ↑ notebook aus. Ich denke, dies ist eine Referenz für die Art der Atmosphäre, die Sie bei der Überprüfung des Betriebs verwenden können.

2-1. Spielen Sie ein wenig

Das Notizbuch und das offizielle Dokument Tutorial, die bei der Funktionsprüfung von ↑ verwendet werden, sind nützlicher, aber es ist eine große Sache. Ich werde selbst ein bisschen spielen.

Testdaten

Verwenden Sie die [National Municipal Boundary Data] von esri Japan (https://www.esrij.com/products/japan-shp/). Wenn Sie am Linkziel auf "Datei herunterladen" klicken und "Zustimmen" aktivieren, können Sie die shp-Datei in Form von "japan_ver821.zip" abrufen. Entpacken Sie sie also in das Arbeitsverzeichnis und legen Sie sie ab.

Lauf

Versuche Folgendes:

  1. Lesen Sie die shp-Datei mit GeoPandas und speichern Sie sie in Form einer Parkettdatei (Hive-Tabelle).
  2. Lesen Sie die in ↑ erstellte Parkettdatei, um einen DataFrame mit dem Geometrietyp zu generieren und zu betreiben.

Unten haben wir die Operation auf jupyterlab bestätigt.

Vorbereitung
#Importieren Sie die erforderlichen Bibliotheken
import os

import folium
import geopandas as gpd
from pyspark.sql import SparkSession

from geospark.register import GeoSparkRegistrator
from geospark.utils import GeoSparkKryoRegistrator, KryoSerializer
from geospark.register import upload_jars

#Funken-Sitzung generieren
upload_jars()
spark = SparkSession.builder.\
        master("local[*]").\
        appName("TestApp").\
        config("spark.serializer", KryoSerializer.getName).\
        config("spark.kryo.registrator", GeoSparkKryoRegistrator.getName) .\
        getOrCreate()
GeoSparkRegistrator.registerAll(spark)
Testdaten lesen
sdf_japan = spark.createDataFrame(
    #Lesen Sie die heruntergeladenen Grenzdaten zu Esri Japan mit Geopandas
    gpd.read_file("japan_ver821/japan_ver821.shp")
)

#Bestätigung
sdf_japan.show(5)
# +-----+------+----------+----+------+----------+--------------------+--------+--------+--------------------+
# |JCODE|   KEN|     SICHO| GUN|SEIREI|SIKUCHOSON|            CITY_ENG|   P_NUM|   H_NUM|            geometry|
# +-----+------+----------+----+------+----------+--------------------+--------+--------+--------------------+
# |01101|Hokkaido|Ishikari Promotion Bureau|null|Sapporo|Chuo-ku|Sapporo-shi, Chuo-ku|235449.0|141734.0|POLYGON ((141.342...|
# |01102|Hokkaido|Ishikari Promotion Bureau|null|Sapporo|Kita Ward|Sapporo-shi, Kita-ku|286112.0|151891.0|POLYGON ((141.408...|
# |01103|Hokkaido|Ishikari Promotion Bureau|null|Sapporo|Higashi Ward|Sapporo-shi, Higa...|261777.0|142078.0|POLYGON ((141.446...|
# |01104|Hokkaido|Ishikari Promotion Bureau|null|Sapporo|Shiraishi Ward|Sapporo-shi, Shir...|212671.0|122062.0|POLYGON ((141.465...|
# |01105|Hokkaido|Ishikari Promotion Bureau|null|Sapporo|Toyohei Ward|Sapporo-shi, Toyo...|222504.0|126579.0|POLYGON ((141.384...|
# +-----+------+----------+----+------+----------+--------------------+--------+--------+--------------------+
# only showing top 5 rows
Speichern Sie DataFrame
#.
sdf_japan.write.save("esri_japan")

#.parquet)
spark.sql("CREATE DATABASE IF NOT EXISTS geo_test") #
sdf_japan.write.saveAsTable("geo_test.esri_japan")  #__Parkettformat) Im Hive-Tabellenformat speichern (die eigentliche Datei ist standardmäßig nicht bissig erforderlich, aber als Tabelle esrijapan beim Datenbankerstellungsdatenbank-Geotest speichern

↑ Sie können Format und Komprimierung mit den Optionen save und saveAsTable ändern, und es scheint, dass Sie auch mit zlib.orc und json.gzip speichern können. (Abgesehen davon, wie glücklich es ist)

Lesen
#Datei lesen
#Geben Sie das Verzeichnis an, in dem die eigentliche Datei gespeichert wird. Geben Sie beim Speichern in einem anderen Format als Parkett das Format in der Ladeoption an.
sdf_from_file = spark.read.load("esri_japan")
sdf_from_file.show(5)
# +-----+------+-----+------+------+----------+--------------+-------+-------+--------------------+
# |JCODE|   KEN|SICHO|   GUN|SEIREI|SIKUCHOSON|      CITY_ENG|  P_NUM|  H_NUM|            geometry|
# +-----+------+-----+------+------+----------+--------------+-------+-------+--------------------+
# |32207|Präfektur Shimane| null|  null|  null|Ezu Stadt|     Gotsu-shi|23664.0|11513.0|MULTIPOLYGON (((1...|
# |32209|Präfektur Shimane| null|  null|  null|Stadt Yunnan|     Unnan-shi|38479.0|13786.0|MULTIPOLYGON (((1...|
# |32343|Präfektur Shimane| null|Nita-Pistole|  null|Oku Izumo Stadt|  Okuizumo-cho|12694.0| 4782.0|POLYGON ((133.078...|
# |32386|Präfektur Shimane| null|Iiishi-Pistole|  null|Iinan Stadt|     Iinan-cho| 4898.0| 2072.0|POLYGON ((132.678...|
# |32441|Präfektur Shimane| null|Echi-Pistole|  null|Kawamoto Stadt|Kawamoto-machi| 3317.0| 1672.0|POLYGON ((132.487...|
# +-----+------+-----+------+------+----------+--------------+-------+-------+--------------------+
# only showing top 5 rows

#Tabelle gelesen
sdf_from_table = spark.table("geo_test.esri_japan") #Geben Sie den zu lesenden Tabellennamen an
sdf_from_table.show(5)
# +-----+------+-----+------+------+----------+--------------+-------+-------+--------------------+
# |JCODE|   KEN|SICHO|   GUN|SEIREI|SIKUCHOSON|      CITY_ENG|  P_NUM|  H_NUM|            geometry|
# +-----+------+-----+------+------+----------+--------------+-------+-------+--------------------+
# |32207|Präfektur Shimane| null|  null|  null|Ezu Stadt|     Gotsu-shi|23664.0|11513.0|MULTIPOLYGON (((1...|
# |32209|Präfektur Shimane| null|  null|  null|Stadt Yunnan|     Unnan-shi|38479.0|13786.0|MULTIPOLYGON (((1...|
# |32343|Präfektur Shimane| null|Nita-Pistole|  null|Oku Izumo Stadt|  Okuizumo-cho|12694.0| 4782.0|POLYGON ((133.078...|
# |32386|Präfektur Shimane| null|Iiishi-Pistole|  null|Iinan Stadt|     Iinan-cho| 4898.0| 2072.0|POLYGON ((132.678...|
# |32441|Präfektur Shimane| null|Echi-Pistole|  null|Kawamoto Stadt|Kawamoto-machi| 3317.0| 1672.0|POLYGON ((132.487...|
# +-----+------+-----+------+------+----------+--------------+-------+-------+--------------------+
# only showing top 5 rows

Es wurde bestätigt, dass es als einfache Datei oder in einem Tabellenformat gespeichert und gelesen werden kann. Außerdem war ich der Meinung, dass die Konvertierung von Geopandas in DataFrame von pyspark langsam war, und dachte daher, dass es besser ist, die Konvertierung von Geopandas <-> pyspark zu minimieren.

※dtypes

sdf = sdf_from_file #Im Folgenden wird der aus der Datei gelesene als sdf bezeichnet.

display(sdf.dtypes)
# [('JCODE', 'string'),
#  ('KEN', 'string'),
#  ('SICHO', 'string'),
#  ('GUN', 'string'),
#  ('SEIREI', 'string'),
#  ('SIKUCHOSON', 'string'),
#  ('CITY_ENG', 'string'),
#  ('P_NUM', 'double'),
#  ('H_NUM', 'double'),
#  ('geometry', 'udt')]

Es scheint, dass "Geometrie" als ein "udt" -Typ behandelt wird, der in der Geospark-Bibliothek definiert ist. (Wenn Sie also versuchen, eine Datei oder Tabelle ohne Geospark-Einstellungen zu lesen, wird eine Fehlermeldung angezeigt.)

Führen Sie einfache Abfragen usw. aus und bestätigen Sie sie.

Siehe insbesondere aus der offiziellen Dokumentation:

#Registrieren Sie den DataFrame als TEMP VIEW, damit Sie spark sql verwenden können
sdf.createOrReplaceTempView('esri_japan')

#Bestätigen Sie die Anzahl der Originaldaten
sdf.count() # 1907

#Längengrad: 135-140, Breitengrad: 35-Filter im Bereich von 40
sdf_filtered = spark.sql("""
    SELECT * FROM esri_japan
        WHERE ST_Contains(ST_PolygonFromEnvelope(135., 35., 140., 40.), esri_japan.geometry)
""")

sdf_filtered.show(5)
# +-----+------+-----+--------+------+----------+----------------+-------+------+--------------------+
# |JCODE|   KEN|SICHO|     GUN|SEIREI|SIKUCHOSON|        CITY_ENG|  P_NUM| H_NUM|            geometry|
# +-----+------+-----+--------+------+----------+----------------+-------+------+--------------------+
# |06401|Präfektur Yamagata| null|Nishioki-Pistole|  null|Oguni Stadt|     Oguni-machi| 7612.0|3076.0|POLYGON ((139.911...|
# |06426|Präfektur Yamagata| null|Higashidagawa-Pistole|  null|Mikawa Town|    Mikawa-machi| 7400.0|2387.0|POLYGON ((139.842...|
# |07364|Präfektur Fukushima| null|Minami Aizu-Pistole|  null|Hiedagi Village|  Hinoemata-mura|  557.0| 202.0|POLYGON ((139.259...|
# |07367|Präfektur Fukushima| null|Minami Aizu-Pistole|  null|Tadami Stadt|    Tadami-machi| 4366.0|1906.0|POLYGON ((139.366...|
# |07368|Präfektur Fukushima| null|Minami Aizu-Pistole|  null|Minami Aizu Stadt|Minamiaizu-machi|15679.0|6707.0|POLYGON ((139.530...|
# +-----+------+-----+--------+------+----------+----------------+-------+------+--------------------+
# only showing top 5 rows

sdf_filtered.count() # 573 <- original: 1907

Die Anzahl der DataFrames hat sich ebenfalls verringert (1907-> 573), und es scheint, dass der Filter ordnungsgemäß abgeschlossen wurde, aber ich werde ihn visualisieren und für alle Fälle überprüfen.

# matplotlib
gdf_filtered = gpd.GeoDataFrame( #In Geopandas konvertieren
    sdf_filtered.toPandas(),
    geometry='geometry'
)
gdf_filtered.plot()

(Handlungsergebnis) image.png

Übrigens, wenn Sie das gesamte Original japan_ver821.shp zeichnen

gpd.read_file('japan_ver821/japan_ver821.shp') \
    .plot()

image.png

Es scheint also, dass die Filterung richtig durchgeführt wird.

Sie können auch folium für die interaktive Visualisierung verwenden.

m = folium.Map(
    location=(37.5, 137.5), #Beachten Sie, dass die Reihenfolge Breiten- und Längengrad ist.
    zoom_start=7,
    control_scale=True,
)
m.add_child(folium.LatLngPopup()) #Klicken Sie hier, um den Breiten- und Längengrad in einem Popup zu überprüfen

#Konvertieren Sie den gefilterten DataFrame in GeoJSON und übergeben Sie ihn an Folium
m.add_child(
    folium.GeoJson(gdf_filtered.to_json())
)

folium.LayerControl().add_to(m) #LayerControl hinzugefügt
m.save('df_filterd.html') #sparen
m #Wird auf dem Jupiter angezeigt

image.png

Ich konnte es auch auf dem Folium visualisieren.

3. Verschiedene Gefühle

――Ich war diesmal nicht sehr glücklich, weil ich nur eine sehr einfache Abfrage zu kleinen Daten durchgeführt habe, aber es war interessant, auf Spark eine PostGIS-ähnliche Atmosphäre schaffen zu können.

Recommended Posts

Versuchen Sie, GeoSpark (Apache Sedona) in einer Python-Umgebung zu installieren
Versuchen Sie gRPC in Python
virtuelle Umgebung in Python
Probieren Sie 9 Slices in Python aus
Entwicklungsumgebung in Python
Behandeln Sie Umgebungsvariablen in Python
Versuchen Sie LINE Notify mit Python
Lassen Sie uns Yuma in Python 3 implementieren
Berühren Sie Apache Beam mit Python
Versuchen Sie, Python in der mit pipenv erstellten Django-Umgebung auszuführen
Installieren Sie Scrapy in einer Python Anaconda-Umgebung
Versuchen Sie es mit LevelDB mit Python (plyvel)
Versuchen wir es mit Fizz Buzz mit Python
Versuchen Sie, Trace in Python zu berechnen
Versuchen Sie den Zugriff auf das SPS-Register in Python
Installieren Sie Tensorflow in einer anaconda + python3.5-Umgebung
Versuchen Sie es mit LeapMotion mit Python
Von der Installation von Ansible bis zum Erstellen einer Python-Umgebung in der virtuellen Umgebung von Vagrant
Erstellen und testen Sie mit Docker in wenigen Minuten eine OpenCV- und Python-Umgebung
Versuchen Sie, sich mit Python bei qiita anzumelden
Versuchen Sie es mit der Wunderlist-API in Python
Methode zum Erstellen einer Python-Umgebung in Xcode 6
Verwenden von venv in der Windows + Docker-Umgebung [Python]
Versuchen Sie, ein SYN-Paket in Python zu senden
Versuchen Sie, eine einfache Animation in Python zu zeichnen
Versuchen Sie Python
Das Ergebnis der Installation von Python auf Anaconda
Verweisen auf Umgebungsvariablen in Python in Blender
Probieren Sie schnell die Microsoft Face API in Python aus
[AWS] Hinweise zur Problemvermeidung bei der Installation von awscli und boto3 in einer Python 2.7-Umgebung
Verfahren zur Erstellung der Umgebung: Ubuntu + Apache2 + Python + Pyramid
Versuchen Sie, Ihr Tagebuch mit Python zu durchsuchen
Probieren Sie eine funktionale Programmierpipe in Python aus
Versuchen Sie etwas wie Python für-else in Ruby
Verstümmelte Python-Zeichen in der Windows + Git Bash-Umgebung
Einführung von sip-4.14 in der Python3.2.2-Umgebung mit MacOS 10.7.4
Erstellen Sie in 1 Minute eine Vim + Python-Testumgebung
Erste Schritte zum Testen von Google CloudVision in Python
Versuchen Sie, Oni Mai Tsuji Miserable mit Python zu implementieren
Berechnen wir das statistische Problem mit Python
3,14 π Tag, versuchen Sie also, in Python auszugeben
Versuchen Sie automatisch, Enum in Python 3.6 automatisch zu bewerten
Versuchen Sie, zwei Stapel in Python auf einem Array zu implementieren
Erstellen einer Umgebung, die Python mit Eclipse verwendet
Installieren Sie das Python-Paket in einer persönlichen Umgebung unter Ubuntu
Wenn ich matplotlib in Python versuche, heißt es'cairo.Context '.
Versuchen Sie es mit der BitFlyer Ligntning API in Python
Erstellen Sie eine virtuelle Umgebung mit conda in Python
Installieren Sie Python 3.5.1 + numpy + scipy + α in einer Windows-Umgebung
Vorsichtsmaßnahmen bei der Installation von Paketen in der Conda-Umgebung
Verwenden Sie Python in Ihrer Umgebung von Win Automation
Versuchen Sie, RPN mit Python zu berechnen (für Anfänger)
[Umgebungskonstruktion] Abhängigkeitsanalyse mit CaboCha mit Python 2.7
Versuchen Sie, mit Mongo in Python auf dem Mac zu arbeiten
Denken Sie daran, eine Python 3-Umgebung in einer Mac-Umgebung zu erstellen