Сформіть графік сюжету з matplotlib


15

Я намагаюся прочитати файл форми і побудувати його за допомогою matplotlib. Ось код:

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

Однак я отримую лінії, що з'єднують мої багатокутники. Як я можу намалювати багатокутники так, щоб вони були способом у файлі форм. Ось скріншоти сюжету та файл форми, коли він відкривається за допомогою ArcGIS.Породжений кодом Фактичний файл


Не знайомий з читачем формфайлів, проте можу сказати, що ви просто додаєте всі точки файлу до одного великого списку, не розділяючи кожну фігуру на її складові частини. Вам потрібен великий список фігур, до яких ви додаєте очки кожної фігури

Правильно. Доведеться знайти спосіб відокремити фігури. Але це я зараз не в змозі зробити.
statBeginner

@DanPatterson Чи можете ви вказати, як побудувати кілька фігур на одній фігурі після того, як мені вдасться розділити фігури? Якщо я використовую plt.plot (listx, listy) для кожної форми, вона продовжує генерувати нову фігуру кожен раз, замість того, щоб використовувати ту саму фігуру.
statBeginner

Відповіді:


10

Я залишу вам, як збирати фігури, але це принцип

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

о .. дивно, як я пропустив це. Я отримую форми, надруковані в різних кольорах, хоча. Доведеться це виправити :)
statBeginner

як отримати або виділити різні фігури?
FaCoffee

15

Для подальших посилань, ось таке рішення, до якого я прийшов після виконання рекомендацій, наведених вище.

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

Отримана цифра буде дуже барвистою, але тоді вам просто потрібно відкоригувати ключові слова сюжету.


6
Я знаю, що це може бути зайвою інформацією, але для тих, хто ще не знайомий з темою, було б корисно сказати, що import shapefileйдеться про pyshpпакет: pypi.python.org/pypi/pyshp
FaCoffee

Це не нормально, коли у вас є купа островів, оскільки ці точки будуть з'єднані лініями з точками на материку, створюючи щось подібне до того, що розміщено в ОП.
FaCoffee

1
@FaCoffee, ти маєш рацію. Моя відповідь gis.stackexchange.com/a/309780/126618 повинна відповісти на це.
Гас

9

Вам потрібно використовувати шляхи та патчі matplotlib, і є модуль Python, призначений для побудови полігонів із форм-файлів за допомогою цих функцій Декарт .

Оскільки Pyshp (shapefile) має конвенцію geo_interface ( Новий геоінтерфейс для PyShp ), ви можете використовувати його.

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

Результатом є представлення геометрії GeoJSON, і ви можете використовувати рішення Як побудувати геодані за допомогою 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()

введіть тут опис зображення


Це дійсно корисно, але чи можете ви зробити це в циклі for, якщо у вас є кілька полігонів для побудови?
FaCoffee

Так без проблем
ген

Я помітив, що descartesрішення не працює, якщо ви спробуєте побудувати дві різні форми форми на двох сусідніх підскладах, використовуючи, fig, ax = plt.subplots(1,2,figsize=(15, 8))а потім 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)). В результаті виходить порожнє зображення. Будь-яка ідея?
FaCoffee

3

Окрім ldocao відповіді та відповіді на питання FaCoffee. Якщо у вас є окремі острови, і вони є частиною однієї функції, ви можете спробувати наступне:

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

Це змушує мене працювати. Власні "частини" фігури повертають початкові покажчики геометрики різниць усередині функції.


2

Це можна зробити, використовуючи геопанда або pyshp, як обговорюється у цій відповіді . Geopandas використовує matplotlib у своєму бекенде для створення графіків.


0

Але все-таки в одній фігурній формі може бути кілька частин. Це накреслить кожну частину в межах однієї форми, окремо.

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]))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.