GIS奮闘記

元GISエンジニアの技術紹介ブログ。主にPythonを使用。

スポンサーリンク

PyShp を使って CSV をシェープファイルに変換する方法

さて、本日は久しぶりに GIS に関するエントリーを書いてみようと思います。PyShp を使って CSV をシェープファイルに変換してみます。

PyShp とは

Shape ファイルを読み書きするためのライブラリです。

使用するデータ

ESRIジャパンさんが主催した「ArcGIS 開発者のための最新アプリ開発塾 2020」で使用された 各店舗売上.csvを使用します。

community.esri.com

CSV の中身はこんな感じになっています。

f:id:sanvarie:20200930145007p:plain

使用するライブラリ

PyShp と Pandas を使用するのでインストールをお願いします。

実行環境

Windows 10 64bit
Python 3.6.10
Pandas 1.1.2
PyShp 2.1.2
ArcGIS Pro 2.6(作成した Shape ファイルの確認用に使用)

サンプルコード

PyShp を使って CSV をシェープファイルに変換するサンプルです

# -*- coding: utf-8 -*-
import shapefile
import pandas as pd

# 読み込むCSV
input_file = r"D:\python\data\csv\各店舗売上.csv"

# CSV 読込
df = pd.read_csv(input_file, encoding="SHIFT-JIS")

# CSV のカラムを取得
column_list = df.columns.values

def create_shape():

    with shapefile.Writer(r'D:\python\data\pyshp\各店舗売上.shp') as w:

        # Shape のフィールドを作成
        for column in column_list:
            if column == "緯度":
               w.field(column, "F", 12, 6)
            elif column == "経度":
                w.field(column, "F", 12, 6)
            else:
                w.field(column, "C", 50)

        for _, row in df.iterrows():

            lat = 0
            lon = 0
            attributes = []

            for column in column_list:

                if column == "緯度":
                    lat = row[column]
                    attributes.append(lat)

                elif column == "経度":
                    lon = row[column]
                    attributes.append(lon)

                else:
                    attributes.append(row[column])

            # ポイントを作成
            w.point(lon, lat)
            w.record(attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7])

    # プロジェクションファイル作成
    with open("%s.prj" % r'D:\python\data\pyshp\各店舗売上', "w") as prj:
        epsg = 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]]'
        prj.write(epsg)

if __name__ == '__main__':
    create_shape()

結果をみるとばっちりシェープファイルが作成されたことがわかります。属性もしっかり付与されてますね。

f:id:sanvarie:20200930200901p:plain

PyShp のいいところ

GDAL や Fiona などで同じことをやろうとすると以下エントリーのように日本語でひっかかるのですが、PyShp の場合はその問題は起きないのが素晴らしいですね。

www.gis-py.com

PyShp のいまいちなところ

属性を作成する際に、w.record(attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7]) のようにしなければならないのがいまいちかなと思います(他のやり方があるのかもしれませんが・・・)。この仕様だと汎用的には使えないですね。

解決策

コメント欄参照

最後に

ArcGIS のような商用 GIS を使用すればシェープファイルの作成なんて簡単にできてしまいますが、高価な製品なので簡単には購入できません。シェープファイルが欲しいけど、フリーのライブラリで何とかしたいという方はぜひ PyShp を使ってみてください。本日は以上です。