matplotlibでシェープファイルをプロットする


13

シェープファイルを読み取り、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で開いたときのプロットとシェープファイルのスクリーンショットです。コードによって生成 実際のファイル


シェープファイルリーダーに慣れていませんが、各シェイプをコンポーネントパーツに分割せずに、ファイル内のすべてのポイントを1つの大きなリストに追加しているだけであることがわかります。各図形ポイントを追加する図形の大きなリストが必要です

正しい。図形を分離する方法を見つける必要があります。しかし、それは現時点ではできません。
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

島がたくさんある場合、これらのポイントは本土のポイントに線で接続され、OPが投稿したものと同様の何かを作成するため、これは大丈夫ではありません。
FaCoffee

1
@FaCoffee、あなたは正しい。私の答えgis.stackexchange.com/a/309780/126618はこれに対処する必要があります。
ガス

7

matplotlibのパスパッチを使用する必要があり、これらの関数を使用してシェープファイルからポリゴンをプロットするためのPythonモジュールがあります Descartes

Pyshp(シェープファイル)にはgeo_interfacePyShpの新しいgeo_interface)規則があるため、これを使用できます。

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

はい、問題なし
遺伝子

and then とdescartesを使用してfig, ax = plt.subplots(1,2,figsize=(15, 8))、2つの隣接するサブプロットに2つの異なるシェープファイルをプロットしようとすると、ソリューションが機能しないことに気付きました。結果は空の画像です。何か案が?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

2

この回答で説明したように、geopandasまたはpyshpを使用して実行できます。Geopandasは、プロットのためにバックエンドでmatplotlibを使用します。


2

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

これは私のために動作します。シェイプのプロパティ「パーツ」は、フィーチャ内の異なるジオメトリの開始インデックスを返します。


0

それでも、1つのシェープファイルシェイプには、複数のパーツがある場合があります。これにより、1つの形状内の各パーツが個別にプロットされます。

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]))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.