Membaca data mentah menjadi geopanda

14

Apakah mungkin untuk membaca data mentah menjadi geopandas GeoDataFrame, a la a pandas DataFrame?

Misalnya, yang berikut ini berfungsi:

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))

Berikut ini tidak:

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))

Dengan kata lain, apakah mungkin untuk membaca data geospasial yang ada di memori tanpa menyimpan data itu ke disk terlebih dahulu?

Aleksey Bilogur
sumber

Jawaban:

16

Anda bisa meneruskan json langsung ke konstruktor GeoDataFrame:

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()

Output:

                                            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

Untuk format file tunggal yang didukung atau bentuk file zip, Anda dapat menggunakan fiona.BytesCollectiondan 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())
dan untuk shapefile zip (didukung pada 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())

Anda dapat mengetahui format apa yang didukung Fiona menggunakan sesuatu seperti:

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

Dan solusi peretasan untuk membaca data zip di memori dalam fiona 1.7.1 atau sebelumnya:

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())
pengguna2856
sumber
Ini berfungsi untuk GeoJSON, yang menjawab pertanyaan. Tetapi ini tidak akan berfungsi untuk format file geospasial lainnya, hal-hal seperti shapefile atau KML atau KMZ. Apakah Anda tahu solusi untuk kasus-kasus itu?
Aleksey Bilogur
Ada sedikit klarifikasi. GeoPandas dan Fiona mendukung shapefile dan KML, tetapi mereka tidak dapat sepenuhnya mendukung satu dari API seperti Kota New York. Juga, BytesCollectionbenar-benar berfungsi, tetapi mungkin akan dihapus dalam versi masa depan demi salah satu opsi di github.com/Toblerity/Fiona/issues/409 .
sgillies
Terima kasih. @sgillies haruskah ini dibuka sebagai permintaan fitur aktif geopandas, atau apakah lebih baik menunggu perubahan yang Anda sebutkan di sini ?
Aleksey Bilogur
@sgillies Anda menyatakan Fiona mendukung KML dalam komentar Anda di atas, tetapi DriverError: unsupported driver: 'KML'dinaikkan ketika mencoba untuk membuka KML karena tidak ada dalam supported_driversdikt (menggunakan Fiona 1.7.1) dan saya melihat beberapa masalah kembali. kurangnya dukungan KML (# 23 & # 97). Apakah Fiona mendukung KML?
user2856
Terima kasih telah menemukan from_featuresmetode ini. Selamatkan hari saya!
jlandercy
3

Karena fiona.BytesCollectionsepertinya tidak bekerja untuk di TopoJSONsini solusi yang bekerja untuk semua tanpa perlu 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
sumber
Dengan geopandas==0.4.0, Fiona==1.8.4dan Python 3, saya mengerti DriverError: unsupported driver: 'TopoJSON'.
edesz
Kamu benar. Itu bekerja sampai setidaknya versi 1.7.13dariFiona
Mattijn
Sangat disayangkan bahwa ini tidak berhasil. Saya mencoba mengikuti contoh Anda di GitHub untuk plot Altair choropleth tapi itu juga melempar kesalahan yang sama persis di baris gdf = gpd.read_file(counties, driver='TopoJSON'). Saya pikir menggunakan with fiona.Collection...mungkin berhasil tetapi sayangnya tidak.
edesz
@edesz ini adalah bug dan akan diperbaiki di Fiona 1.8.5, lihat: github.com/Toblerity/Fiona/issues/721
Mattijn
2

Saat menggunakan Fiona 1.8, ini dapat (harus?) Dilakukan dengan menggunakan proyek itu MemoryFileatauZipMemoryFile .

Sebagai contoh:

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
sumber
0

Cara termudah adalah memasukkan URL GeoJSON langsung ke gpd.read (). Saya sudah mencoba mengekstraksi shapefile dari zip sebelum ini menggunakan BytesIO & zipfile dan memiliki masalah dengan gpd (khususnya Fiona) menerima objek seperti file.

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
sumber
0

Saya lebih suka hasil yang diperoleh dengan menggunakan yang tidak terdokumentasi GeoDataFrame.from_features()daripada meneruskan GeoJSON ke konstruktor GDF secara langsung:

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

Keluaran

                       geometry                         name                                url           line objectid                                              notes
0    POINT (-73.99107 40.73005)                     Astor Pl  http://web.mta.info/nyct/service/  4-6-6 Express        1  4 nights, 6-all times, 6 Express-weekdays AM s...
1    POINT (-74.00019 40.71880)                     Canal St  http://web.mta.info/nyct/service/  4-6-6 Express        2  4 nights, 6-all times, 6 Express-weekdays AM s...
2    POINT (-73.98385 40.76173)                      50th St  http://web.mta.info/nyct/service/            1-2        3                              1-all times, 2-nights
3    POINT (-73.97500 40.68086)                    Bergen St  http://web.mta.info/nyct/service/          2-3-4        4           4-nights, 3-all other times, 2-all times
4    POINT (-73.89489 40.66471)             Pennsylvania Ave  http://web.mta.info/nyct/service/            3-4        5                        4-nights, 3-all other times

GeoDataFrame yang dihasilkan memiliki kolom geometri yang diatur dengan benar dan semua kolom seperti yang saya harapkan, tanpa perlu membatalkan fitur apapun.

dericke
sumber