การอ่านข้อมูลดิบลงใน geopandas


14

เป็นไปได้ไหมที่จะอ่านข้อมูลดิบลงใน a geopandas GeoDataFrame, a la a pandas DataFrame?

ตัวอย่างเช่นงานดังต่อไปนี้:

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

สิ่งต่อไปนี้ไม่:

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

กล่าวอีกนัยหนึ่งเป็นไปได้ไหมที่จะอ่านข้อมูลเชิงพื้นที่ที่อยู่ในหน่วยความจำโดยไม่บันทึกข้อมูลนั้นลงดิสก์ก่อน

คำตอบ:


16

คุณสามารถส่ง json โดยตรงไปยังตัวสร้าง 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()

ขาออก:

                                            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

สำหรับรูปแบบไฟล์เดี่ยวหรือรูปร่างที่ได้รับการสนับสนุนคุณสามารถใช้fiona.BytesCollectionและ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())
และสำหรับรูปร่างที่ซิป (รองรับ ณ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())

คุณสามารถค้นหารูปแบบที่ฟิโอน่าสนับสนุนโดยใช้สิ่งที่ชอบ

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

และวิธีแก้ปัญหาการแฮ็กสำหรับการอ่านข้อมูลซิปในหน่วยความจำใน fiona 1.7.1 หรือสูงกว่า:

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

สิ่งนี้ใช้ได้กับ GeoJSON ซึ่งตอบคำถาม แต่สิ่งนี้จะใช้ไม่ได้กับรูปแบบไฟล์ geospatial อื่น ๆ เช่น shapefiles หรือ KML หรือ KMZ คุณรู้วิธีแก้ปัญหาสำหรับกรณีเหล่านี้หรือไม่?
Aleksey Bilogur

คำอธิบายเล็กน้อยอยู่ในลำดับ GeoPandas และ Fiona สนับสนุน shapefiles และ KML แต่พวกเขาไม่สามารถรองรับ API แบบ off-off อย่าง City of New York นอกจากนี้BytesCollectionการทำงานโดยสิ้นเชิง แต่อาจจะถูกลบออกในรุ่นอนาคตในความโปรดปรานของหนึ่งในตัวเลือกในgithub.com/Toblerity/Fiona/issues/409
sgillies

ขอบคุณ @sgillies นี้ควรจะเปิดเป็นคำขอคุณลักษณะgeopandasหรือมันจะดีกว่าที่จะรอให้การเปลี่ยนแปลงที่คุณพูดถึงที่นี่ ?
Aleksey Bilogur

@sgillies ที่คุณระบุว่าฟิโอน่าสนับสนุน KML ในความคิดเห็นของคุณด้านบน แต่DriverError: unsupported driver: 'KML'จะเพิ่มขึ้นเมื่อพยายามเปิด KML เนื่องจากไม่ได้อยู่ในคำสั่งsupported_drivers(โดยใช้ฟิโอน่า 1.7.1) และฉันสังเกตเห็นปัญหาสองสามข้อ ไม่มีการสนับสนุน KML (# 23 & # 97) ฟิโอน่าสนับสนุน KML หรือไม่
2856

ขอบคุณสำหรับการตรวจสอบfrom_featuresวิธีการ บันทึกวันของฉัน!
jlandercy

3

เนื่องจากfiona.BytesCollectionดูเหมือนจะไม่ทำงานTopoJSONที่นี่เป็นวิธีการแก้ปัญหาที่เหมาะสำหรับทุกคนโดยไม่ต้อง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)

ด้วยgeopandas==0.4.0, Fiona==1.8.4และ Python 3 DriverError: unsupported driver: 'TopoJSON'ฉันได้รับ
edesz

คุณพูดถูก มันได้รับการทำงานอย่างน้อยจนถึงรุ่น1.7.13ของFiona
Mattijn

มันโชคร้ายที่มันไม่ทำงาน ผมพยายามที่จะทำตามตัวอย่างของคุณบน GitHub สำหรับ Altair choropleth แปลงgdf = gpd.read_file(counties, driver='TopoJSON')แต่ก็โยนข้อผิดพลาดเดียวกันแน่นอนที่บรรทัด ฉันคิดว่าการใช้with fiona.Collection...อาจใช้งานได้ แต่น่าเสียดายที่มันไม่ได้
edesz

@edesz นี่เป็นข้อผิดพลาดและจะได้รับการแก้ไขใน Fiona 1.8.5 ดู: github.com/Toblerity/Fiona/issues/721
Mattijn


2

เมื่อใช้ Fiona 1.8 นี้สามารถ (ต้อง?) ทำได้โดยใช้โครงการที่หรือMemoryFileZipMemoryFile

ตัวอย่างเช่น:

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)

0

วิธีที่ง่ายที่สุดคือการป้อน GeoJSON URL ลงใน gpd.read () โดยตรง ฉันพยายามแยกไฟล์จาก zip ก่อนหน้านี้โดยใช้ BytesIO & zipfile และมีปัญหากับ gpd (โดยเฉพาะฟิโอน่า) ที่รับวัตถุเหมือนไฟล์

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)

0

ฉันชอบผลลัพธ์ที่ได้จากการใช้เอกสารที่GeoDataFrame.from_features()ไม่ใช่เอกสารแทนที่จะส่ง GeoJSON ไปยังตัวสร้าง GDF โดยตรง:

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

เอาท์พุต

                       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 มีการตั้งค่าคอลัมน์รูปทรงเรขาคณิตได้อย่างถูกต้องและคอลัมน์ทั้งหมดตามที่ฉันคาดหวังโดยไม่จำเป็นต้องยกเลิก FeatureCollections ใด ๆ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.