ArcGIS Field Calculator – galingas įrankis

ArcGIS (ArcMAP, ArcGIS Pro ir pan.) funkcija Field Calculator skirta užpildyti atributų laukus ir pasiekiama tiesiogiai atributų lentelėje (pasirinkus konkretų atributą – lauką) arba iš atskiro įrankio Calculate Field yra vienas iš universaliausių, galingiausių ir lanksčiausių ArcGIS duomenų tvarkymo ir analizės įrankių. Taip – bendrai duomenų, ne vien aprašomųjų – atributinių, bet ir bendrai kaip erdvinių.

Paprasčiausias Field Calculator panaudojimas – pvz. į laukelį nr įrašomas numeris 5

ArcMAP projekte, atidarytoje lentelėje, atributui (laukeliui) "nr"  iškviestas įrankis "Field Calculator..."

Rezultatas – visų arba pažymėtų eilučių parinktame laukelyje įrašoma reikšmė 5.

Galima įrašyti reikšmę iš kito laukelio, pvz. OBJECTID, kurio reikšmės šiuo atveju lentelėje išsidėsčiusios iš eilės.

Tai labai paprasti veiksmai. Visa Field Calculator galia slypi tame, kad įrašomą reikšmę galima formuoti naudojant Python programavimo kalbą.

Iškarto imkime uždavinį, tarkime mums reikia į laukelį nr įrašyti ne konkrečią reikšmę, ir ne reikšmę iš kito laukelio, tarkime mums reikalingas unikalus iš eilės einantis numeris ir ne toks, koks yra šiuo metu OBJECTID (nes OBJECTID yra tarnybinis atributas ir po objektų trynimo, kūrimo ir kitų veiksmų, jo reikšmė nebūtinai eis iš eilės ir pan.), bet kad nesidvejintų vaizdas su OBJECTID, tarkime mums reikalinga numeracija kurią sudaro tik lyginiai skaičiai, pvz. 2, 4, 6, 8, 10

Ką daryti? Juk Field Calculator veikimo principas yra toks, kad jis nemato lentelės visumos, jis veikia iteratyviai (kartotinai), tiek kartų, kiek yra lentelėje eilučių (arba kiek yra tuo momentu pažymėtų eilučių) ir per kiekvieną kartą (iteraciją) jis mato tik tą vieną eilutę ir jos kitus laukelius, tačiau nežino kiek eilučių yra apskritai ir kurioje eilutėje jis šiuo metu yra.

Galima pasigooglinti, štai pats ESRI support’as siūlo daryti taip https://support.esri.com/en/technical-article/000011137

Prieš aptariant pavyzdį, truputi apie tai, kaip veikia Field Calculator:

  1. Reikia pažymėti Python (ArcMAP‘e numatytasis pažymėjimas yra VB Script).
  2. Codeblock (Pre-Logic Script Code: – toliau nadosiu Codeblock sąvoką, tokia yra ir įrankyje Calculate Field) langas. Pagal nutylėjimas jis išjungtas, kad būtų paprasčiau atlikti paprastus veiksmus (kaip pavyzdžiuose aukščiau). Įjungiamas pažymėjus Show Codeblock. Paleidus veikti Field Calculator sesiją šiame lange esantis tekstas (kodas) nuskaitomas (interpretuojamas) vieną kartą.
  3. Expression (nr =, tai sufleruoja, kad reikšmė bus įrašyta į konkretų laukelį, bendrai naudosiu Expression sąvoką) langas. Jame esantis tekstas (išraiška) yra vykdoma (interpretuojama) iteratyviai, kaip jau minėta – kiekvienai lentelės eilutei. Veikimo logika Python stiliumi atrodytų taip: for eilutė in eilutės: expression. Pats ciklas for neaprašomas, jį fone vykdo Field Calculator. Expression gali (ir turi) turėti nuorodas į Codeblock, tai Python objektų (kintamųjų, sąrašų, funkcijų, egzempliorių, metodų ir pan.) vardai,

Grįžkime prie uždavinio – sunumeruoti iš eilės lyginiais numeriais. Ką siūlo ESRI:

# Codeblock
rec = 0
def auto_increment():
    global rec
    p_start = 2
    p_interval = 2
    if rec == 0:
        rec = p_start
    else:
        rec += p_interval
    return rec
# Expression
auto_increment()

Štai kaip tai turėtų veikti:

Codeblock sukuriama (def) funkcija auto_increment, funkcija be parametrų (). Funkcijoje nurodoma sekos start pozicija p_start = 2 (mums reikia lyginių ir pradėsim nuo 2) ir sekos žingsnis p_interval = 2 (tik lyginiai – kas 2). Toliau veikia taip: tikrinama ar anksčiau nurodyto nulinės reikšmės rec reikšmė yra 0, kas reikštų, kad tai pirma funkcijos iteracija, jei 0, tada rec gauna p_start reikšmę (pirma iteracija, pirmas skaičius bus 2), kitu atveju (jei rec nėra 0 – jau ne pirma, bet neaišku kuri iteracija) rec reikšmė padidinama žingsniu += p_interval, ir taip per kiekvieną iteraciją. Funkcija kiekvieną kartą įrašymui į laukelį atiduoda (return) aktualią rec reikšmę (pirmą kartą tai bus 2, tada 2+2=4, 4+2=6 ir tt).

Expression, kiekvienai lentelės eilutei iškviečiama aukščiau aprašyta funkcija auto_increment() o funkcijos atiduota reikšmė – reultatas yra įrašomi į konkrečios eilutės nr laukelį.

Veikia!

Čia galima atkreipti dėmesį į vieną momentą. Minėjau, kad Field Calculator veikia kiekvienai eilutei atskirai nematydamas visų eilučių visumos ir kiekio. Kaip jis sudėlioja nuoseklią skaičių seką per visą eilučių kiekį jei funkcija kiekvienai eilutei paleidžiama iš naujo? Prieš pačią funkciją yra sukuriama reikšmė rec = 0. Funkcijos viduje nurodoma, kad rec yra globalus vardas – global rec, jis nėra apribotas vienu funkcijos veikimu o yra vienas ir tas pats vardas visai Field Calculator veikimo sesijai. Pati funkcija kiekvienai eilutei paleidžiama daug kartų, o vardas rec visą laiką yra tas pats ir funkcija kiekvieną kartą 2 prideda prie paskutinės, anksčiau veikusios funkcijos suskaičiuotos rec reikšmės ir kiekvieną kartą funkcija atiduoda naujausią rec.

ESRI pasiūlymas labai geras ir labai teisingas, toks pagal Python Zen, jis yra aiškus, akivaizdus, lengvai skaitomas. Bet… jis nėra elegantiškas :).

Field Calculator veikia su Python ir truputi daugiau žinant Python galimybes, tą patį uždavinį galima išspręsti kitais, elegantiškesniais būdais, pavyzdžiui:

# Codeblock
import itertools
auto_increment = itertools.count(2, 2)
# Expression
next(auto_increment)

Codeblock importuojamas standartinis Python modulis itertools. Su modulio funkcija count sukuriama begalinis iteruojamas objektas – seka auto_increment = itertools.count(2, 2), kur 2 yra start reikšmė, kitas 2 yra žingsnis (pavadinimas auto_increment čia tik dėl vizualinės sieties su praeitu pavyzdžiu, realiai jie nieko bendro neturi). Expression dalyje kiekvienai lentelės eilutei iš to iteruojamo objekto imama vis kita, sekanti reikšmė next.

Perskaitėt viską? Puiku. Tenorėjau tik parodyti užuominą į Field Calculator lankstumą ir jėgą, kuri jame slypi. Galimybės išties yra daug, daug didesnės.

Laukite tęsinio.

Turite pastabų? Minčių? Būtinai pakomentuokite.

Parašykite komentarą

El. pašto adresas nebus skelbiamas. Būtini laukeliai pažymėti *