Pythonを使用してポリゴンフィーチャの重心をポイントに変換する


9

複数のポリゴンフィーチャを含むいくつかのポリゴンベースのshpファイルを、基本的に各ポリゴンフィーチャの中心点を表す各フィーチャのポイントに変換したいと思います。ArcGISの世界ではFeature To Pointツールを使用できることはわかっていますが、これをArcpyがインストールされていないPCで実行できるスクリプトに保持したいので、それに代わるオープンソースを探しています。私がこれに使用できるライブラリと、それをどのように活用してこれを達成するかについての方向性を知っている人はいますか?


Geneが以下に提供する回答にはまだ複数の問題があります。問題は、属性を元の順序からアルファベット順に並べ替える方法です。これが問題です。2番目に、シェイプファイルは、250を超える属性を持つ変換しようとしているファイルが原因で破損している可能性があります。
wilbev 2017年

QGISには、これを正確に実行する「Polygon Centroids」という標準ツールがあります。スクリプトが必要ですか?PyQGISを使用してスクリプトを作成するのは簡単だと思います。
DUNカーン

スクリプトであり、QGISがインストールされていないPCで動作する必要があります。
wilbev 2017年

回答:


9

ogr2ogrコマンドを実行できます(たとえば、OSGeo4wシェルから)。たとえば、国のシェープファイル:

cd path/to/shapefiles
ogr2ogr -sql "SELECT ST_Centroid(geometry), * FROM countries" -dialect sqlite countries_centroid.shp countries.shp

新しいシェープファイルcountries_centroid.shpは入力に似ているはずですが、[Multi] Polygonご​​とに1つのポイントしか含まれていません。

@PELは、ST_PointOnSurfaceの良い例も示しています。これは、このコマンドで簡単に置き換えることができます。


必要に応じて、Pythonでも同様のことができますが、数行のコードがさらに必要になる場合があります。

import os
from osgeo import ogr

ogr.UseExceptions()
os.chdir('path/to/shapefiles')

ds = ogr.Open('countries.shp')
ly = ds.ExecuteSQL('SELECT ST_Centroid(geometry), * FROM countries', dialect='sqlite')
drv = ogr.GetDriverByName('Esri shapefile')
ds2 = drv.CreateDataSource('countries_centroid.shp')
ds2.CopyLayer(ly, '')
ly = ds = ds2 = None  # save, close

私は、OGRとSQLを使用した、最も簡単なソリューションを提案したと思います。-nltポイントを使用してOGRにパラメーターを追加する方が安全だと思います
PEL

残念ながら、これを機能させることはできません。ST_Centroidが機能していないというエラーメッセージが表示されます。
wilbev 2017年

1
SQLite方言オプション(図を参照)とGDALに組み込まれたSpatialiteが必要ですが、これは常に保証されているわけではありません。OSGeo4Wには、このコマンドを正しく実行するGDALの適切なバージョンがあります。
Mike T

ogr2ogr内のトップスクリプトを問題なく機能させることができます。ただし、スタンドアロンのPythonスクリプトでこれを行う必要があるので、2番目のコードセットを機能させようとしています。これは、ST_Centroidを続行しても、関数エラーではないためです。私のコードは、sqlite方言を含む上記のものと同じです。
wilbev 2017年

1
あなたが説明するエラーは、GDALがSpatialiteサポートなしでビルドされたときです。一部のgdal-pythonパッケージはこれをサポートしていますが、すべてをサポートしているわけではありません。OSGeo4Wシェルを開いて、その環境からPythonスクリプトを実行してみてください。関連するデフォルトのパッケージセットにgdal-binは、このサポートが含まれていると思います。
Mike T

9

FionaまたはGeoPandas(Python 2.7.xおよび3.x)を使用するだけです

一部のポリゴン

ここに画像の説明を入力してください

import geopandas as gpd
# GeoDataFrame creation
poly = gpd.read_file("geoch_poly.shp")
poly.head()

ここに画像の説明を入力してください

ポイントへの変換(図心)

# copy poly to new GeoDataFrame
points = poly.copy()
# change the geometry
points.geometry = points['geometry'].centroid
# same crs
points.crs =poly.crs
points.head()

ここに画像の説明を入力してください

# save the shapefile
points.to_file('geoch_centroid.shp')

結果

ここに画像の説明を入力してください


回答遺伝子をありがとう。points.crs = gdf.crsコードの 'gdf'変数が 'poly'であるはずの上の1つのタイプミスがあると思います。.prjファイルが取得されない他のいくつかの問題も発生しています作成され、空で表示され、属性フィールドの順序は、アルファベット順のように見えるため、ポリゴンデータからの順序が変更されています。それらが同じ順序であることが重要です。フィールド属性を同じに保つ方法を知っています。注文?
wilbev 2016年

ありがとう、修正しました。属性フィールドの順序は、GeoPandas GeoDataFrame(= Pandas DataFrame)の順序を変更するだけ
gene

Geneに感謝しますが、ここのコードでその順序をどこで変更するのかわかりません。これに関して他にも2つの問題が発生しています。最初に、*。prjファイルは新しいshpファイルでは空白です。次に、shpリーダーでshpファイルを開こうとすると、ファイルが破損しているようにファイルを開くときにエラーが発生します。shpファイルに単一の機能しかない場合でも、破損することなく機能するようですが、複数の問題が発生しているようです。
wilbev 2016年

申し訳ありませんが、そのためにパンダを知る必要があります。私は自分のデータを含むスクリプトに問題がありません (私はGeoPandas、Fiona、Numpyの最新バージョンを使用しています)
gene

自分で確認できるように、shpファイルを送信できますが、このshpファイルには、問題が生じていると思われる250列を超えるデータが含まれています。属性をはるかに少なくしたshpファイルでこれを試してみましたが、問題はないようです。
wilbev 2016年

5

別の、おそらくより「低レベル」の方法は、直接使用fionaしてshapely、I / Oおよびジオメトリ処理に使用することです。

import fiona
from shapely.geometry import shape, mapping

with fiona.open('input_shapefile.shp') as src:
    meta = src.meta
    meta['schema']['geometry'] = 'Point'
    with fiona.open('output_shapefile.shp', 'w', **meta) as dst:
        for f in src:
            centroid = shape(f['geometry']).centroid
            f['geometry'] = mapping(centroid)
            dst.write(f)

ロイックありがとう。それは間違いなく私が抱えていた並べ替えの問題を修正しますが、ファイルが破損する原因となっている非常に多くの属性の問題を修正していません。その問題を克服する方法について他に何かアイデアはありますか?属性を削除する必要があるかもしれませんね。参考になれば、サンプルファイルをお送りします。
wilbev 2017年

@wilbev可能であれば、データへのダウンロードリンクを送信します。そうでなければ私は何が間違っているのかわかりません。
ロイックDutrieux

ロイック、私はあなたにサンプルファイルをメールで送った。うまくいけば、私が遭遇している問題についての良い考えが得られます。
wilbev 2017年

@wilbev「ファイルが破損した」とはどういう意味ですか?送信したファイルを使用して、重心を作成し、出力シェープファイルをQGISで問題なく開くことができました。属性テーブルは、両方のファイル間で変更されません。
ロイックDutrieux

破損するとは、スクリプトを実行すると1 KBサイズのdbfファイルが作成され、開くと完全に空であるため、基本的には空のdbfファイルであることを意味します。上記と同じスクリプトを、属性の少ないファイルで実行すると、問題なく動作します。2台目のPCで試しても、同じ結果が得られました。わかりません。
wilbev 2017年

2

最も簡単な方法は、gdal / ogr Virtual Formatを使用することだと思います。(http://www.gdal.org/drv_vrt.html)およびSQL / SQLITE方言(http://www.gdal.org/ogr_sql.htmlおよびhttps://www.gaia-gis.it/spatialite-3.0 .0-BETA / spatialite-sql-3.0.0.html

私のポリゴンシェープファイルの名前はpoly.shpです。次に、このXMLのようなファイルをvrt.vrtという名前で作成します。このファイル(vrt.vrt)内で、ポイントに変換するコンテンツ

<OGRVRTDataSource>
    <OGRVRTLayer name="poly">
        <SrcDataSource relativeToVRT="1">poly.shp</SrcDataSource>
        <SrcSQL dialect="sqlite">SELECT ST_PointOnSurface(geometry) as geom_point, poly.* from poly</SrcSQL>
        <GeometryType>wkbPoints</GeometryType> 
        <GeometryField name="geom_point" />
    </OGRVRTLayer>
</OGRVRTDataSource>

現時点では、このファイルをQgisに統合して検証できます。確かに、すべての機能はすべてのレンダリングクエリでポイントとしてキャストされるため、レンダリングはrawソースよりも遅くなります。

その後、Pythonシェル/スクリプトからgdal / ogr utilsを使用して、このファイル(vrt.vrt)を別のファイルに変換します

os.system("ogr2ogr point_from_vrt.shp vrt.vrt poly")

point_from_vrt.shpという名前のポイントシェープファイルを取得します。


私はこれを機能させることができましたが、すべて異なるファイル名の数百のファイルを変換する必要があるため、すべてをpythonスクリプト内に保持したいと考えています。@Mike Tソリューションを使用したいのですが、「そのような関数はありません。ST_Centroidを使用し、ST_PointOnSurfaceも試した場合、そのような関数はない」と表示されます。これらがExecuteSQLの関数ではないことを示す理由は何ですか? ()?
wilbev 2017年

私が得る'wkbPoints' is not a valid value of the atomic type
ベン・シンクレア
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.