Rohdaten in Geopandas einlesen

12

Ist es möglich, Rohdaten in a geopandas GeoDataFrame, a la a einzulesen pandas DataFrame?

Zum Beispiel funktioniert Folgendes:

import pandas as pd
import requests
data = requests.get("https://data.cityofnewyork.us/api/geospatial/arq3-7z49?method=export&format=GeoJSON")
pd.read_json(io.BytesIO(r.content))

Folgendes nicht:

import geopandas as gpd
import requests
data = requests.get("https://data.cityofnewyork.us/api/geospatial/arq3-7z49?method=export&format=GeoJSON")
gpd.read_file(io.BytesIO(r.content))

Mit anderen Worten, ist es möglich, Geodaten zu lesen, die sich im Speicher befinden, ohne diese Daten zuerst auf der Festplatte zu speichern?

Aleksey Bilogur
quelle

Antworten:

14

Sie können den json direkt an den GeoDataFrame-Konstruktor übergeben:

import geopandas as gpd
import requests
data = requests.get("https://data.cityofnewyork.us/api/geospatial/arq3-7z49?method=export&format=GeoJSON")
gdf = gpd.GeoDataFrame(data.json())
gdf.head()

Ausgänge:

                                            features               type
0  {'type': 'Feature', 'geometry': {'type': 'Poin...  FeatureCollection
1  {'type': 'Feature', 'geometry': {'type': 'Poin...  FeatureCollection
2  {'type': 'Feature', 'geometry': {'type': 'Poin...  FeatureCollection
3  {'type': 'Feature', 'geometry': {'type': 'Poin...  FeatureCollection
4  {'type': 'Feature', 'geometry': {'type': 'Poin...  FeatureCollection

Für Single-File - Formate oder ZIP - Shape - Dateien unterstützt, können Sie fiona.BytesCollectionund GeoDataFrame.from_features:

import requests
import fiona
import geopandas as gpd

url = 'http://www.geopackage.org/data/gdal_sample.gpkg'
request = requests.get(url)
b = bytes(request.content)
with fiona.BytesCollection(b) as f:
    crs = f.crs
    gdf = gpd.GeoDataFrame.from_features(f, crs=crs)
    print(gdf.head())
und für Shapefiles mit Reißverschluss (unterstützt ab Fiona 1.7.2 )
url = 'https://www2.census.gov/geo/tiger/TIGER2010/STATE/2010/tl_2010_31_state10.zip'
request = requests.get(url)
b = bytes(request.content)
with fiona.BytesCollection(b) as f:
    crs = f.crs
    gdf = gpd.GeoDataFrame.from_features(f, crs=crs)
    print(gdf.head())

Sie können herausfinden, welche Formate Fiona unterstützt, indem Sie Folgendes verwenden:

import fiona
for name, access in fiona.supported_drivers.items():
    print('{}: {}'.format(name, access))

Und eine hackige Problemumgehung zum Lesen von komprimierten In-Memory-Daten in Fiona 1.7.1 oder früher:

import requests
import uuid
import fiona
import geopandas as gpd
from osgeo import gdal

request = requests.get('https://github.com/OSGeo/gdal/blob/trunk/autotest/ogr/data/poly.zip?raw=true')
vsiz = '/vsimem/{}.zip'.format(uuid.uuid4().hex) #gdal/ogr requires a .zip extension

gdal.FileFromMemBuffer(vsiz,bytes(request.content))
with fiona.Collection(vsiz, vsi='zip', layer ='poly') as f:
    gdf = gpd.GeoDataFrame.from_features(f, crs=f.crs)
    print(gdf.head())
user2856
quelle
Dies funktioniert für GeoJSON, das die Frage beantwortet. Dies würde jedoch nicht für andere Geodateiformate funktionieren, z. B. Shapefiles oder KML oder KMZ. Kennen Sie eine Problemumgehung für diese Fälle?
Aleksey Bilogur
Eine kleine Klarstellung ist angebracht. GeoPandas und Fiona unterstützen Shapefiles und KML, können jedoch nicht einmalige APIs wie die der Stadt New York vollständig unterstützen. Funktioniert auch BytesCollectionvöllig, wird aber wahrscheinlich in einer zukünftigen Version zugunsten einer der Optionen in github.com/Toblerity/Fiona/issues/409 entfernt .
Sgillies
Vielen Dank. @sgillies sollte dies als Feature-Anfrage für geöffnet werden geopandas, oder ist es besser, auf die Änderungen zu warten, die Sie hier erwähnen ?
Aleksey Bilogur
@sgillies Sie geben an, dass Fiona KML in Ihrem obigen Kommentar unterstützt, DriverError: unsupported driver: 'KML'wird jedoch beim Versuch, KML zu öffnen, ausgelöst, da es nicht im supported_driversDiktat enthalten ist (mit Fiona 1.7.1), und ich habe einige Probleme bezüglich festgestellt. Mangel an KML-Unterstützung (# 23 & # 97). Unterstützt Fiona KML?
user2856
3

Da fiona.BytesCollectionscheint TopoJSONhier keine Lösung zu funktionieren, die für alle funktioniert, ohne dass gdal:

import fiona
import geopandas as gpd
import requests

# parse the topojson file into memory
request = requests.get('https://vega.github.io/vega-datasets/data/us-10m.json')
visz = fiona.ogrext.buffer_to_virtual_file(bytes(request.content))

# read the features from a fiona collection into a GeoDataFrame
with fiona.Collection(visz, driver='TopoJSON') as f:
    gdf = gpd.GeoDataFrame.from_features(f, crs=f.crs)
Mattijn
quelle
Mit geopandas==0.4.0, Fiona==1.8.4und Python 3, erhalte ich DriverError: unsupported driver: 'TopoJSON'.
Edesz
Du hast recht. Es funktionierte bis mindestens Version 1.7.13vonFiona
Mattijn
Es ist bedauerlich, dass dies nicht funktioniert. Ich habe versucht, Ihrem Beispiel auf GitHub für Altair-Choroplethen-Plots zu folgen, aber auch das wirft genau den gleichen Fehler in die Zeile gdf = gpd.read_file(counties, driver='TopoJSON'). Ich dachte, dass die Verwendung with fiona.Collection...funktionieren könnte, aber leider nicht.
Edesz
@edesz dies war ein Fehler und wird in Fiona
1.8.5
2

Bei Verwendung von Fiona 1.8 kann (muss?) Dies mit dem Projekt MemoryFileoder durchgeführt werdenZipMemoryFile .

Zum Beispiel:

import fiona.io
import geopandas as gpd
import requests

response = requests.get('http://example.com/Some_shapefile.zip')
data_bytes = response.content

with fiona.io.ZipMemoryFile(data_bytes) as zip_memory_file:
    with zip_memory_file.open('Some_shapefile.shp') as collection:
      geodf = gpd.GeoDataFrame.from_features(collection, crs=collection.crs)
esmail
quelle
0

Am einfachsten ist es, die GeoJSON-URL direkt in gpd.read () einzugeben. Ich hatte zuvor versucht, ein Shapefile mit BytesIO & zipfile aus einer Zip-Datei zu extrahieren, und hatte Probleme damit, dass gpd (insbesondere Fiona) dateiähnliche Objekte akzeptiert.

import geopandas as gpd
import David.SQL_pull_by_placename as sql
import os

os.environ['PROJ_LIB'] = r'C:\Users\littlexsparkee\Anaconda3\Library\share\proj'

geojson_url = f'https://github.com/loganpowell/census-geojson/blob/master/GeoJSON/500k/2018/{sql.state}/block-group.json?raw=true'
census_tracts_gdf = gpd.read_file(geojson_url)
littlexsparkee
quelle