Formulės#
Formulės rašomos prepare
stulpelyje. Formulių pagalba galima atlikti
įvairius duomenų transformavimo, nuasmeninimo, filtravimo ir kokybės tikrinimo
veiksmus.
Kadangi yra labai didelė įvairovė duomenų formatų ir duomenų valdymo mechanizmų, siekiant suvaldyti visą šią įvairovę DSA formulės leidžia vieningai aprašyti veiksmus su duomenimis. Vėliau formulės verčiamos į vieningą AST, kurį gali interpretuoti automatizuotos priemonės, priklausomai nuo duomenų šaltinio ir konteksto ir DSA sluoksnio.
Gramatika#
Formulių sintaksė atitinką šią ABNF gramatiką:
formula = testlist
testlist = test *("," test) *1","
test = or
or = and *("|" and)
and = not *("&" not)
not = "!" not / comp
comp = expr *(compop expr)
expr = term *(termop term)
term = factor *(factorop factor)
factor = sign factor / composition
composition = atom *trailer
atom = "(" *1group ")"
/ "[" *1list "]"
/ func / value / name
group = test *("," test) *1","
list = test *("," test) *1","
trailer = "[" *1filter "]" / method / attr
func = name call
method = "." name call
call = "(" *1arglist ")"
arglist = argument *("," argument) *1","
argument = test / kwarg
kwarg = name ":" test
filter = test *("," test) *1","
attr = "." name
value = null / bool / integer / number / string / star
compop = ">=" / "<=" / "!=" / "=" / "<" / ">"
termpop = "+" / "-"
factorop = "*" / "/" / "%"
sign = "+" / "-"
star = "*"
name = ~/[a-z_][a-z0-9_]*/i
number = ~/\d+(\.\d+)?/
integer = ~/0|[1-9]\d*/
bool = "false" / "true"
null = "null"
string = ~/(?!"").*?(?<!\\)(\\\\)*?"|'(?!'').*?
(?<!\\)(\\\\)*?'/i
Sintaksės medis#
Formulės verčiamos į vieningą abstraktų sintaksės medį. Vieningas abstraktus sintaksės medis leidžia atskirti formulės skaitymo ir interpretavimo veiklas.
Abstraktus sintaksės medis sudarytas iš vienodų elementų turinčių tokias savybes:
- name
Funkcijos pavadinimas.
- args
Funkcijos argumentų sąrašas, kurį gali sudaryti konkrečios reikšmės ar kiti medžio elementai, veiksmai.
Visos formulėje naudojamos išraiškos sintaksės medyje verčiamos į funkcijų ir
argumentų medį. Pavyzdžiui test("a", "b")
bus verčiamas į:
{
"name": "test",
"args": ["a", "b"],
}
Funkcijų iškvietimas#
Formulės susideda iš vykdomų funkcijų sekos. Pavyzdžiui funkcijos pavadinimu
test
vykdymas formulėje atrodys taip:
test()
Aukščiau pavyzdyje pateikta formulė vykdo funkciją test
, be argumentų. Tačiau
funkcijos gali turėti pozicinius ir vardinius argumentus.
Poziciniai argumentai#
Poziciniai argumentai perduodami taip:
test(a, b, c)
Pavyzdyje, funkcijai test
perduodami trys argumentai a
, b
ir c
. Šioje
dokumentacijoje, tais atvejais, kai funkcijos pozicinių argumentų skaičius nėra
fiksuotas, naudojama *args
išraiška, kur *
nurodo, kad pozicinių argumentų
gali būti 0 ar daugiau.
Vardiniai argumentai#
Vardiniai argumentai funkcijai perduodami taip:
test(a: 1, b: 2, c: 3)
Pozicinius argumentus būtina perduoti tiksliai tokia tvarka, kokios tikisi funkcija. Tačiau vardinius argumentus, galima perduoti, bet kuria tvarka.
Jei vardinių argumentų sąrašas nėra fiksuotas, dokumentacijoje toks argumentų
sąrašas užrašomas **kwargs
forma, kur **
nurodo, kad vardinių argumentų
gali būti 0 ar daugiau.
Alternatyvus funkcijos iškvietimas#
Funkcijų iškvietimas gali būti užrašomas įprastiniu būdu, pavyzdžiui:
test(test(test(a), b), c)
Arba funkcijų grandinės (angl. Method chain) būdu:
a.test().test(b).test(c)
Kadangi formulės dažnai naudojamos tam tikros reikšmės transformavimui, todėl dažnai formulė yra lengviau skaitoma, naudojant funkcijų grandinę.
test(a)
yra a.test()
arba test(a, b)
ir a.test(b)
yra ekvivalentūs
(UFCS).
Standartinės funkcijos#
Priklausomai nuo duomenų šaltinio ar konteksto gali būti naudojami skirtingi veiksmai, tačiau žemiau yra pateikti bendrosios paskirties veiksmai:
- func.bind(name)#
Rodo į reikšmę pavadinimu
name
iš konteksto. Reikšmės ieškoma tokia tvarka:
- func.item(name)#
Sąrašo elemento savybė pavadinimu
name
.
- func.self()#
Rodo į aktyvią reikšmę, naudojamas
property.prepare
formulėse.
- func.or(*args)#
Taip pat galima naudoti tokia išraiška:
a | b | c
Grąžiną pirmą netuščią reikšmę. Pirmoji netuščia reikšmė nutraukia sekančių
args
argumentų interpretavimą.
- func.and(*args)#
Taip pat galima naudoti tokia išraiška:
a & b & c
Grąžina pirmą tuščią reikšmę arba paskutinę reikšmę, jei prieš tai esančios reikšmės netuščios.
- func.not(arg)#
Taip pat galima naudoti tokia išraiška:
!arg
Jei
arg
tuščia grąžinatrue
, priešingu atvejufalse
.
- func.eq(a, b)#
Taip pat galima naudoti tokia išraiška:
a = b
a
lygusb
.
- func.ne(a, b)#
Taip pat galima naudoti tokia išraiška:
a != b
a
nelygusb
.
- func.lt(a, b)#
Taip pat galima naudoti tokia išraiška:
a < b
a
mažiau užb
.
- func.le(a, b)#
Taip pat galima naudoti tokia išraiška:
a <= b
a
mažiau arba lygu užb
.
- func.gt(a, b)#
Taip pat galima naudoti tokia išraiška:
a > b
a
daugiau užb
.
- func.ge(a, b)#
Taip pat galima naudoti tokia išraiška:
a >= b
a
daugiau arba lygu užb
.
- func.add(a, b)#
Taip pat galima naudoti tokia išraiška:
a + b
a
irb
suma.
- func.sub(a, b)#
Taip pat galima naudoti tokia išraiška:
a - b
a
irb
skirtumas.
- func.mul(a, b)#
Taip pat galima naudoti tokia išraiška:
a * b
a
irb
sandauga.
- func.div(a, b)#
Taip pat galima naudoti tokia išraiška:
a / b
a
irb
dalyba.
- func.mod(a, b)#
Taip pat galima naudoti tokia išraiška:
a % b
a
irb
modulis.
- func.positive(a)#
Taip pat galima naudoti tokia išraiška:
+a
Gali būti interpretuojamas skirtingai, priklausomai nuo konteksto. Įprastiniu atveju keičia skaičiaus ženklą.
- func.negative(a)#
Taip pat galima naudoti tokia išraiška:
-a
Gali būti interpretuojamas skirtingai, priklausomai nuo konteksto. Įprastiniu atveju keičia skaičiaus ženklą.
- func.tuple(*args)#
Taip pat galima naudoti tokia išraiška:
(*args)
Grupė argumentų.
- ()
Tuščia grupė.
- a, b
Tas pats, kas
tuple(a, b)
.
- func.list(*args)#
Taip pat galima naudoti tokia išraiška:
[*args]
Sąrašas reikšmių.
- func.getattr(object, attr)#
Taip pat galima naudoti tokia išraiška:
object.attr
Gaunamos reikšmės pagal atributą arba raktą.
- func.getitem(object, item)#
Taip pat galima naudoti tokia išraiška:
a[item]
Gaunamos reikšmės pagal atributą arba raktą.
getitem()
gali būti interpretuojamas kaip sąrašo reikšmių filtras:a[b > c]
- func.dict(**kwargs)#
Taip pat galima naudoti tokia išraiška:
{a: b}
Sudėtinė duomenų struktūra.
- func.set(**kwargs)#
Taip pat galima naudoti tokia išraiška:
{a, b}
Reikšmių aibė.
- func.op(operator)#
Taip pat galima naudoti tokia išraiška:
a(*)
Operatoriai gali būti naudojami kaip argumentai.
- func.stack(columns, values, exclude)#
Visus stulpelius išskyrus
exclude
verčia į vieną stulpelių eilutei suteikiantcolumns
pavadinimą, o reikšmių stulpeliuivalues
pavadinimą. Pavyzdžiui:vertinimas
2015P2
2016P2
Neigiamai
0
1
Teigiamai
39
28
Tokiai lentelei pritaikius
stack("data", "rodiklis", ["vertinimas"])
transformaciją, gausime tokį rezultatą:vertinimas
data
rodiklis
Neigiamai
2015P2
0
Neigiamai
2016P2
1
Teigiamai
2015P2
39
Teigiamai
2016P2
28
- func.date(datetime)#
Gražinama data iš datos ir laiko.
Failai#
Dažnai duomenys teikiami failų pavidalu, kurie gali būti saugomi tiek lokaliai failų sistemoje, tiek nuotoliniame serveryje. Failai gali būti suspausti ir patalpinti į archyvo konteinerius. DSA leidžia aprašyti įvairius prieigos prie duomenų, saugomų failuose, atvejus.
- resource.source
Nutolusiame serveryje saugomo failo URI arba kelias iki lokalaus katalogo. Lokalaus katalogo kelias gali būti pateikiamas tiek POSIX, tiek DOS formatais, priklausomai nuo to, kokioje operacinėje sistemoje failai saugomi.
- resource.prepare
- func.file(resource, encoding: 'utf-8')#
- Parametrai:
resource -- Kelias arba URI iki failo.
encoding -- Failo koduotę.
Ši funkcija leidžia nurodyti failo koduotę, jei failas yra užkoduotas kita, nei UTF-8 koduote. Pilną palaikomų koduočių sąrašą galite rasti šiame sąraše.
- func.extract(resource, type)#
- Parametrai:
resource -- Kelias arba URI iki archyvo failo arba failo objektas.
type -- Archyvo tipas.
Išpakuoja archyvą, kuriame saugomi failai. Galimos
type
reikšmės:- zip
- tar
- rar
Funkcijos rezultatas yra archyvo objektas, kuris leidžia pasiekti esančius archyvo failus
getitem()
funkcijos pagalba.
- func.decompress(resource, type)#
- Parametrai:
resource -- Kelias arba URI iki archyvo failo arba failo objektas.
type -- Archyvo tipas.
Taikomas srautinis failo glaudinimo filtras. Galimos
type
reikšmės:- gz
- bz2
- xz
Stulpeliai lentelėje#
CSV ar skaičiuoklių lentelėse stulpelių pavadinimai pateikiami pačioje lentelėje. Eilutė, kurioje surašyti pavadinimai nebūtinai gali būti pirma. Stulpelių pavadinimai gali būti pateikti keliose eilutėse iš kurių formuojamos kompleksinės struktūros (žiūrėti Kompleksinės struktūros). Įvairias situacijas galima aprašyti formulių pagalba.
- model.prepare
- func.header(*line)#
- null
Lentelėje eilučių pavadinimų nėra. Tokiu atveju,
property.source
stulpelyje reikia pateikti stulpelio numerį, pradedant skaičiuoti nuo 0.
- line
Nurodomas eilutės numeris, pradedant eilutes skaičiuoti nuo 0, kur yra pateikti lentelės stulpelių pavadinimai. Pagal nutylėjimą stulpelių pavadinimų ieškoma pirmoje eilutėje.
- *line
Jei lentelė turi kompleksinę stulpelių struktūrą, tada galima pateikti daugiau nei vieną eilutės numerį iš kurių bus nustatomi stulpelių pavadinimai.
- func.head(n)#
Praleisti
n
einančių po stulpelių pavadinimų eilutės.
- func.tail(n)#
Ignoruoti
n
eilučių failo pabaigoje.
- property.source
Jei naudojamas
header(null)
, tada nurodomas stulpelio numeris, pradedant nuo 0.Jei naudojamas
header(line)
, tada nurodomas stulpelio pavadinimas, toks koks įrašytas lentelės line eilutėje.Jei naudojamas
header(*line)
, tada nurodomas stulpelio pavadinimas, toks koks įrašymas lentelės pirmajame line argumente.
- property.prepare
Jei naudojamas
header(*line)
, žiūrėti Kompleksinės struktūros.
Periodiškumas#
Periodiškumui nurodyti naudojamas model.prepare stulpelis, kuriame galima naudoti tokias formules:
- model.prepare
- func.cron(line)#
Duomenų atnaujinimo laikas, analogiškas cron formatui.
line
argumentas aprašomas taip:n
mn
-toji minutė,n
∊ 0-59.n
hn
-toji valanda,n
∊ 0-23.n
dn
-toji mėnesio diena,n
∊ 1-31.- $d
Paskutinė mėnesio diena.
n
Mn
-tasis mėnuo,n
∊ 1-12.n
wn
-toji savaitės diena,n
∊ 0-6 (sekmadienis-šeštadienis).n
#i
wn
-toji savaitės diena,i
-toji mėnesio savaitė,i
∊ 1-6.n
$i
wn
-toji savaitės diena,i
-toji savaitė nuo mėnesio galo,i
∊ 1-6.
- ,
Kableliu galim atskirt kelias laiko vertes.
- -
Brūkšneliu galima atskirti laiko verčių intervalą.
- /
Pasvyruoju brūkšniu galima atskirti laiko verčių kartojimo žingsnį.
Laiko vertės atskiriamos tarpo simbolių. Jei laiko vertė nenurodyta, reiškia įeina visos įmanomos laiko vertės reikšmės.
- func.hourly()#
- func.daily()#
- func.weekly()#
- func.monthly()#
- func.yearly()#
Statinės reikšmės#
Statinės reikšmės arba konstantos duomenų laukams gali būti nurodomos
property.prepare
stulpelyje naudojant formulės sintaksę. Plačiau apie
formules žiūrėti Formulės skyrelyje.
Transformavimas#
property.prepare
stulpelyje gauta šaltinio reikšmė gali būti pasiekiama
per self
kintamąjį.
property.prepare
formulėje gali būti aprašomos kelios reikšmės atskirtos
kableliu, tai naudojama ryšio laukams, kai ryšiui aprašyti reikia daugiau nei
vieno duomenų lauko.
Formulėje galima naudoti kitus to pačio modelio property pavadinimus, kai
aprašomo property
reikšmės formuojamos dinamiškai naudojant vieną ar
kelis jau aprašytus laukus.
property.prepare
stulpelyje galima naudoti tokias formules:
- property.prepare
- func.null()#
Grąžina
null
reikšmę, jei toliau einančios transformacijos grąžinanull
.
- func.replace(old, new)#
Pakeičia visus
old
įnew
simbolius eilutėje.
- func.re(pattern)#
Grąžina atitinkančią reguliariosios išraiškos
pattern
reikšmę arba pirmos grupės reikšmę jei naudojama tik viena grupė arba reikšmių grupę jeipattern
yra daugiau nei viena grupė.
- func.cast(type)#
Konvertuoja šaltinio tipą į nurodytą
type
tipą. Tipų konvertavimas yra įmanomas tik tam tikrais atvejais. Jei tipų konvertuoti neįmanoma, tada metodas turėtų grąžinti klaidą.
- func.split()#
Dalina simbolių eilutę naudojant
s+
reguliariąją išraišką. Grąžina masyvą.
- func.strip()#
Pašalina tarpo simbolius iš pradžios ir pabaigos.
- func.lower()#
Verčia visas raides mažosiomis.
- func.upper()#
Verčia visas raides didžiosiomis.
- func.len()#
Grąžina elementų skaičių sekoje.
- func.choose(default)#
Jei šaltinio reikšmė nėra viena iš enum, tada grąžinama default reikšmė.
Jei
default
nepateiktas, grąžina vieną išproperty.enum
reikšmių, jei duomenų šaltinio reikšmė nėra viena išproperty.enum
, tada grąžinama klaida.
- func.switch(*cases)#
- func.case(cond, value)#
- func.case(default)#
Grąžina
value
, jei tenkinacond
arbadefault
. Jeicase(default)
nepateiktas, tada grąžina pradinę reikšmę.Jei,
cases
nepateikti, grąžina vieną išswitch.source
reikšmių, tenkinančių switch prepare sąlygą.
- func.swap(old, new)#
Pakeičia
old
reikšmęnew
, jeiguself
atitinkaold
.
- func.return()#
Nutraukia transformacijų grandinę ir grąžina reikšmę.
- func.set(name)#
Išsaugo reikšmę į kintamąjį
name
.
- func.url()#
Skaido URI į objektą turintį tokias savybes:
- scheme
URI schema.
- netloc
Visada URI dalis tarp scheme ir path.
- username
Naudotojo vardas.
- password
Slaptažodis.
- host
Domeno vardas arba IP adresas.
- port
Prievado numeris.
- path
Kelias.
- query
URL dalis einanti tarp
?
ir#
.- fragment
URL dalis einanti po #.
- func.query()#
Skaido URI query dalį į parametrus.
Kompleksinės struktūros#
Daugelis duomenų šaltiniu turi galimybę saugoti kompleksines struktūras. Jei
duomenys yra kompleksiniai, tada property.source
stulpelyje galima
nurodyti tik duomens pavadinimą iš pirmojo lygmens, gilesniuose lygmenyse
esančius duomenis galima aprašyti naudojant formules property.prepare
stulpelyje.
Analogiškai duomenų atranką galima daryti ir model
eilutėse, jei tai leidžia
duomenų šaltinis.
Kaip pavyzdį naudosime tokią JSON duomenų struktūrą:
{
"result": {
"count": 1,
"results": [
{
"type": "dataset",
"tags": ["CSV"]
}
]
}
}
- property.prepare
- func.getattr(object, name)#
Grąžina
object
savybęname
.>>> self.result.count 1
- func.getitem(object, item)#
Grąžina
object
objektoitem
savybę arbaobject
masyvoitem
elementą.>>> self["result"]["count"] 1
getitem()
irgetattr()
gali būti naudojami kartu.>>> self.result.results[0].type "dataset"
getitem()
gali būti naudojamas, kaip masyvo elementų filtras pateikiant filtro sąlygą.>>> self.result.results[tags = "CSV"].type ["dataset"] >>> self.result.results[item(tags) = "CSV"].type ["dataset"]
Norint gauti visus masyvo elementus, galima naudoti tokią išraišką:
>>> self.result.results[].tags[] ["CSV"]
- func.first(object, default)#
Grąžina pirmą
object
sąrašo reikšmę, jei sąrašas tuščias, tada grąžinadefault
reikšmę, jeidefault
nenurodytas, tada nutraukia vykdymą su klaidą.>>> self.result.results[].tags.first() "CSV"
Jei `self.result.results[].tags būtų tuščias, tada:
>>> self.result.results[].tags.first(null) null
Analogiška struktūra gali būti gaunama ir lentelėse, kai stulpelių pavadinimai nurodyti keliose eilutėse, pavyzdyje pateiktą struktūrą atitiktų tokia lentelė:
result |
||
---|---|---|
count |
results |
|
type |
tags |
|
1 |
dataset |
CSV |
Šioje lentelėje stulpelių pavadinimai pateikti trijose eilutėse, todėl
model.prepare
reikėtų naudoti header(0, 1, 2)
.