フィールド演算 (Calculate Field) の Python の例

キーボードを使用して値を入力する以外の方法でも、テーブル内の値を編集することができます。場合によっては、数学的な計算を実行して、単一のレコードまたはすべてのレコードのフィールド値を設定することもできます。すべてのレコードまたは選択したレコードについて、単純なものから高度なものまでさまざまな計算を実行することができます。さらに、属性テーブルのフィールドで、面積、長さ、周長、およびその他のジオメトリ プロパティを計算することもできます。以下の各セクションでは、フィールド演算を使用する例を示しています。Python、SQL、および Arcade を使用して計算が実行されます。

このトピックでは、Python ベースの [フィールド演算 (Calculate Field)] の例に焦点を合わせます。Arcade 条件式の詳細については、ArcGIS Arcade のガイドをご参照ください。SQL 式の詳細については、「フィールドの計算」をご参照ください。

メモ:
  • Python では、インデントが構文の一部と見なされます。それぞれの論理レベルの定義には、2 つまたは 4 つのスペースを使用します。ステートメント ブロックの開始位置と終了位置を揃え、一貫性を保ってください。
  • Python の計算式フィールドは感嘆符 (!!) で囲みます。
  • 変数に名前を付ける際には、Python で大文字と小文字が区別されることに注意してください。つまり、「value」と「Value」は同じではありません。
  • ステートメントを入力した後でファイルに書き込むには、[エクスポート] ボタンをクリックします。[インポート] ボタンをクリックすると、既存の計算ファイルを検索して選択するよう求められます。

単純な演算

短い式だけでさまざまな演算ができます。

単純な文字列の例

文字列は、Python の一連の文字列関数でサポートされています。これには、capitalizerstripreplace などがあります。

CITY_NAME フィールド内の文字列の先頭の文字を大文字にします。

!CITY_NAME!.capitalize()

CITY_NAME フィールド内の文字列の末尾にある空白をすべて除去します。

!CITY_NAME!.rstrip()

STATE_NAME フィールド内で「california」が見つかった場合は、すべて「California」で置き換えます。

!STATE_NAME!.replace("california", "California")

Python では、文字列フィールド内の文字にインデックス付けと分割によってアクセスできます。インデックス付けはインデックス位置における文字を取得してきて、スライスは文字のグループを取得してきます。以下の表では、!fieldname! が、「abcde」という値を含んでいる文字列フィールドであると仮定しています。

説明結果

!fieldname![0]

最初の文字

"a"

!fieldname![-2]

最後から 2 つ目の文字

"d"

!fieldname![1:4]

2 つ目、3 つ目、4 つ目の文字

"bcd"

Python では、format() メソッドを使用した文字列の書式設定もサポートされています。

FieldA と FieldB をコロンで区切って結合します。

"{}:{}".format(!FieldA!, !FieldB!)

単純な関数の例

Python には、数値を処理するためのツールが用意されています。また、Python では、mathcmathdecimalrandomitertoolsfunctoolsoperator など、数多くの数値関数と数学関数もサポートされています。

演算子説明結果

x + y

x に y を加算

1.5 + 2.5

4.0

x - y

x から y を減算

3.3 - 2.2

1.1

x * y

x に y を乗算

2.0 * 2.2

4.4

x / y

x を y で除算

4.0 / 1.25

3.2

x // y

x を y で除算 (切り捨て除算)

4.0 // 1.25

3.0

x % y

x を y で除算した剰余

8 % 3

2

-x

x の負数表現

x = 5

-x

-5

+x

x を変更しない

x = 5

+x

5

x ** y

x の y 乗

2 ** 3

8

乗算

!Rank! * 2

半径フィールドが指定された球体の体積を計算します。

4.0 / 3.0 * math.pi * !Radius! ** 3
レガシー:

ArcGIS Pro では Python 3 が使用され、ArcGIS Desktop では Python 2 が使用されます。Python 2 では整数の算術演算が使用されます。つまり、2 つの整数値を除算すると、必ず整数値が出力されます (3 / 2 = 1)。Python 3 では、2 つの整数値を除算すると、float 型が出力されます (3 / 2 = 1.5)。

Python 組み込み関数

Python では、maxminroundsum など、多数の組み込み関数を使用できます。

フィールドのリストの各レコードに対する最大値を計算します。

max([!field1!, !field2!, !field3!])

フィールドのリストの各レコードに対する最大値を計算します。

sum([!field1!, !field2!, !field3!])

コード ブロックの使用

Python の式と [コード ブロック] パラメーターを使用すると、次のことが可能になります。

  • 式での任意の Python 関数の使用
  • ジオプロセシング機能およびオブジェクトへのアクセス
  • フィーチャ ジオメトリのプロパティへのアクセス
  • 新しいランダム値演算子へのアクセス
  • If...Then...Else 論理を使用した値の再分類

式のタイプコード ブロック

Python 3

Python の機能をサポートしています。コード ブロックは、Python 関数 (def) を使用して表現されます。ジオメトリ プロパティは、必要に応じてポイント オブジェクトなどのジオプロセシング オブジェクトを使用して表現されます。

Arcade

Arcade の機能をサポートしています。

SQL

SQL 式をサポートします。

SQL 式は、特にパフォーマンス面でフィーチャ サービスとエンタープライズ ジオデータベースを使用した計算をサポートできるように実装されています。一度に 1 つのフィーチャまたは行を計算する代わりに、フィーチャ サービスまたはデータベースに 1 つのリクエストが設定されます。

レガシー:

ArcGIS Desktop[フィールド演算 (Calculate Field)] ツールでは、VBPYTHONPYTHON_9.3 が式の種類としてサポートされます。VB は、式の種類として一部の製品でサポートされていますが、ArcGIS Pro などの 64 ビット製品ではサポートされていません。

PYTHON キーワードと PYTHON_9.3 キーワードもまだ ArcGIS Pro で下位互換性のためにサポートされていますが、リストに選択肢として表示されません。これらのキーワードを使用する Python スクリプトを引き続き利用できます。

Python 3 式タイプと従来の PYTHON_9.3 キーワードの違いは、Python 3 が日付フィールド内の値を Pythondatetime オブジェクトとして返す点だけです。

メモ:

Python 3 式タイプは、ArcGIS Pro と共にインストールされる Python のバージョンに関連していません。Python 3 は、単に歴史的に (PYTHON および PYTHON_9.3 に続く) 3 番目の Python 関連のキーワードということです。

Python 関数は、def キーワードの後に関数の名前と関数の入力引数を付けて定義します。Python 関数は、任意の数の入力引数 (引数がない場合も含む) を使って記述できます。値は、return ステートメントを使用して各関数から返されます。関数名は自由に作成できます (スペースを使用したり、名前の最初に数字を使用したりすることはできません)。

メモ:

return ステートメントを使用して関数から明示的に値が返されない場合、この関数は None を返します。

メモ:

Python では、インデントが構文の一部として実行されることに注意してください。それぞれの論理レベルの定義には、4 つのスペースを使用します。ステートメント ブロックの開始位置と終了位置を揃え、一貫性を保ってください。

サンプル コード - 数学

次の数学サンプル コードを使用する場合は、式タイプが Python 3 であることを前提とします。

フィールドの値を小数点以下第 2 位に四捨五入します。

式:
round(!area!, 2)

数学モジュールを使用して、メートルをフィートに変換します。変換した値を 2 乗し、さらに面積で乗算します。

式:
MetersToFeet((float(!shape.area!)))
コード ブロック:
import math
def MetersToFeet(area):
    return math.pow(3.2808, 2) * area

Python の論理を使用したフィールド演算

論理パターンをコード ブロックに含めるには、ifelse、および elif ステートメントを使用します。

フィールドの値に基づいて分類します。

式:
Reclass(!WELL_YIELD!)
コード ブロック:
def Reclass(WellYield):
    if (WellYield >= 0 and WellYield <= 10):
        return 1
    elif (WellYield > 10 and WellYield <= 20):
        return 2
    elif (WellYield > 20 and WellYield <= 30):
        return 3
    elif (WellYield > 30):
        return 4

サンプル コード - ジオメトリ

ジオメトリ単位の変換方法の詳細については、次のサンプル コードのほかに、後続の「ジオメトリ単位の変換」セクションもご参照ください。

フィーチャの面積を計算します。

式:
!shape.area!

フィーチャの最大 X 座標を計算します。

式:
!shape.extent.XMax!

フィーチャの頂点数を計算します。

式:
MySub(!shape!)
コード ブロック:
def MySub(feat):    
    partnum = 0
    # Count the number of points in the current multipart feature
    partcount = feat.partCount
    pntcount = 0
    # Enter while loop for each part in the feature (if a singlepart 
    # feature, this will occur only once)
    while partnum < partcount:
        part = feat.getPart(partnum)
        pnt = part.next()
        # Enter while loop for each vertex
        while pnt:
            pntcount += 1   
            pnt = part.next()
   
            # If pnt is null, either the part is finished or there 
            # is an interior ring
            if not pnt: 
                pnt = part.next()
        partnum += 1
    return pntcount

ポイント フィーチャクラスについて、各ポイントの X 座標を 100 だけシフトします。

式:
shiftXCoordinate(!SHAPE!)
コード ブロック:
def shiftXCoordinate(shape):
    shiftValue = 100
    point = shape.getPart(0)
    point.X += shiftValue
    return point

ジオメトリ単位の変換

ジオメトリ フィールドの面積および長さのプロパティは、@ 記号を付けて表現した単位の種類を使用して変更することができます。

  • 面積計測単位のキーワード:
    • ACRES | ARES | HECTARES | SQUARECENTIMETERS | SQUAREDECIMETERS | SQUAREINCHES | SQUAREFEET | SQUAREKILOMETERS | SQUAREMETERS | SQUAREMILES | SQUAREMILLIMETERS | SQUAREYARDS | SQUAREMAPUNITS | UNKNOWN
  • 長さ計測単位のキーワード:
    • CENTIMETERS | DECIMALDEGREES | DECIMETERS | FEET | INCHES | KILOMETERS | METERS | MILES | MILLIMETERS | NAUTICALMILES | POINTS | UNKNOWN | YARDS
メモ:

データが地理座標系に格納されており、距離単位 (たとえば、フィート) が指定されている場合は、測地線アルゴリズムを使用して長さの計算が変換されます。

注意:

地理座標系で表されるデータで面積単位を変換すると、グローブ全体で度 (10 進) が一定でないため、正確な結果となりません。

フィーチャの長さをヤード単位で計算します。

式:
!shape.length@yards!

フィーチャの面積をエーカー単位で計算します。

式:
!shape.area@acres!

geodesicArea の後に測定単位のキーワードが続く、geodesicLength および @ プロパティを使用して、測地線に基づく面積や長さも計算できます。

フィーチャの測地線の長さをヤード単位で計算します。

式:
!shape.geodesicLength@yards!

フィーチャの測地線の面積をエーカー単位で計算します。

式:
!shape.geodesicArea@acres!

サンプル コード - 日付

日付と時刻を計算するには、datetime モジュールと time モジュールを使用します。

現在の日付を計算します。

式:
time.strftime("%d/%m/%Y")

現在の日付と時刻を計算します。

式:
datetime.datetime.now()

2000 年 12 月 31 になるように日付を計算します。

式:
datetime.datetime(2000, 12, 31)

現在の日付とフィールド内の値との間の日数を計算します。

式:
(datetime.datetime.now() - !field1!).days

フィールド内の日付の値に 100 日を加算して、日付を計算します。

式:
!field1! + datetime.timedelta(days=100)

フィールド内の日付の値の曜日 (Sunday (日曜) など) を計算します。

式:
!field1!.strftime('%A')

サンプル コード - 文字列

文字列計算は、Python のさまざまなコード パターンを使用して実行することができます。

右端から 3 つ目の文字を返します。

式:
!SUB_REGION![-3:]

大文字の「P」をすべて小文字の「p」で置き換えます。

式:
!STATE_NAME!.replace("P","p")

2 つのフィールドを、スペースを区切り文字に使用して連結します。

式:
!SUB_REGION! + " " + !STATE_ABBR!

適切な大文字と小文字への変換

次の例は、すべての単語の最初の文字が大文字に、それ以外の文字が小文字になるように単語を変換するための異なる方法を示しています。

式:
' '.join([i.capitalize() for i in !STATE_NAME!.split(' ')])
式:
!STATE_NAME!.title()

正規表現

Pythonre モジュールには、正規表現のマッチング演算が用意されており、これを使用すると、文字列に対して複雑なパターン マッチングと置換ルールを実行できます。

文字列の末尾にある St または St. という単語を、Street という単語で置換します。

式:
update_street(!ADDRESS!)
コード ブロック:
import re
def update_street(street_name):
    return re.sub(r"""\b(St|St.)\Z""",  
                  'Street',
                  street_name)

累積計算と連続計算

累積計算と連続計算を行うには、グローバル変数を使用します。

特定の間隔に基づいて連続する ID または数値を計算します。

式:
autoIncrement()
コード ブロック:
rec=0
def autoIncrement():
    global rec
    pStart = 1  # adjust start value, if req'd 
    pInterval = 1  # adjust interval value, if req'd
    if (rec == 0): 
        rec = pStart 
    else: 
        rec = rec + pInterval 
    return rec

数値フィールドの累積値を計算します。

式:
accumulate(!FieldA!)
コード ブロック:
total = 0
def accumulate(increment):
    global total
    if total:
        total += increment
    else:
        total = increment
    return total

数値フィールドのパーセントの増分を計算します。

式:
percentIncrease(float(!FieldA!))
コード ブロック:
lastValue = 0
def percentIncrease(newValue):
    global lastValue
    if lastValue:
        percentage = ((newValue - lastValue) / lastValue)  * 100
    else: 
        percentage = 0
    lastValue = newValue
    return percentage

ランダム値

ランダム値を計算するには、random モジュールを使用します。

numpy サイトのパッケージを使用して、0.0 から 1.0 の間のランダムな浮動小数の値を計算します。

式:
getRandomValue()
コード ブロック:
import numpy
def getRandomValue():
    return numpy.random.random()

ランダム モジュールを使用して、0 から 10 の間のランダムな整数を計算します。

式:
random.randint(0, 10)
コード ブロック:
import random

NULL 値の計算

Python の式では、PythonNone を使用して NULL 値を計算できます。

メモ:

次の計算は、フィールドに NULL 値が許可されている場合のみ機能します。

Python None を使用した NULL 値の計算

式:
None

関連トピック