Python地理データ処理6:OGRを使用してデータをフィルタリングする


前に書く

  フィルタリング条件により、不要な要素が破棄される可能性があります。フィルタリング条件により、特定の条件を満たす要素を選択できます。また、空間スコープによって要素を制限できるため、目的のデータを簡単に処理できます。

1.属性フィルター

  フィルタ条件には、SQLステートメントのWhere句と同様の条件ステートメントが必要です。といった:

‘Population < 50000’
‘Population = 50000’
‘Name = “Tokyo”’

  :文字列を比較するときは、文字列を引用符で囲み、クエリ文字列全体を囲む引用符とは異なることを確認する必要があります。そうしないと、構文エラーが発生します。

  オブジェクトが別の値と等しくないことをテストします。それを使用できます。=または<>、ANDまたはORステートメントを使用することもできます。

'(Population > 25000) AND (Population < 50000)'
'(Population > 50000) OR (Place_type = "County Seat")'

文1:人口が25,000を超え50,000未満の要素を選択します。
文2:人口が50,000を超えるか、Place_typeが郡庁所在地である(または両方が満たされている)要素を選択します

  NOTを使用して条件を否定し、NULLを使用して属性テーブルにnull値またはデータ値がないことを示します。

'(Population < 50000) OR NOT (Place_type = "County Seat")'
'County NOT NULL'

文1:人口が50,000未満の要素を選択するか、Place_typeが郡庁所在地の要素ではない(または両方を同時に満たす)。
文2:郡が空でない要素を選択する。

  特定の値が他の2つの値の間にあるかどうかを確認するには、BETWEEN:を使用します

'Population BETWEEN 25000 AND 50000'
'(Population > 25000) AND (Population < 50000)'

文1:人口が25,000〜50,000の要素
を選択します文2:人口が25,000〜50,000の要素も選択します。

  値が複数の異なる値と同じであるかどうかをテストします。

'Type_code IN (4, 3, 7)'
'(Type_code = 4) OR (Type_code = 3) OR (Type_code = 7)'

  文字列にも適用されます。

'Place_type IN ("Populated Place", "County Seat")'

  アンダースコアは任意の1文字に一致し、パーセント記号は任意の数の文字に一致します。文字列の一致にはLIKEを使用します(大文字と小文字は区別されません)。

'Name LIKE "%Seattle%"'

  LIKE演算子を使用したマッチングの例:

一致 ミスマッチ
_eattle シアトル Seattle WA
シアトル% Seattle, Seattle WA ノースシアトル
%シアトル% シアトル、ワシントン州シアトル、ノースシアトル タコマ
海%ル シアトル Seattle WA
Sea_le シアトル(スペルミスに注意) シアトル

  Pythonインタラクティブウィンドウテストを使用するには、VectorPlotterクラスをロードして、選択した結果をインタラクティブにプロットする必要があります。

>>> import os
>>> import sys
>>> from osgeo import ogr
>>> import ospybook as pb
>>> import matplotlib.pyplot as plt
>>> from ospybook.vectorplotter import VectorPlotter
>>> data_dir = r'E:\Google chrome\Download'
>>> vp = VectorPlotter(True)
>>> ds = ogr.Open(os.path.join(data_dir, 'global'))
>>> lyr = ds.GetLayer('ne_50m_admin_0_countries')# Get the countries shapefile layer
>>> vp.plot(lyr, fill=False) # fill=False表示只绘制出国家边界
>>> vp.plot(lyr, fill=False)
>>> pb.print_attributes(lyr, 4, ['name'], geom=False) # 查看图层属性

FID    name           
0      Aruba          
1      Afghanistan    
2      Angola         
3      Anguilla       
4 of 241 features

  アジアに含まれる要素を表示する:
  SetAttributeFilter()関数

import os
import sys
from osgeo import ogr
import ospybook as pb
from ospybook.vectorplotter import VectorPlotter

data_dir = r'E:\Google chrome\Download'

ds = ogr.Open(os.path.join(data_dir, 'global'))
lyr = ds.GetLayer('ne_50m_admin_0_countries')

asia=lyr.SetAttributeFilter("continent = 'Asia'")
print(asia)  # asia 为0时,表示查询语句被执行成功

count_asia=lyr.GetFeatureCount()
print(count_asia)# 亚洲总共有多少个记录

vp = VectorPlotter(True)
vp.plot(lyr, 'y')
vp.draw()
0
53

  描画結果:

ここに画像の説明を挿入します
  属性フィルターの効果を表示します。

>>> pb.print_attributes(lyr, 4, ['name'], geom=False)

FID    name                    
1      Afghanistan             
7      United Arab Emirates    
9      Armenia                 
17     Azerbaijan              
4 of 53 features

>>> lyr.GetFeature(2).GetField('name') # FID并没有改变
'Angola'

  別の属性フィルター条件を設定すると、現在のフィルターレイヤー機能のサブセットは作成されませんが、レイヤー全体にフィルター条件が適用されます。

lyr.SetAttributeFilter('continent = "South America"')
vp.plot(lyr, 'b')
5
241

ここに画像の説明を挿入します

  空間フィルター条件と属性フィルター条件の両方を使用して、結果を最適化できます。これについては後で説明します。
属性フィルター条件をクリアして、すべての要素を取得します。

>>> lyr.SetAttributeFilter(None)
0
>>> lyr.GetFeatureCount()
241

2.空間フィルター条件

  空間フィルタリング条件は、属性値の代わりに空間範囲を使用してフィーチャをフィルタリングでき、別のフィーチャまたは境界ボックス内にあるフィーチャを選択するために使用できます。
  自然地球のシェープファイルを使用して、中国の都市を選択します。まず、データソースファイルを開き、属性フィルター基準を使用して中国をフィルター処理し、対応するフィーチャレコードと幾何学的オブジェクトを取得します。

>>> from osgeo import ogr
>>> from ospybook.vectorplotter import VectorPlotter
>>> import ospybook as pb
>>> ds=ogr.Open(r"E:\Google chrome\Download\global")
>>> country_lyr = ds.GetLayer('ne_50m_admin_0_countries')
>>> vp = VectorPlotter(True)
>>> vp.plot(country_lyr, fill=False)
>>> country_lyr.SetAttributeFilter('name = "China"')
5
>>> feat = country_lyr.GetNextFeature()
>>> China = feat.geometry().Clone()

  住宅地レイヤーをオンにして、すべての都市データを赤い点で表します。

>>> city_lyr = ds.GetLayer('ne_50m_populated_places')
>>> city_lyr.GetFeatureCount()
1249
>>> vp.plot(city_lyr, 'r.')

ここに画像の説明を挿入します

# 选取中国城市
# 打开数据源文件夹获取国家边界图层,然后使用属性过滤条件筛选出中国,并获得对应的要素记录和几何对象
# 使用中国边界,根据空间过滤条件,筛选出居住区图层中的中国城市。

from osgeo import ogr
from ospybook.vectorplotter import VectorPlotter
import ospybook as pb

# 打开图层
ds=ogr.Open(r"E:\Google chrome\Download\global")
lyr=ds.GetLayer('ne_50m_admin_0_countries')

vp=VectorPlotter(True)
vp.plot(lyr,fill=False)

# 根据属性过滤条件筛选出中国
""" 属性过滤条件筛选后会返回一个要素,lyr.GetNextFeature()获得这个要素
Clone() 克隆这个要素,这样即使要素在内存中被删除后,仍然可以使用"""
country = lyr.SetAttributeFilter("name = 'China'")
feat = lyr.GetNextFeature()
China = feat.geometry().Clone()

# 加载城市图层,并绘制
city_lyr=ds.GetLayer('ne_50m_populated_places')
vp.plot(city_lyr,'r.')

# 根据空间过滤条件,筛选出中国的城市
country_filter=city_lyr.SetSpatialFilter(China)
country_count=city_lyr.GetFeatureCount()
print(country_count)
vp.plot(city_lyr,'bo')
vp.draw()

ここに画像の説明を挿入します
  空間フィルター条件と属性クエリ関数の組み合わせを使用して選択を最適化し、人口が100万人を超える都市を見つけ、正方形を使用してそれらを表します。

# 找出中国人口超过100万的城市
country_100 = city_lyr.SetAttributeFilter('pop_min > 1000000')
country_100_count = city_lyr.GetFeatureCount()
vp.plot(city_lyr, 'rs')
vp.draw()

  100万人以上の人口を持つ合計95の都市があります。

ここに画像の説明を挿入します
  世界の人口が100万人を超える都市がいくつあるかを確認します。

city_lyr.SetSpatialFilter(None)
city_lyr.GetFeatureCount()
vp.plot(city_lyr, 'm^', markersize=8)
vp.draw()

# 246

  描画結果:

ここに画像の説明を挿入します
SetSpatialFilterRect(minx、miny、maxx、maxy):空間フィルタリング用の長方形を作成します。

country_lyr.SetSpatialFilterRect(110, -50, 160, 0)
vp.plot(country_lyr, 'y')
vp.draw()

  描画結果:
ここに画像の説明を挿入します
  オーストラリアで最大の長方形を描画することは、グローバルボーダーレイヤーの空間フィルター条件として使用できます。

3.SQLを使用して一時レイヤーを作成します

  EcecuteSQL関数は主に、データソースに対してより複雑なクエリを実行するために使用されます。このクエリは、レイヤーではなくデータソースで機能し、複数のレイヤーを操作できます。空間フィルター条件は、オプション項目として使用できます。
EcecuteSQL(ステートメント、[spatialFilter]、[方言])

  1. ステートメント:使用するSQLステートメント
  2. SpatialFilter:オプション、空間フィルタリングは結果に対して実行されます。デフォルトではフィルタリングは行われません。
  3. 方言は、SQLステートメントで使用される標準文字列を説明するために使用されます。使用可能なオプションは、OGRSQLおよびSQLiteです。SQL標準がデフォルトで使用されます。

  1.返された結果を母集団の降順で並べ替えます。

ds = ogr.Open(os.path.join(data_dir, 'global'))
sql = '''SELECT ogr_geom_area as area, name, pop_est
         FROM 'ne_50m_admin_0_countries' ORDER BY POP_EST DESC'''
lyr = ds.ExecuteSQL(sql)
pb.print_attributes(lyr, 3) # 此处输出报错

  未解決の問題:

ここに画像の説明を挿入します

  initファイルは次のことを示しています。

def print_attributes(lyr_or_fn, n=None, fields=None, geom=True, reset=True):
    """Print attribute values in a layer.

    lyr_or_fn - OGR layer object or filename to datasource (will use 1st layer)
    n         - optional number of features to print; default is all
    fields    - optional list of case-sensitive field names to print; default
                is all
    geom      - optional boolean flag denoting whether geometry type is printed;
                default is True
    reset     - optional boolean flag denoting whether the layer should be reset
              - to the first record before printing; default is True
    """
    lyr, ds = _get_layer(lyr_or_fn)
    if reset:
        lyr.ResetReading()

    n = n or lyr.GetFeatureCount()
    geom = geom and lyr.GetGeomType() != ogr.wkbNone
    fields = fields or [field.name for field in lyr.schema]
    data = [['FID'] + fields]
    if geom:
        data[0].insert(1, 'Geometry')
    feat = lyr.GetNextFeature()
    while feat and len(data) <= n:
        data.append(_get_atts(feat, fields, geom))
        feat = lyr.GetNextFeature()
    lens = map(lambda i: max(map(lambda j: len(str(j)), i)), zip(*data))
    format_str = ''.join(map(lambda x: '{
    
    {:<{}}}'.format(x + 4), lens))
    for row in data:
        try:
            print(format_str.format(*row))
        except UnicodeEncodeError:
            e = sys.stdout.encoding
            print(codecs.decode(format_str.format(*row).encode(e, 'replace'), e))
    print('{0} of {1} features'.format(min(n, lyr.GetFeatureCount()), lyr.GetFeatureCount()))
    if reset:
        lyr.ResetReading()
        

  シェープファイルファイルにはSQLエンジンが組み込まれていません。クエリ対象のデータソースにSQLエンジンがサポートされている場合は、ネイティブSQLバージョンが使用されます。

  2. SQLiteバージョンのSQL標準を使用して、データベースから情報を取得します。

ds = ogr.Open(os.path.join(data_dir, 'global',
                           'natural_earth_50m.sqlite'))
sql = '''SELECT geometry, area(geometry) AS area, name, pop_est
         FROM countries ORDER BY pop_est DESC LIMIT 3'''
lyr = ds.ExecuteSQL(sql)
pb.print_attributes(lyr)

ここに画像の説明を挿入します
  3.関数を使用して、複数のレイヤーの属性を接続します。

# ne_50m_populated_places pp:图层重命名
# ON pp.adm0_a3 = c.adm0_a3 基于公共字段连接两表
ds = ogr.Open(os.path.join(data_dir, 'global'))
sql = '''SELECT pp.name AS city, pp.pop_min AS city_pop,
             c.name AS country, c.pop_est AS country_pop
         FROM ne_50m_populated_places pp
         LEFT JOIN ne_50m_admin_0_countries c
         ON pp.adm0_a3 = c.adm0_a3
         WHERE pp.adm0cap = 1'''
lyr = ds.ExecuteSQL(sql)
pb.print_attributes(lyr, 3, geom=False)


  4.複数のレイヤー(都市人口と全国人口)の関連データを表示します。

ds = ogr.Open(os.path.join(data_dir, 'global'))
sql = '''SELECT pp.name AS city, pp.pop_min AS city_pop,
             c.name AS country, c.pop_est AS country_pop
         FROM ne_50m_populated_places pp
         LEFT JOIN ne_50m_admin_0_countries c
         ON pp.adm0_a3 = c.adm0_a3
         WHERE pp.adm0cap = 1 AND c.continent = "Asia"'''
lyr = ds.ExecuteSQL(sql)
pb.print_attributes(lyr, 3)

ここに画像の説明を挿入します
  5. SQLite標準を使用してシェープファイルデータソースを表示します(SQLite標準は他のデータソースにも適用されます)。

lyr = ds.ExecuteSQL(sql, dialect='SQLite')

  6.ジオメトリックオブジェクトをマージします。

# Plot the counties in California.
ds = ogr.Open(os.path.join(data_dir, 'US'))
sql = 'SELECT * FROM countyp010 WHERE state = "CA"'
lyr = ds.ExecuteSQL(sql)
vp = VectorPlotter(True)
vp.plot(lyr, fill=False)

sql = 'SELECT st_union(geometry) FROM countyp010 WHERE state = "CA"'
lyr = ds.ExecuteSQL(sql, dialect='SQLite')
vp.plot(lyr, 'w')

ここに画像の説明を挿入します


4.フィルターを使用する

  1.必要なデータを作成します。

ds = ogr.Open(os.path.join(data_dir, 'global'), 1)

in_lyr = ds.GetLayer('ne_50m_populated_places')
in_lyr.SetAttributeFilter("FEATURECLA = 'Admin-0 capital'")

out_lyr = ds.CopyLayer(in_lyr, 'capital_cities2')
out_lyr.SyncToDisk()

  2.必要な要素のみを選択します。

sql = """SELECT NAME, ADM0NAME FROM ne_50m_populated_places
         WHERE FEATURECLA = 'Admin-0 capital'"""
in_lyr2 = ds.ExecuteSQL(sql)
out_lyr2 = ds.CopyLayer(in_lyr2, 'capital_cities3')
out_lyr2.SyncToDisk()

おすすめ

転載: blog.csdn.net/amyniez/article/details/113513153