Vẽ shapefile với matplotlib


13

Tôi đang cố gắng đọc một shapefile và vẽ nó bằng matplotlib. Đây là mã:

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

Tuy nhiên, tôi nhận được các đường kết nối đa giác của tôi. Làm thế nào tôi có thể vẽ các đa giác sao cho chúng là cách trong shapefile. Dưới đây là ảnh chụp màn hình của cốt truyện và shapefile khi nó được mở bằng ArcGIS.Tạo theo mã Tập tin thực tế


Không quen thuộc với trình đọc shapefile, tuy nhiên tôi có thể nói rằng bạn chỉ nối tất cả các điểm trong tệp vào một danh sách lớn mà không tách từng hình thành các phần thành phần của nó. Bạn cần một danh sách lớn các hình dạng mà bạn nối thêm từng điểm hình

Đúng. Phải tìm cách tách các hình dạng. Nhưng đó là những gì tôi không thể làm vào lúc này.
statBeginner

@DanPatterson Bạn có thể chỉ định cách vẽ nhiều hình trong cùng một hình sau khi tôi quản lý để tách các hình không? Nếu tôi sử dụng plt.plot (listx, listy) cho mọi hình dạng, nó sẽ tiếp tục tạo ra một hình mới mỗi lần, thay vì sử dụng cùng một hình.
statBeginner

Câu trả lời:


10

Tôi sẽ để lại cho bạn cách thu thập các hình dạng nhưng đây là nguyên tắc

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 .. tự hỏi làm thế nào tôi bỏ lỡ điều đó. tôi nhận được các hình dạng in màu khác nhau mặc dù. Sẽ phải sửa nó :)
statBeginner

Làm thế nào để có được hoặc cô lập các hình dạng khác nhau?
FaCoffee

15

Để tham khảo trong tương lai, đây là giải pháp tôi đã tìm đến sau khi làm theo những lời khuyên ở trên.

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

Con số kết quả sẽ rất nhiều màu sắc, nhưng sau đó, bạn chỉ cần điều chỉnh các từ khóa cốt truyện.


6
Tôi biết đây có thể là thông tin dư thừa, nhưng đối với những người chưa quen thuộc với chủ đề này, sẽ rất hữu ích khi nói import shapefileđến pyshpgói đó: pypi.python.org/pypi/pyshp
FaCoffee 15/2/2017

Điều này không ổn khi bạn có một loạt các hòn đảo, vì những điểm này sẽ được kết nối bằng các đường đến các điểm trên đất liền, tạo ra một cái gì đó tương tự như những gì OP đăng.
FaCoffee

1
@FaCoffee, bạn nói đúng. Câu trả lời của tôi gis.stackexchange.com/a/309780/126618 nên giải quyết điều này.
Gus

7

Bạn cần sử dụng các đường dẫnbản vá matplotlib và có một mô-đun Python dành riêng để vẽ đa giác từ các shapefile bằng các hàm Descartes này .

Vì Pyshp (shapefile) có quy ước Geo_interface ( New Geo_interface cho PyShp ), bạn có thể sử dụng nó.

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

Kết quả là biểu diễn GeoJSON của hình học và bạn có thể sử dụng giải pháp Cách vẽ biểu đồ dữ liệu địa lý bằng 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()

nhập mô tả hình ảnh ở đây


Điều đó thực sự hữu ích, nhưng bạn có thể làm điều này trong một vòng lặp for nếu bạn có nhiều đa giác để vẽ không?
FaCoffee

Có mà không có vấn đề
gen

Tôi nhận thấy rằng descartesgiải pháp không hoạt động nếu bạn thử và vẽ hai shapefile khác nhau trên hai ô con liền kề bằng cách sử dụng fig, ax = plt.subplots(1,2,figsize=(15, 8))và sau đó ax[0].add_patch(PolygonPatch(poly_geo, fc='#d3d3d3', ec='#000000', alpha=0, zorder=5))ax[1].add_patch(PolygonPatch(poly_geo, fc='#d3d3d3', ec='#000000', alpha=0, zorder=5)). Kết quả là một hình ảnh trống rỗng. Bất kỳ ý tưởng?
FaCoffee

2

Nó có thể được thực hiện bằng cách sử dụng geopandas hoặc pyshp như được thảo luận trong câu trả lời này . Geopandas sử dụng matplotlib ở phần cuối của nó để vẽ.


2

Ngoài câu trả lời ldocao, và trả lời câu hỏi FaCoffee. Khi bạn có các đảo bị cô lập và chúng là một phần của cùng một tính năng, bạn có thể thử tiếp theo:

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

Điều này làm cho nó làm việc cho tôi. Các "bộ phận" của hình dạng trả về các chỉ mục bắt đầu của hình học khác biệt bên trong một tính năng.


0

Tuy nhiên, trong một hình dạng shapefile, có thể có nhiều phần. Điều này sẽ vẽ từng phần trong một hình dạng, riêng biệt.

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]))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.