[PYTHON] Machen wir eine Karte der neuen Korona-Infektionsstelle [FastAPI / PostGIS / deck.gl (React)] (Datenverarbeitung)

New Corona ... Die Ausbreitung der Infektion hört nicht auf ...

Als junger GIS-Shop wollte ich einige Daten auf eine Karte setzen und visualisieren, aber die meisten öffentlich verfügbaren Daten waren PDF-Dateien, daher war es schwierig, sie zu sammeln.

Aber! !! !! !! !! !!

Websites, die hervorragende Daten mit kostenlosem Kopieren, Zitieren und Nachdrucken für nichtkommerzielle Zwecke bereitstellen ([https://gis.jag-japan.com/covid19jp/](https: // gis). Ich habe jag-japan.com/covid19jp/)) gefunden, daher möchte ich diese Daten verwenden, um sie auf einer Karte auszudrücken! !! xf

Dieses Mal hat es nach dem Studium eine leicht redundante Konfiguration (z. B. Starten eines Anwendungsservers und eines DB-Servers mit Docker-Compose und Bereitstellen von GeoJSON mit API).

Daten bekommen

Schauen wir uns die Daten sofort an!

Gehen Sie zur obigen Site und klicken Sie oben links auf den Link "csv".

スクリーンショット 2020-03-30 7.40.44.png

Dann können Sie die folgende CSV herunterladen.

COVID-19.csv


Durch,Ministerium für Gesundheit, Arbeit und Soziales NR,Asymptomatischer Erregerträger,Inländisch,Charterflug,Alter,Sex,Festes Datum,Datum des Beginns,Beratungspräfektur,Präfektur des Wohnsitzes,In der Wohngerichtsbarkeit,Wohnort,Schlüssel,Ankündigung,Präfektur Fallnummer,Status,Bemerkungen,Quelle,Quelle2,Quelle3,Anzahl der Personen,Kumulativ,Der Tag vor Verhältnis,Total tot,Anzahl der EntladungenKumulativ,Anzahl der Entladungen,Zahl der Fälle,PCR検査実施Anzahl der Personen,PCR検査Der Tag vor Verhältnis,Beruf_Zur Bestätigung der Richtigkeit,Arbeitsplatz_Zur Bestätigung der Richtigkeit,Hospital Pref,Residential Pref,Release,Gender,X,Y,Festes DatumYYYYMMDD,Beratungspräfekturコード,Präfektur des Wohnsitzesコード,Datum und Uhrzeit aktualisieren,Field2,Field4,Field5,Field6,Field7,Field8,Field9,Field10
1 ,1 ,,A-1,,30 ,männlich,1/15/2020,1/3/2020,Präfektur Kanagawa,Präfektur Kanagawa,,,Präfektur Kanagawa,Präfektur Kanagawa,1,Erfüllen,,https://www.mhlw.go.jp/stf/newpage_08906.html,https://www.pref.kanagawa.jp/docs/ga4/bukanshi/occurrence.html,,1 ,1 ,1 ,0 ,1 ,1 ,0 ,,,,,Kanagawa,Kanagawa,Kanagawa Prefecture,Male,139.642347,35.447504,2020/1/15,14,14,3/29/2020 18:50,,,,,,,,
2 ,2 ,,A-2,,40 ,männlich,1/24/2020,1/14/2020,Tokio,Volksrepublik China,,,Volksrepublik China,Tokio,1,Erfüllen,,https://www.mhlw.go.jp/stf/newpage_09079.html,https://www.metro.tokyo.lg.jp/tosei/hodohappyo/press/2020/01/24/20.html,,1 ,2 ,1 ,0 ,,,2 ,,,,,Tokyo,China(Mainland),Tokyo Metropolitan Government,Male,116.409685,39.903832,2020/1/24,13,NA,,,,,,,,,

CSV ist das Beste.

Die Anzahl der infizierten Personen = die Anzahl der Datensätze, und sie liefern recht detaillierte Daten, aber ich kann damit nicht umgehen. Konzentrieren wir uns also auf die Daten, die Sie verwenden möchten!

Erstellen Sie eine virtuelle Umgebung, bevor Sie Daten verarbeiten

Lassen Sie uns vorerst ein Arbeitsverzeichnis und ein Datenverarbeitungs-Arbeitsverzeichnis erstellen! (Der Verzeichnisname (diesmal covid_sample) ist beliebig)

Mit dem folgenden Befehl können Sie das Verzeichnis covid_sample und das Skriptverzeichnis darunter gleichzeitig erstellen.

$mkdir -p covid_sample/script

Dieses Mal möchte ich nur die Daten auf der Karte anzeigen, also möchte ich die Daten auf der Karte anzeigen. Nehmen wir nur um X "," Y "]` heraus!

Ich möchte die Umgebung des Hauptcomputers nicht verschmutzen, daher erstelle ich eine virtuelle Umgebung mit "pipenv" usw. und bearbeite sie schnell mit Pandas.

Ich denke, der Artikel hier wird sehr hilfreich für die Verwendung von pipenv sein!

Wenn Sie pipenv installiert haben, verschieben Sie das Skriptverzeichnis mit "$ cd covid_sample / script" und erstellen Sie eine Pip-Datei wie die folgende.

Pipfile


[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
pandas = "==0.24.2"
requests = "*"

[requires]
python_version = "3.8"

Die obige Datei ist eine Datei, die angibt, wie eine virtuelle Umgebung erstellt wird. Im obigen Beispiel ist die Python-Version 3.8 und Pandas und Anforderungen werden installiert.

Erstellen Sie eine virtuelle Umgebung mit dem Befehl "$ pipenv install" und geben Sie die virtuelle Umgebung mit der Shell "$ pipenv" ein.

Dann denke ich, dass ein Zeichen wie (Skript) am linken Ende der Shell angezeigt wird, aber wenn dies angezeigt wird, befindet es sich in der virtuellen Umgebung.

Wenn Sie die installierten Bibliotheken mit "$ pip list" in diesem Status überprüfen, können Sie sehen, dass Pandas und Anforderungen und ihre Abhängigkeiten installiert sind.

(script) hogehoge:script$pip list
Package         Version   
--------------- ----------
certifi         2019.11.28
chardet         3.0.4     
idna            2.9       
numpy           1.18.2    
pandas          0.24.2    
pip             20.0.2    
python-dateutil 2.8.1     
pytz            2019.3    
requests        2.23.0    
setuptools      46.1.3    
six             1.14.0    
urllib3         1.25.8    
wheel           0.34.2    

Damit ist die Erstellung der virtuellen Umgebung abgeschlossen!

Datenverarbeitung

Lassen Sie uns ein Python-Skript wie das folgende erstellen! Ich habe es "format.py" genannt!

Dieses Skript wird csv sofort herunterladen und verarbeiten!

format.py


import pandas as pd
from datetime import datetime as dt
import requests

#CSV-URL
csv_url = "https://dl.dropboxusercontent.com/s/6mztoeb6xf78g5w/COVID-19.csv"

try:
    #Geben Sie die URL- und http-Anforderung mit der GET-Methode an
    r = requests.get(csv_url)
    # COVID-19.Als CSV speichern
    with open("COVID-19.csv", 'wb') as f:
        f.write(r.content)
except requests.exceptions.RequestException as err:
    print(err)

#Geben Sie den Namen der zu verwendenden Spalte an
column_names = [
    "Durch", "Alter", "Sex", "Festes Datum", "Datum des Beginns",
    "Beratungspräfektur", "Präfektur des Wohnsitzes", "X", "Y",
]

#Spaltennamen ändern
changed_column_name = {
    "Durch": "id",
    "Alter": "age",
    "Sex": "gender",
    "Festes Datum": "fixed_data",
    "Datum des Beginns": "onset_data",
    "Beratungspräfektur": "consultation",
    "Präfektur des Wohnsitzes": "prefectures",
    "X": "lng",
    "Y": "lat",
}

#Geben Sie den in usecols verwendeten Spaltennamen im Array-Format an
df = pd.read_csv('COVID-19.csv', usecols=column_names)
#Geben Sie den Spaltennamen an, der im Wörterbuchformat geändert werden soll
rename_df = df.rename(columns=changed_column_name)

#Erstellen Sie eine Liste, indem Sie die angegebene Zeichenfolge aus der Altersspalte löschen
rename_df["age"] = [string.strip(' ') for string in list(rename_df["age"])]
#Zeit in Datum umwandeln
rename_df["fixed_data"] = [dt.strptime(data_string, "%m/%d/%Y").date() for data_string in list(rename_df["fixed_data"])]
# onset_Ersetzen Sie NaN in Daten
rename_df.fillna({'onset_data': '1/1/0001'}, inplace=True)
rename_df["onset_data"] = [dt.strptime(data_string, "%m/%d/%Y").date() for data_string in list(rename_df["onset_data"])]

#Ersetzen Sie den angegebenen Wert in der angegebenen Spalte
# inplace=Ändern Sie die ursprüngliche df mit True
rename_df.replace(
    {
        "age": {"Unbekannt": "999", "0-10": "10"}
    }
    , inplace=True)

#Export nach CSV
rename_df.to_csv("../docker/postgis/custom_COVID-19.csv", index=False)

Wenn dieser Befehl ausgeführt wird, wird csv heruntergeladen und im selben Verzeichnis wie das Skript gespeichert. Anschließend werden die erforderlichen Daten extrahiert und verarbeitet und in das angegebene Verzeichnis entladen.

Die Details sind in den Kommentaren des Codes beschrieben. Wenn Sie also dort nachsehen, können Sie es verstehen!

Geben Sie für den CSV-Entladungsspeicherort (covid_sample / fastAPI / docker / postgis / custom_COVID-19.csv) das neue Verzeichnis an, das durch Erstellen der im Element erläuterten Docker-Umgebung erstellt wurde, und geben Sie dasselbe Verzeichnis in den Docker-Einstellungen an. Bitte seien Sie vorsichtig, wenn Sie das Skript ausführen!

Umgebungskonstruktion mit Docker-Compose

Wenn Sie die Verarbeitung von csv abgeschlossen haben, drücken Sie "Strg + D", um die virtuelle Umgebung zu verlassen, und verwenden Sie "cd ../", um zum Stammverzeichnis (covid_sample) zurückzukehren.

Lassen Sie uns die Daten in GeoJSON konvertieren, ein Format von Geoinformationen, das im Web einfach zu verarbeiten ist!

Jede Methode kann verwendet werden, aber in Zukunft möchte ich die Daten als API verwenden. Registrieren Sie sie also in der Datenbank und starten Sie den API-Server über das Backend!

In diesem Fall verwenden wir Docker, was für den Start des Personal Servers sehr praktisch ist!

Wir gehen davon aus, dass es installiert ist. Wenn Sie also einen Mac verwenden, lesen Sie bitte Docker Compose --Installation usw. mit Docker Bitte installieren Sie Docker-Compose. (Wenn Sie für ein anderes Betriebssystem googeln, wird es bald herauskommen!)

Erstellen Sie nach der Erstellung ein Verzeichnis für die API wie folgt!

$mkdir -p docker/fastapi
$mkdir -p docker/postgis/init
$mkdir docker/postgis/sql

Die aktuelle Verzeichnisstruktur sollte so aussehen!

covid_sample
├── docker
│   ├── fastapi
│   └── postgis
│       ├── init
│       └── sql
└── script
    ├── COVID-19.csv
    ├── Pipfile
    ├── Pipfile.lock
    └── format.py

Darüber hinaus sind einige Dateien erforderlich, um Docker zu starten. Daher werden sie im Folgenden grob beschrieben. Kopieren Sie sie daher bitte und verwenden Sie sie! Lol

docker/docker-compose.yml


version: '3.7'
services:
    fastapi:
#Containername
        container_name: fastapi
#Verzeichnis mit der zu erstellenden Docker-Datei
        build: fastapi
        volumes:
#Verzeichnis zum Mounten
            - ./fastapi:/usr/src/app/
        ports:
#Host-seitiger Port: Container-seitiger Port
            - 8000:8000
        env_file:
#Datei, die in der Umgebungsvariablen festgelegt werden soll
            - fastapi/.env
        depends_on:
#Service zum Verbinden
            - postgis

    postgis:
        container_name: postgis
        build: postgis
        volumes:
            - covid_postgis_data:/var/lib/postgresql/data
#            down -Geben Sie die Datei an, die beim ersten Start ausgeführt werden soll, auch wenn kein Volume mit v usw. vorhanden ist.
            - ./postgis/init:/docker-entrypoint-initdb.d
#Verzeichnis zum Mounten
            - ./postgis:/home
        env_file: postgis/.env_db
        ports:
#Der Port auf der Host-Seite schlägt mit dem lokalen psql, also scheint es besser als 5432
            - 5433:5432

volumes:
    covid_postgis_data:

docker/fastapi/.env


DATABASE_HOST=localhost
DATABASE_PORT=5433

--Dockerfile zum Starten des Fastapi-Containers (Docker / Fastapi / Dockerfile)

docker/fastapi/Dockerfile


FROM python:3.8

RUN apt-get update -y --fix-missing \
    && apt-get install -y -q --no-install-recommends

# install
RUN pip install pipenv
ADD Pipfile Pipfile.lock /
RUN pipenv install --system

# add to application
ADD app.py /

CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]

docker/fastapi/Pipfile


[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
fastapi = "*"
uvicorn = "*"
psycopg2-binary = "*"

[requires]
python_version = "3.8.0"

--Anwendungsdatei für Fastapi

docker/fastapi/app.py


from fastapi import FastAPI

app = FastAPI()

# `uvicorn app:app --reload`Beginnen mit
@app.get("/")
async def hello():
    return {"text": "hello"}

--postgis Container Umgebungsvariable Einstellungsdatei

Geben Sie ein Passwort für "docker / postgis / .env_db" an.

docker/postgis/.env_db


#Wenn Sie im Postgres-Container in env schreiben, wird die Datenbank automatisch erstellt
POSTGRES_USER=covid_user
POSTGRES_PASSWORD=hogehoge
POSTGRES_DB=covid_db

--Postgis Dockerfile für den Container-Start (Docker / Postgis / Dockerfile)

docker/postgis/Dockerfile


FROM mdillon/postgis:9.6

# locale settings.
RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
ENV LANG ja_JP.UT

--postgis Shell-Skript wird geladen, wenn der Container zum ersten Mal gestartet wird

docker/postgis/init/init.sh


#!/bin/sh

psql -U covid_user -d covid_db -f /home/sql/init.sql

psql -U covid_user -d covid_db -c "COPY covid_data FROM '/home/custom_COVID-19.csv' WITH CSV HEADER DELIMITER ',';"

psql -U covid_user -d covid_db -f /home/sql/create_geom.sql

docker/postgis/sql/init.sql


CREATE EXTENSION postgis;

create table covid_data
(
    id           smallint not null,
    age          int,
    gender       text,
    fixed_data   date,
    onset_data   date,
    consultation text,
    prefectures  text,
    lng          float,
    lat          float
);

docker/postgis/sql/create_geom.sql


alter table covid_data
	add geom geometry(point, 4326);

UPDATE covid_data SET geom = ST_GeogFromText('SRID=4326;POINT(' || lng || ' ' || lat || ')')::GEOMETRY;

Sobald Sie die CSV mit den oben genannten Dateien und Skripten verarbeitet haben, erstellen und starten Sie sie mit $ docker-compose up -d --build!

Dieses Mal starten wir einen Container für "FastAPI", ein Microweb-Framework für Python, und "PostGIS", eine räumliche Erweiterung für PostgreSQL.

Wenn der Container gestartet wird, werden CSV-Daten in der Datenbank registriert, und init.sh generiert automatisch eine Geomspalte vom Geometrietyp aus diesen Daten und gibt die Daten ein.

Zu diesem Zeitpunkt sollten Sie in der Lage sein, die Daten anzuzeigen, indem Sie auf irgendeine Weise eine Verbindung zur Datenbank im Postgis-Container herstellen (z. B. pgadmin oder $ psql -U covid_user -d covid_db -h localhost -p 5433).

Wenn Sie über Ihren Browser auf localhost: 8000 zugreifen und die Anzeige von {" text ":" hello "} zurückgegeben wird, ist die Erstellung der Docker-Compose-Umgebung abgeschlossen!

API erstellen

Sobald Sie eine Umgebung haben, erstellen wir eine API!

Bearbeiten Sie docker / fastapi / app.py wie folgt!

docker/fastapi/app.py


from fastapi import FastAPI
import psycopg2
from starlette.middleware.cors import CORSMiddleware

app = FastAPI()

#Für CORS-Einstellungen hinzugefügt
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"]
)

# `uvicorn app:app --reload`Beginnen mit
@app.get("/")
async def hello():
    #Stellen Sie eine Verbindung zu postgreSQL her
    connection = psycopg2.connect(
        # host="localhost",
        host="postgis",
        user="covid_user",
        password="hogehoge",
        dbname="covid_db",
        port=5432
    )

    #Stellen Sie die Codierung des Client-Programms ein (automatisch aus dem DB-Zeichencode konvertieren)
    connection.set_client_encoding('utf-8')

    #Holen Sie sich den Cursor
    cursor = connection.cursor()

    #Geojson generieren
    sql = """
    SELECT jsonb_build_object(
        'type',     'FeatureCollection',
        'features', jsonb_agg(features.feature)
    )
    FROM (
      SELECT jsonb_build_object(
        'type',       'Feature',
        'id',         id,
        'geometry',   ST_AsGeoJSON(geom)::jsonb,
        'properties', to_jsonb(inputs) - 'gid' - 'geom'
      ) AS feature
      FROM (SELECT * FROM covid_data) inputs) features;
    """

    #SQL-Ausführung
    cursor.execute(sql)

    #Ergebnis der Ausgabeerfassung
    results = cursor.fetchall()[0][0]

    #Schließen Sie den Cursor
    cursor.close()

    #Trennen
    connection.close()

    return results

In dieser Anwendung ist es zunächst erforderlich, über React with Ajax auf die API zuzugreifen, um Daten zu erfassen und anzuzeigen. Daher stellen wir CORS ein (diesmal sind als Test alle Hosts und Methoden zulässig, jedoch Bitte hören Sie so viel wie möglich auf, da dies gefährlich ist.

Wenn Sie es nicht festlegen, können Sie nicht über die JavaScript-Seite (Anwendung zum Anzeigen von Karten) auf die API zugreifen. Stellen Sie es also unbedingt ein! (Für weitere Informationen versuchen Sie Google mit "CORS"!)

In dem Teil von "@ app.get (" / ")" bedeutet dies, dass die Verarbeitung, auf die über die GET-Methode zugegriffen wird, darunter geschrieben wird. Lassen Sie uns diesmal den Prozess hier schreiben.

Greifen Sie danach mit einem Modul namens "psycopg2" auf die Datenbank zu, um von Python aus eine Verbindung zu PostgreSQL herzustellen.

Im SQL-Teil werden die Daten mithilfe der JSONB-Typfunktion von PostgreSQL zwangsweise in GeoJSON konvertiert.

Stoppen Sie nach dem Umschreiben die Container mit "$ docker-compose down" und starten Sie mit "$ docker-compose up -d --build" neu!

Stellen Sie nach Abschluss des Startvorgangs erneut eine Verbindung zu localhost: 8000 her.

Wenn alles gut geht, solltest du dir so einen GeoJSON zulegen!

{
    "type": "FeatureCollection",
    "features": [
        {
            "id": 1,
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [
                    139.642347,
                    35.447504
                ]
            },
            "properties": {
                "id": 1,
                "age": 30,
                "lat": 35.447504,
                "lng": 139.642347,
                "gender": "männlich",
                "fixed_data": "2020-01-15",
                "onset_data": "2020-01-03",
                "prefectures": "Präfektur Kanagawa",
                "consultation": "Präfektur Kanagawa"
            }
        },
        {
            "id": 2,
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [
                    116.409685,
                    39.903832
                ]
            },
            "properties": {
                "id": 2,
                "age": 40,
                "lat": 39.903832,
                "lng": 116.409685,
                "gender": "männlich",
                "fixed_data": "2020-01-24",
                "onset_data": "2020-01-14",
                "prefectures": "Volksrepublik China",
                "consultation": "Tokio"
            }
        },
        ...
}

Jetzt sind die Daten fertig! !!

Lassen Sie uns diese Daten das nächste Mal auf der Karte anzeigen!

→ Klicken Sie hier, um weitere Informationen zu erhalten: [Erstellen einer neuen Corona-Infektions-Site-Map FastAPI / PostGIS / deck.gl (React)](https://qiita.com/nokonoko_1203/items/23ee1ffb6880f6acdda9)

Recommended Posts

Machen wir eine Karte der neuen Korona-Infektionsstelle [FastAPI / PostGIS / deck.gl (React)] (Datenverarbeitung)
Lassen Sie uns die Analyse der sinkenden Daten der Titanic so durchführen
Werfen wir einen Blick auf die Feature-Map von YOLO v3
Lassen Sie uns mit flask-babel eine mehrsprachige Site erstellen
Wie erstelle ich eine Pelican Site Map?
Die Geschichte der Verarbeitung A von Blackjack (Python)
Versuchen Sie, die Umweltkonzentration organischer Fluorverbindungen mit offenen Daten auf einer Karte darzustellen
Erstellen Sie einen BOT, der die Anzahl der infizierten Personen in der neuen Corona anzeigt