フィールド演算の Python の例

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

このトピックでは、Python ベースの [フィールド演算 (Calculate Field)] を中心に取り上げます。 Arcade 式の詳細については、「ArcGIS Arcade ガイド」をご参照ください。 SQL 式の詳細については、「フィールドの計算」をご参照ください。 VBScript の例の詳細については、「フィールド演算 (Calculate Field) の VBScript の例」をご参照ください。

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

単純な演算

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

単純な文字列の例

文字列は、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

フィールドの値に 2 を掛けます。

!Rank! * 2

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

4.0 / 3.0 * math.pi * !Radius! ** 3
注意:

Short、Long、および Big Integer フィールドは、サポートする整数の範囲が次のように異なります。

  • Short (16 ビット整数) - -(215) 〜 215 (-32,768 〜 32,767) の整数をサポートします。
  • Long (32 ビット整数) - -(231) 〜 231 (-2,147,483,648 〜 2,147,483,647) の整数をサポートします。
  • Big Integer (64 ビット整数) - -(253) 〜 253 (-9,007,199,254,740,992 〜 9,007,199,254,740,991) の整数をサポートします。

レガシー:

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 など、多数の組み込み関数を使用できます。

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

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

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

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

コード ブロックの使用

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

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

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

Python (PYTHON3 キーワード)

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

Arcade

Arcade の機能がサポートされます。

SQL

SQL 式をサポートします。

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

VBScript

VBScript 機能がサポートされます。

レガシー:

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

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

注意:

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

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

注意:

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

注意:

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

サンプル コード - 数学

単純な数式は [式] パラメーターを使用して追加でき、より複雑な数式は [式] パラメーターと [コード ブロック] パラメーターを使用して作成できます。

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

Expression:
round(!area!, 2)

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

Expression:
MetersToFeet((float(!shape.area!)))

Code Block:
import math
def MetersToFeet(area):
    return math.pow(3.2808, 2) * area

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

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

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

Expression:
Reclass(!WELL_YIELD!)

Code Block:
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

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

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

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

Expression:
!shape.area!

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

Expression:
!shape.extent.XMax!

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

Expression:
getVertexCount(!shape!)

Code Block:
def getVertexCount(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 だけシフトします。

Expression:
shiftXCoordinate(!SHAPE!)

Code Block:
def shiftXCoordinate(shape):
    shiftValue = 100
    point = shape.getPart(0)
    point.X += shiftValue
    return point

ジオメトリ単位の変換

ジオメトリ フィールドの面積および長さのプロパティは、getArea および getLength ジオメトリ メソッドを使用して、単位の種類とともに変更することができます。

ジオプロセシングでサポートされている距離単位と面積単位の詳細

詳細については、Polygon オブジェクトと Polyline オブジェクトをご参照ください。

注意:

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

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

Expression:
!shape!.getLength('PLANAR', 'YARDS')

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

Expression:
!shape!.getArea('PLANAR', 'ACRES')

GEODESIC メソッド タイプを使用して、測地線に基づく面積や長さも計算できます。

詳細については、Polygon オブジェクトと Polyline オブジェクトをご参照ください。

ジオプロセシング ツールと距離および面積単位の詳細

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

Expression:
!shape!.getLength('GEODESIC', 'YARDS')

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

Expression:
!shape!.getArea('GEODESIC', 'ACRES')

サンプル コード - Date フィールド

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

注意:

フィールド タイプ (Date、Date Only、Time Only、Timestamp Offset、Text) 間で時間値を転送するには、代わりに [時間フィールドの変換 (Convert Temporal Field)] ツールを使用します。

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

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

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

Expression:
datetime.datetime.now()

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

Expression:
datetime.date.today()

日付を 2015 年 3 月 15 日午後 1 時 30 分 00 秒になるように計算します。

Expression:
datetime.datetime(year=2015, month=3, day=15, hour=13, minute=30, second=0)

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

Expression:
datetime.datetime.now().day - !OID!

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

Expression:
!field1! + timedelta(days=100)

Code Block:
from datetime import timedelta

datetime モジュールの ctime メソッドを使用し、日付を表す文字列を計算します。 この例では、'Mon Feb 22 10:15:00 2021' の形式の文字列が作成されます。

Expression:
!field1!.ctime()

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

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

datetime モジュールの strftime メソッドと、明示的な書式文字列を使用して日付フィールドから書式設定された文字列を計算します。 この例では、'02/22/2021, 10:15:00' の形式の文字列が作成されます。

Expression:
!field1!.strftime("%m/%d/%Y, %H:%M:%S")

ISO 8601 形式の文字列を使用して日付を計算します。

Expression:
'1969-07-21 02:56:00'

月、日、年、時間の規則を使用して日付を計算します。

Expression:
'July 1 2020 12:30:45'

サンプル コード - Time only フィールド

datetime モジュールの time 関数を使用して、時間を午後 4 時 30 分 00 秒になるように計算します。

Expression:
time(hour=16, minute=30, second=0)

Code Block:
from datetime import time

Date フィールドを Time only フィールドに計算すると、datetime オブジェクトの時間部分のみが適用されます。

Expression:
!date_field!

サンプル コード - Date only フィールド

注意:

フィールド タイプ (Date、Date Only、Time Only、Timestamp Offset、Text) 間で時間値を転送するには、代わりに [時間フィールドの変換 (Convert Temporal Field)] ツールを使用します。

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

Expression:
datetime(2000, 12, 31)

Date フィールドを Time only フィールドに計算すると、datetime オブジェクトの時間部分のみが適用されます。

Expression:
!date_field!

サンプル コード - Timestamp offset フィールド

注意:

フィールド タイプ (Date、Date Only、Time Only、Timestamp Offset、Text) 間で時間値を転送するには、代わりに [時間フィールドの変換 (Convert Temporal Field)] ツールを使用します。

datetime.timezone モジュールの utc プロパティを使用して、現在の日付と時間に UTC タイムスタンプ オフセットを追加します。

Expression:
datetime.now(tz=timezone.utc)

Code Block:
from datetime import timezone

zoneinfo モジュールの ZoneInfo クラスを使用して、現在の日付と時間にタイムスタンプ オフセットを追加し、タイム ゾーンを設定します。

Expression:
datetime.now(ZoneInfo('America/New_York'))

Code Block:
from zoneinfo import ZoneInfo

サンプル コード - 文字列

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

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

Expression:
!SUB_REGION![-3:]

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

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

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

Expression:
!SUB_REGION! + " " + !STATE_ABBR!

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

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

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

正規表現

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

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

Expression:
update_street(!ADDRESS!)

Code Block:
import re
def update_street(street_name):
    return re.sub(r"""\b(St|St.)\Z""",  
                  'Street',
                  street_name)

累積計算と連続計算

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

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

Expression:
autoIncrement(10, 5)

Code Block:
rec = 0
def autoIncrement(start=1, interval=1):
    global rec
    if rec == 0:
        rec = start
    else:
        rec += interval
    return rec

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

Expression:
accumulate(!FieldA!)

Code Block:
total = 0
def accumulate(increment):
    global total
    if total:
        total += increment
    else:
        total = increment
    return total

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

Expression:
percentIncrease(float(!FieldA!))

Code Block:
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 の間のランダムな浮動小数の値を計算します。

Expression:
getRandomValue()

Code Block:
import numpy

def getRandomValue():
    return numpy.random.random()

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

Expression:
random.randint(0, 10)

Code Block:
import random

NULL 値の計算

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

注意:

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

Python None を使用して NULL 値を計算します。

Expression:
None

関連トピック