QGISバッチ処理入門【複数ファイルの一括処理】
目次
同じ処理を複数のファイルに適用したいとき、バッチ処理が便利です。
この記事では、QGISでバッチ処理を行う方法を解説します。
バッチ処理とは
概要
バッチ処理 = 複数のデータに同じ処理を一括で適用すること
【手動処理】
ファイル1 → 処理 → 出力1
ファイル2 → 処理 → 出力2
ファイル3 → 処理 → 出力3
→ 時間がかかる、ミスが起きやすい
【バッチ処理】
[ファイル1, 2, 3] → 一括処理 → [出力1, 2, 3]
→ 効率的、確実
活用シーン
| シーン | 処理内容 |
|---|---|
| 座標系変換 | 複数ファイルをまとめて変換 |
| バッファ作成 | 複数レイヤにバッファを作成 |
| 形式変換 | シェープファイル→GeoPackage |
| 属性計算 | 全ファイルの面積を計算 |
処理ツールのバッチ実行
バッチ処理の起動
1. プロセシング → ツールボックス
2. 使いたいツールを右クリック
3. 「バッチ処理として実行」
バッチ処理画面
┌────────────────────────────────────────────┐
│ パラメータ1 パラメータ2 出力 │
├────────────────────────────────────────────┤
│ 入力1 100 出力1.shp │
│ 入力2 100 出力2.shp │
│ 入力3 100 出力3.shp │
├────────────────────────────────────────────┤
│ [行を追加] [自動入力] [実行] │
└────────────────────────────────────────────┘
入力ファイルの一括追加
1. 「入力」列のセルをダブルクリック
2. ファイル選択ダイアログ
3. 複数ファイルを選択(Ctrl+クリック)
4. 各行に自動で展開される
出力ファイル名の自動生成
出力列で「自動入力」を使用:
・入力ファイル名をベースに自動生成
・接頭辞/接尾辞を追加可能
例:
入力:data.shp
出力:data_buffered.shp
PyQGISでのバッチ処理
基本パターン
import os
import processing
input_folder = "C:/data/input"
output_folder = "C:/data/output"
# フォルダ内のシェープファイルを処理
for filename in os.listdir(input_folder):
if filename.endswith(".shp"):
input_path = os.path.join(input_folder, filename)
output_name = filename.replace(".shp", "_processed.shp")
output_path = os.path.join(output_folder, output_name)
# 処理を実行
processing.run("native:buffer", {
'INPUT': input_path,
'DISTANCE': 100,
'OUTPUT': output_path
})
print(f"処理完了: {filename}")
print("すべての処理が完了しました")
複数の処理を連続実行
def process_file(input_path, output_folder):
filename = os.path.basename(input_path)
name = os.path.splitext(filename)[0]
# 処理1: 座標系変換
reprojected = processing.run("native:reprojectlayer", {
'INPUT': input_path,
'TARGET_CRS': 'EPSG:6677',
'OUTPUT': 'memory:'
})['OUTPUT']
# 処理2: バッファ
buffered = processing.run("native:buffer", {
'INPUT': reprojected,
'DISTANCE': 50,
'OUTPUT': 'memory:'
})['OUTPUT']
# 処理3: 出力
output_path = os.path.join(output_folder, f"{name}_result.gpkg")
processing.run("native:savefeatures", {
'INPUT': buffered,
'OUTPUT': output_path
})
return output_path
# バッチ実行
for filepath in glob.glob("C:/data/*.shp"):
result = process_file(filepath, "C:/output")
print(f"完了: {result}")
実践的なバッチ処理例
例1: 座標系一括変換
import os
import processing
def batch_reproject(input_folder, output_folder, target_crs):
"""複数ファイルの座標系を一括変換"""
os.makedirs(output_folder, exist_ok=True)
for filename in os.listdir(input_folder):
if filename.endswith(('.shp', '.gpkg', '.geojson')):
input_path = os.path.join(input_folder, filename)
output_path = os.path.join(output_folder, filename)
try:
processing.run("native:reprojectlayer", {
'INPUT': input_path,
'TARGET_CRS': target_crs,
'OUTPUT': output_path
})
print(f"✓ {filename}")
except Exception as e:
print(f"✗ {filename}: {e}")
# 実行
batch_reproject(
"C:/data/input",
"C:/data/output_epsg6677",
"EPSG:6677"
)
例2: シェープファイル→GeoPackage変換
import os
import processing
def shp_to_gpkg(input_folder, output_gpkg):
"""複数シェープファイルを1つのGeoPackageに統合"""
for filename in os.listdir(input_folder):
if filename.endswith(".shp"):
input_path = os.path.join(input_folder, filename)
layer_name = os.path.splitext(filename)[0]
options = QgsVectorFileWriter.SaveVectorOptions()
options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
options.layerName = layer_name
layer = QgsVectorLayer(input_path, layer_name, "ogr")
QgsVectorFileWriter.writeAsVectorFormatV3(
layer,
output_gpkg,
QgsCoordinateTransformContext(),
options
)
print(f"追加: {layer_name}")
# 実行
shp_to_gpkg("C:/data/shapefiles", "C:/data/combined.gpkg")
例3: 面積・長さの一括計算
import os
def calculate_geometry_batch(input_folder, field_name, calc_type):
"""複数ファイルのジオメトリを計算して属性に追加"""
for filename in os.listdir(input_folder):
if filename.endswith(".gpkg"):
filepath = os.path.join(input_folder, filename)
layer = QgsVectorLayer(filepath, filename, "ogr")
if not layer.isValid():
continue
# フィールド追加
layer.startEditing()
if field_name not in [f.name() for f in layer.fields()]:
layer.addAttribute(QgsField(field_name, QVariant.Double))
layer.updateFields()
field_index = layer.fields().indexOf(field_name)
# 計算
for feature in layer.getFeatures():
if calc_type == "area":
value = feature.geometry().area()
elif calc_type == "length":
value = feature.geometry().length()
else:
value = 0
layer.changeAttributeValue(feature.id(), field_index, value)
layer.commitChanges()
print(f"計算完了: {filename}")
# 実行(面積計算)
calculate_geometry_batch("C:/data", "calc_area", "area")
エラーハンドリング
基本的なエラー処理
import traceback
def safe_batch_process(input_folder, output_folder):
"""エラーが発生しても処理を継続"""
success = []
failed = []
for filename in os.listdir(input_folder):
if filename.endswith(".shp"):
input_path = os.path.join(input_folder, filename)
output_path = os.path.join(output_folder, filename)
try:
processing.run("native:buffer", {
'INPUT': input_path,
'DISTANCE': 100,
'OUTPUT': output_path
})
success.append(filename)
except Exception as e:
failed.append({
'file': filename,
'error': str(e),
'traceback': traceback.format_exc()
})
# 結果サマリ
print(f"\n=== 処理結果 ===")
print(f"成功: {len(success)}件")
print(f"失敗: {len(failed)}件")
if failed:
print("\n失敗したファイル:")
for f in failed:
print(f" - {f['file']}: {f['error']}")
return success, failed
入力検証
def validate_input(filepath):
"""入力ファイルの検証"""
if not os.path.exists(filepath):
raise FileNotFoundError(f"ファイルが見つかりません: {filepath}")
layer = QgsVectorLayer(filepath, "test", "ogr")
if not layer.isValid():
raise ValueError(f"無効なレイヤ: {filepath}")
if layer.featureCount() == 0:
raise ValueError(f"フィーチャがありません: {filepath}")
return True
ログと進捗管理
ログファイルの出力
import logging
from datetime import datetime
def setup_logging(log_folder):
"""ログ設定"""
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
log_file = os.path.join(log_folder, f"batch_{timestamp}.log")
logging.basicConfig(
filename=log_file,
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
return logging.getLogger()
# 使用例
logger = setup_logging("C:/logs")
logger.info("バッチ処理開始")
logger.info(f"処理完了: {filename}")
logger.error(f"エラー: {error}")
プログレス表示
def batch_with_progress(input_files, output_folder):
"""プログレス付きバッチ処理"""
total = len(input_files)
for i, filepath in enumerate(input_files):
progress = (i + 1) / total * 100
print(f"\r処理中: {progress:.1f}% ({i+1}/{total})", end="")
# 処理
process_file(filepath, output_folder)
print("\n完了!")
まとめ
バッチ処理のポイント
1. 処理ツールの「バッチ処理として実行」が簡単
2. 複雑な処理はPyQGISで
3. エラーハンドリングを忘れずに
4. ログを残して追跡可能に
チェックリスト
□ 入力ファイルの形式・座標系を確認
□ 出力先フォルダを準備
□ テストデータで動作確認
□ エラー処理を実装
□ ログを記録
参考・一次情報
- QGIS「The batch processing interface」 — 複数入力、値の自動入力、出力名の設定、実行ログを含む公式バッチ処理手順です。
- QGIS「Using processing algorithms from the console」 — PyQGISによるアルゴリズム実行、エラー通知、進捗・キャンセル処理の公式資料です。
- QGIS「Using processing from the command line」 — デスクトップを起動せず
qgis_processで処理を自動実行する公式手順です。
関連記事
お問い合わせ
バッチ処理の自動化についてのご相談は、お気軽にお問い合わせください。
最終更新: 2025年1月