Plot shapefile dengan matplotlib


13

Saya mencoba membaca sebuah shapefile dan memplotnya menggunakan matplotlib. Ini kodenya:

import matplotlib.pyplot as plt
import shapefile   

shpFilePath = "D:\test.shp"  
listx=[]
listy=[]
test = shapefile.Reader(shpFilePath)
for sr in test.shapeRecords():
    for xNew,yNew in sr.shape.points:
        listx.append(xNew)
        listy.append(yNew)
plt.plot(listx,listy)
plt.show()

Namun, saya mendapatkan garis yang menghubungkan poligon saya. Bagaimana saya bisa menggambar poligon sedemikian rupa sehingga ada jalan di shapefile. Berikut adalah screenshot dari plot dan shapefile ketika dibuka dengan ArcGIS.Dihasilkan oleh Kode File yang Sebenarnya


Tidak terbiasa dengan pembaca shapefile, namun saya dapat mengatakan bahwa Anda hanya menambahkan semua poin dalam file ke satu daftar besar tanpa memisahkan setiap bentuk menjadi bagian-bagian komponennya. Anda memerlukan daftar besar bentuk tempat Anda menambahkan setiap titik bentuk

Baik. Harus menemukan cara untuk memisahkan bentuk. Tapi itu yang tidak bisa saya lakukan saat ini.
statBeginner

@DanPatterson Bisakah Anda menentukan cara memplot banyak bentuk pada gambar yang sama setelah saya berhasil memisahkan bentuk? Jika saya menggunakan plt.plot (listx, listy) untuk setiap bentuk, ia terus menghasilkan angka baru setiap kali, alih-alih menggunakan angka yang sama.
statBeginner

Jawaban:


10

Saya akan menyerahkan kepada Anda cara mengumpulkan bentuk tetapi ini adalah prinsipnya

import numpy as np
from matplotlib import pyplot as p  #contains both numpy and pyplot
x1 = [-1,-1,10,10,-1]; y1 = [-1,10,10,-1,-1]
x2 = [21,21,29,29,21]; y2 = [21,29,29,21,21]
shapes = [[x1,y1],[x2,y2]]
for shape in shapes:
  x,y = shape
  p.plot(x,y)
p.show()

oh .. ingin tahu bagaimana saya melewatkan itu. saya mendapatkan bentuk dicetak dalam warna berbeda.
Harus

bagaimana cara mendapatkan atau mengisolasi bentuk yang berbeda?
FaCoffee

15

Untuk referensi di masa mendatang, inilah solusi yang saya gunakan setelah mengikuti saran di atas.

import shapefile as shp  # Requires the pyshp package
import matplotlib.pyplot as plt

sf = shp.Reader("test.shp")

plt.figure()
for shape in sf.shapeRecords():
    x = [i[0] for i in shape.shape.points[:]]
    y = [i[1] for i in shape.shape.points[:]]
    plt.plot(x,y)
plt.show()

Angka yang dihasilkan akan sangat berwarna, tetapi kemudian, Anda hanya perlu menyesuaikan kata kunci plot.


6
Saya tahu ini mungkin informasi yang berlebihan, tetapi bagi mereka yang belum akrab dengan subjek, akan berguna untuk mengatakan bahwa import shapefilemerujuk pada pyshppaket: pypi.python.org/pypi/pyshp
FaCoffee

Ini tidak ok ketika Anda memiliki banyak pulau, karena titik-titik ini akan dihubungkan oleh garis ke titik di daratan, menciptakan sesuatu yang mirip dengan apa yang diposting OP.
FaCoffee

1
@FaCoffee, Anda benar. Jawaban saya gis.stackexchange.com/a/309780/126618 harus mengatasi ini.
Gus

7

Anda perlu menggunakan jalur dan tambalan matplotlib dan ada modul Python yang didedikasikan untuk memplot poligon dari shapefile menggunakan fungsi-fungsi ini Descartes .

Karena Pyshp (shapefile) memiliki konvensi geo_interface ( geo_interface baru untuk PyShp ), Anda dapat menggunakannya.

polys  = shapefile.Reader("polygon")
# first polygon
poly = polys.iterShapes().next().__geo_interface__
print poly
{'type': 'Polygon', 'coordinates': (((151116.87238259654, 135890.8706318218), (153492.19971554304, 134793.3055883224), (153934.50204650551, 133892.31935858406), (152623.97662143156, 131811.86024627919), (150903.91200102202, 130894.49244872745), (149347.66305874675, 132991.33312884573), (149151.08424498566, 134383.76639298678), (151116.87238259654, 135890.8706318218)),)}

Hasilnya adalah representasi GeoJSON dari geometri dan Anda dapat menggunakan solusi Cara memplot data geo menggunakan matplotlib / python

import matplotlib.pyplot as plt 
from descartes import PolygonPatch
BLUE = '#6699cc'
fig = plt.figure() 
ax = fig.gca() 
ax.add_patch(PolygonPatch(poly, fc=BLUE, ec=BLUE, alpha=0.5, zorder=2 ))
ax.axis('scaled')
plt.show()

masukkan deskripsi gambar di sini


Itu sangat membantu, tetapi bisakah Anda melakukan ini dalam for for loop jika Anda memiliki beberapa poligon untuk plot?
FaCoffee

Ya tanpa masalah
gen

Saya perhatikan bahwa descartessolusinya tidak berfungsi jika Anda mencoba dan memplot dua shapefile berbeda pada dua subplot yang berdekatan menggunakan fig, ax = plt.subplots(1,2,figsize=(15, 8))dan kemudian ax[0].add_patch(PolygonPatch(poly_geo, fc='#d3d3d3', ec='#000000', alpha=0, zorder=5))dan ax[1].add_patch(PolygonPatch(poly_geo, fc='#d3d3d3', ec='#000000', alpha=0, zorder=5)). Hasilnya adalah gambar kosong. Ada ide?
FaCoffee

2

Ini dapat dilakukan dengan menggunakan geopanda atau pyshp seperti yang dibahas dalam jawaban ini . Geopanda menggunakan matplotlib di bagian belakangnya untuk merencanakan.


2

Selain jawaban ldocao, dan menanggapi pertanyaan FaCoffee. Ketika Anda memiliki pulau-pulau terpencil dan mereka adalah bagian dari fitur yang sama, Anda dapat mencoba berikutnya:

import shapefile as shp
import matplotlib.pyplot as plt

sf = shp.Reader("test.shp")

plt.figure()
for shape in sf.shapeRecords():
    for i in range(len(shape.shape.parts)):
        i_start = shape.shape.parts[i]
        if i==len(shape.shape.parts)-1:
            i_end = len(shape.shape.points)
        else:
            i_end = shape.shape.parts[i+1]
        x = [i[0] for i in shape.shape.points[i_start:i_end]]
        y = [i[1] for i in shape.shape.points[i_start:i_end]]
        plt.plot(x,y)
plt.show()

Ini membuatnya bekerja untuk saya. Propertie "bagian" dari suatu bentuk mengembalikan indeks awal geometri differents di dalam fitur.


0

Namun, dalam satu bentuk shapefile, mungkin ada beberapa bagian. Ini akan memplot setiap bagian dalam satu bentuk, secara terpisah.

import matplotlib.pyplot as plt
import shapefile
import numpy as np

this_shapefile = shapefile.Reader(map_file_base) # whichever file
shape = this_shapefile.shape(i) # whichever shape
points = np.array(shape.points)

intervals = list(shape.parts) + [len(shape.points)]

ax = plt.gca()
ax.set_aspect(1)

for (i, j) in zip(intervals[:-1], intervals[1:]):
    ax.plot(*zip(*points[i:j]))
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.