Rasterize shapefile dengan Geopanda atau fiona - python

10

Saya perlu merasterisasi shapefile yang sangat sederhana sedikit seperti ini http://tinyurl.com/odfbanu . Yang hanya merupakan negara coutaining shapefile di AS. Saya telah melihat jawaban sebelumnya: GDAL RasterizeLayer tidak Membakar Semua Poligon ke Raster? tapi saya bertanya-tanya apakah ada cara untuk melakukannya menggunakan Geopanda atau fiona dan mungkin rasterio untuk bagian penulisan tiff.

Jadi tujuan saya adalah merasterisasi dan menetapkan nilai untuk setiap poligon yang berbagi nilai umum, LSAD dalam pengecualian.

Jadi saya menulis awal kode yang terinspirasi oleh shongololo di utas: Melarutkan poligon berdasarkan atribut dengan Python (rupawan, fiona)? .

from geopandas import GeoDataFrame

name_in = 'cb_2013_us_county_20m.shp'

#Open the file with geopandas
counties = GeoDataFrame.from_file(name_in)

#Add a column to the Geodataframe containing the new value
for i in range (len(counties)):
    LSAD = counties.at[i,'LSAD']
    if LSAD == 00 :
        counties['LSAD_NUM'] == 'A'
    elif LSAD == 03 :
        counties['LSAD_NUM'] == 'B'
    elif LSAD == 04 :
        counties['LSAD_NUM'] == 'C'
    elif LSAD == 05 :
        counties['LSAD_NUM'] == 'D'
    elif LSAD == 06 :
        counties['LSAD_NUM'] == 'E'
    elif LSAD == 13 :
        counties['LSAD_NUM'] == 'F'
    elif LSAD == 15 :
        counties['LSAD_NUM'] == 'G'  
    elif LSAD == 25 :
        counties['LSAD_NUM'] == 'I'          
    else :
        counties['LSAD_NUM'] == 'NA'

Benar-benar hal yang mudah jadi sekarang saya bertanya-tanya bagaimana saya bisa benar-benar menulis bentuk-bentuk itu ke tiff. Saya mulai bekerja dengan Geopanda karena saya percaya itu adalah pilihan terbaik tetapi jika Anda memiliki saran fiona saya siap untuk itu juga.

Saya menemukan sepotong kode dari rasterio yang tampaknya dapat mengambil bentuk geometri dan membakarnya menjadi raster baru http://tinyurl.com/op49uek

# I guess that my goal should be to load my list of geometries under geometry to be able to pass it to rasterio later on
geometry = {'type':'Polygon','coordinates':[[(2,2),(2,4.25),(4.25,4.25),(4.25,2),(2,2)]]}

with rasterio.drivers():
    result = rasterize([geometry], out_shape=(rows, cols))
    with rasterio.open(
            "test.tif",
            'w',
            driver='GTiff',
            width=cols,
            height=rows,
            count=1,
            dtype=numpy.uint8,
            nodata=0,
            transform=IDENTITY,
            crs={'init': "EPSG:4326"}) as out:
                 out.write_band(1, result.astype(numpy.uint8))
User18981898198119
sumber
Jawabannya adalah tentang GDALrasterize, saya bertanya apakah seseorang memiliki ide untuk melakukan hal yang sama menggunakan Geopandas dan rasterio. Bukan duplikat
User18981898198119
Menemukan sepotong Kode yang mungkin membantu, dikirim diedit
User18981898198119

Jawaban:

20

Anda berada di jalur yang benar dan geopandas GeoDataFrame adalah pilihan yang baik untuk rasterisasi di atas Fiona. Fiona adalah toolset yang hebat, tapi saya pikir bahwa DataFrame lebih cocok untuk shapefile dan geometri daripada kamus bersarang.

import geopandas as gpd
import rasterio
from rasterio import features

Siapkan nama file Anda

shp_fn = 'cb_2013_us_county_20m.shp'
rst_fn = 'template_raster.tif'
out_fn = './rasterized.tif'

Buka file dengan GeoPANDAS read_file

counties = gpd.read_file(shp_fn)

Tambahkan kolom baru (seperti pada kode Anda di atas)

for i in range (len(counties)):
    LSAD = counties.at[i,'LSAD']
    if LSAD == 00 :
        counties['LSAD_NUM'] == 'A'
    elif LSAD == 03 :
        counties['LSAD_NUM'] == 'B'
    elif LSAD == 04 :
        counties['LSAD_NUM'] == 'C'
    elif LSAD == 05 :
        counties['LSAD_NUM'] == 'D'
    elif LSAD == 06 :
        counties['LSAD_NUM'] == 'E'
    elif LSAD == 13 :
        counties['LSAD_NUM'] == 'F'
    elif LSAD == 15 :
        counties['LSAD_NUM'] == 'G'  
    elif LSAD == 25 :
        counties['LSAD_NUM'] == 'I'          
    else :
        counties['LSAD_NUM'] == 'NA'

Buka file raster yang ingin Anda gunakan sebagai templat untuk pembakaran fitur menggunakan rasterio

rst = rasterio.open(rst_fn)

salin dan perbarui metadata dari raster input untuk output

meta = rst.meta.copy()
meta.update(compress='lzw')

Sekarang bakar fitur-fiturnya ke dalam raster dan tuliskan

with rasterio.open(out_fn, 'w+', **meta) as out:
    out_arr = out.read(1)

    # this is where we create a generator of geom, value pairs to use in rasterizing
    shapes = ((geom,value) for geom, value in zip(counties.geometry, counties.LSAD_NUM))

    burned = features.rasterize(shapes=shapes, fill=0, out=out_arr, transform=out.transform)
    out.write_band(1, burned)

Gagasan keseluruhan adalah untuk membuat tuple berisi (geometri, nilai) yang dapat diubah, di mana geometri adalah geometri yang indah dan nilainya adalah apa yang ingin Anda bakar ke dalam raster di lokasi geometri itu. Baik Fiona dan GeoPANDAS menggunakan geometri yang indah sehingga Anda beruntung di sana. Dalam contoh ini generator digunakan untuk beralih melalui pasangan (geometri, nilai) yang diekstrak dari GeoDataFrame dan bergabung bersama menggunakan zip ().

Pastikan Anda membuka out_fnfile dalam w+mode, karena itu harus digunakan untuk membaca dan menulis.

Michael Lindgren
sumber
1

geocube adalah alat baru yang dirancang khusus untuk meraster data geopanda yang membungkus rasterio. Ini menyederhanakan proses dan menghilangkan kebutuhan untuk raster template.

https://github.com/corteva/geocube

Dalam konteks contoh di atas:

from geocube.api.core import make_geocube
import geopandas

counties = geopandas.read_file("zip://cb_2013_us_county_20m.zip/cb_2013_us_county_20m.shp")

Surat itu dapat diatur pada kerangka data seperti:

counties["LSAD_LETTER"] = 'NA'
lsad_letter = counties.LSAD_LETTER.copy()
lsad_letter[counties.LSAD=='00'] = 'A'
lsad_letter[counties.LSAD=='03'] = 'B'
lsad_letter[counties.LSAD=='04'] = 'C'
lsad_letter[counties.LSAD=='05'] = 'D'
lsad_letter[counties.LSAD=='06'] = 'E'
lsad_letter[counties.LSAD=='13'] = 'F'
lsad_letter[counties.LSAD=='15'] = 'G'
lsad_letter[counties.LSAD=='25'] = 'I'
counties["LSAD_LETTER"] = lsad_letter

Namun, hanya nilai numerik yang dapat dirasterisasi. Berikut ini adalah contoh kategorikal: https://corteva.github.io/geocube/stable/examples/categorical.html

Jadi, alih-alih menggunakan itu, gunakan angka dalam format string dan konversikan ke integer:

counties["LSAD_NUM"] = counties.LSAD.astype(int)

Kemudian, rasterisasi data:

cube = make_geocube(
    counties,
    measurements=["LSAD_NUM"],
    resolution=(1, -1),
)

masukkan deskripsi gambar di sini

Terakhir, ekspor ke raster:

cube.LSAD_NUM.rio.to_raster("lsad_num.tif")
manusia salju2
sumber