SPARQL‐kurs ‐ del 8 - Utdanningsdirektoratet/Grep_SPARQL GitHub Wiki
Denne siden er en del av SPARQL-kurs
- om hvordan vi kan telle ting med SPARQL
I SPARQL er COUNT en aggregeringsfunksjon som brukes i SELECT-delen av spørringen for å telle antall forekomster av et bestemt mønster i resultatsettet. Dette kan være nyttig for å få en oversikt over mengden data som tilfredsstiller visse kriterier.
Når du bruker COUNT i en SPARQL-spørring, teller den antall bindinger (bindings) av variablene som matcher mønsteret i spørringen. La oss ta en titt på et enkelt eksempel for å illustrere dette.
PREFIX ex: <http://eksempel.no/>
SELECT (COUNT(?bok) AS ?antallBøker)
WHERE {
?bok a ex:Bok .
}
I denne spørringen:
-
PREFIX ex: <http://eksempel.no/>
definerer et prefiks for vårt eksempel-navnerom. -
SELECT (COUNT(?bok) AS ?antallBøker)
instruerer SPARQL-motoren til å telle antall bindinger (bindings) det er av variabelen?bok
og returnere resultatet som?antallBøker
. -
WHERE { ?bok a ex:Bok . }
spesifiserer mønsteret vi leter etter, nemlig alle forekomster der?bok
er av typenex:Bok
.
Eller hvis vi hopper til Grep – vi kan telle hvor mange tripler Grep har i hele Greps triplestore:
Antall tripler i hele Grep:
SELECT (COUNT(*) AS ?antallTripler) WHERE {
?s ?p ?o
}
Og slik kan vi fortsette: Forrige spørring svarte med over en million. Men hvor mange "ting" har Grep?
Antall entiteter (ting):
SELECT (COUNT(distinct ?s) AS ?entiteter) WHERE{
?s a []
}
Antall grep-typer:
PREFIX u: <http://psi.udir.no/ontologi/kl06/>
SELECT (COUNT(distinct ?o) AS ?typer) WHERE{
[] u:grep-type ?o
}
I hvor mange læreplaner (LK20) finnes det kompetansemål som inneholder ordet "bærekraft"@default?
Se "fasit" nederst på siden.
COUNT kan også kombineres med GROUP BY for å telle antall forekomster per gruppe. For eksempel, hvis vi ønsker å telle antall bøker per forfatter, kan vi bruke følgende spørring:
PREFIX ex: <http://example.org/>
SELECT ?forfatter(COUNT(?bok) AS ?antallBøker)
WHERE {
?bok a ex:Bok .
?bok ex:forfatter ?forfatter .
}
GROUP BY ?forfatter
I denne spørringen:
-
SELECT ?forfatter (COUNT(?bok) AS ?antallBøker)
teller antall bøker per forfatter og returnerer resultatet som?bookCount
for hver?author
. - `WHERE { ?bok a ex:Bok . ?bok ex:forfatter ?forfatter . } spesifiserer mønsteret der vi leter etter bøker og deres respektive forfattere.
-
GROUP BY ?forfatter
grupperer resultatene etter forfatter. Resultatet vil være en liste over forfattere med antall bøker de har skrevet.
Vi kan gjøre noe lignende i Grep:
Antall kompetansemål for hvert kompetansemålsett i en gitt læreplan:
PREFIX d: <http://psi.udir.no/kl06/>
PREFIX u: <http://psi.udir.no/ontologi/kl06/>
SELECT ?kms ?kmsTittel (COUNT(DISTINCT ?km) AS ?antallKm)
WHERE {
d:NOR01-06 u:kompetansemaalsett ?kms .
?kms u:kompetansemaal ?km ;
u:tittel ?kmsTittel ;
u:rekkefoelge ?kmsR .
FILTER(LANG(?kmsTittel)="default")
}
GROUP BY ?kms ?kmsR ?kmsTittel
ORDER BY ?kmsR
Vi kan også, ved litt lur bruk av parenteser, lage regnestykker. I spørringen nedenfor har vi to COUNT-elementer, men vi omslutter begge med en nyt parentes (og hver av COUNT-delene har vi kuttet ut AS
-delen. Den legger vi på til slutt for resultatet av hele regnestykket.
Gjennomsnittlig antall kompetansemål pr kompetansemålsett for LK20-læreplaner:
PREFIX d: <http://psi.udir.no/kl06/>
PREFIX u: <http://psi.udir.no/ontologi/kl06/>
SELECT ?lp (ROUND(COUNT(DISTINCT ?km) / (COUNT(DISTINCT ?kms))) as ?kmPrKms)
WHERE {
?lp a u:laereplan_lk20 ;
u:kompetansemaalsett ?kms .
?kms u:kompetansemaal ?km .
}
GROUP BY ?lp
ORDER BY DESC(?kmPrKms) ASC(?lp)
I denne spørringen deler vi altså antall kompetansemål på antall kompetansemålsett. Da får vi antall kompetansemål pr. kompetansemålsett for hver læreplan av LK20-typen.
Dette vekker en viss læreplan-faglig nysgjerrighet hos meg, så her har jeg lyst til å borre videre. Hva om vi kunne sammenligne antall kompetansemål pr kompetansemålsett for LK-06 og LK20? Det ble jo sagt at antallet kompetansemål i læreplanene skulle ned i forbindelse med fagfornyelsen. Men ikke la deg lure, og stoppe bare ved neste spørring, vi må lage enda en spørring for å være mer presise. Men altså først:
PREFIX d: <http://psi.udir.no/kl06/>
PREFIX u: <http://psi.udir.no/ontologi/kl06/>
SELECT distinct ?lpType (COUNT(DISTINCT ?km) / (COUNT(DISTINCT ?kms)) as ?kmPrKms)
WHERE {
[] a u:opplaeringsfag ;
u:laereplan-referanse ?lp .
?lp u:grep-type ?lpType ;
u:kompetansemaalsett ?kms .
?kms u:kompetansemaal ?km .
}
GROUP BY ?lpType
ORDER BY ?lpType
I denne spørringen droppet jeg ROUND
, for her var det close race. Vi må på desimaler for å skille dem fra hverandre:
Husk at utsagnet om å redusere antall kompetansemål var sagt i forbindelse med innføringen av fagfornyelsen, og at debatten handlet som grunnskolen. OK, vi tar det med i beregningen og tar med krav om at læreplanene skal være for grunnskolen:
PREFIX d: <http://psi.udir.no/kl06/>
PREFIX u: <http://psi.udir.no/ontologi/kl06/>
SELECT distinct ?lpType (COUNT(DISTINCT ?km) / (COUNT(DISTINCT ?kms)) as ?kmPrKms)
WHERE {
[] a u:opplaeringsfag ;
u:laereplan-referanse ?lp .
?lp u:grep-type ?lpType ;
u:fagtype d:fagtype_grunnskolefag ; # vi legger på krav om grunnskolefag
u:kompetansemaalsett ?kms .
?kms u:kompetansemaal ?km .
}
GROUP BY ?lpType
ORDER BY ?lpType
I følge denne beregningen, har vi redusert antall kompetansemål med ca 8 pr kompetansemålsett.
Men jeg er ikke helt fornøyd - husk at LK06-planene kan ha mange revisjoner bakover i tid, så antallet læreplaner er større på LK06-siden av ligningen. Derfor tar jeg meg bryet å kun ta med LK06-læreplaner som er erstattet av en LK20-lærpelan (i skrivende stund er det ikke noen revisjoner av LK20-planer). Det er overgangen til fagfornyelsen vi er ute etter. Jeg må også presisere at slik spørringen nedenfor er utformet, kun tar med LK20-læreplaner som erstatter en annen læreplan. Men det er kanskje like greit, for det vi ønsker er jo å sammenligne LK06 og LK20, og se utviklingen.
PREFIX d: http://psi.udir.no/kl06/ PREFIX u: http://psi.udir.no/ontologi/kl06/
SELECT DISTINCT ?lpType (COUNT(DISTINCT ?km) / COUNT(DISTINCT ?kms) AS ?kmPrKms)
WHERE {
{
# LK20-læreplaner
?lp20 a u:laereplan_lk20 ;
u:grep-type ?lpType ;
u:fagtype d:fagtype_grunnskolefag ;
u:kompetansemaalsett ?kms .
}
UNION
{
# LK06-læreplaner som er erstattet av LK20
?lp20 a u:laereplan_lk20 ;
u:erstatter ?lp06 .
?lp06 a u:laereplan ;
u:grep-type ?lpType ;
u:fagtype d:fagtype_grunnskolefag ;
u:kompetansemaalsett ?kms .
}
?kms u:kompetansemaal ?km .
}
GROUP BY ?lpType
ORDER BY ?lpType
Da får vi dette resultatet:
Altså en marginal forskjell. Men vi får et mer korrekt svar og det i favør av målet med å redusere antall kompetansemål.
I den siste spørringen innfører vi egentlig også to nye ting; delspørringer og UNION. Det tar vi i neste del.
- Hvor mange kompetansemålsett pr læreplan er det gjennomsnittlig i LK20?
- Hva om vi kun teller grunnskolefag?
- Hva om viser og grupperer etter læreplan?
Se "fasit" nederst på siden.
I denne delen har sett og øvd på hvordan vi kan bruke aggregeringsfunksjonen COUNT for å telle ting i Grep. Vi har også brukt COUNT med grupperinger for å telle antall forekomster noe pr. gruppe ved hjelp av GROUP BY
.
I den neste delen skal vi gå inn på delspørringer generelt, og vi skal se på UNION spesielt. Det er en operator som brukes for å kombinere resultatene av to eller flere mønstre i én spørring.
Her er et forslag til løsning:
PREFIX u: <http://psi.udir.no/ontologi/kl06/>
select (COUNT(DISTINCT(?lp)) AS ?antallLp) where {
?km a u:kompetansemaal_lk20 ;
u:tilhoerer-laereplan ?lp ;
u:tittel ?tittel .
FILTER (
(REGEX(str(?tittel), "bærekraft", "i")) &&
(LANG(?tittel) = "default")
)
}
Det som er verdt å merke seg, er at jeg først har slått opp alle kompetansemålene (?km
), og deretter brukt u:tilhoerer-laereplan ?lp
for å finne læreplanen som kompetansemålet tilhører. Så må jeg huske å bruke DISTINCT i COUNT(DISTINCT(
for å kun få én læreplan pr treff på "bærekraft" i ligningen.
Her er et forslag:
PREFIX u: <http://psi.udir.no/ontologi/kl06/>
select (COUNT(DISTINCT ?kms) / COUNT(DISTINCT ?lp) AS ?kmsPrLp) where {
?lp a u:laereplan_lk20 ;
u:kompetansemaalsett ?kms
}
Da legger vi bare inn en betingelse om at ?lp kun skal være grunnskolefag:
PREFIX u: <http://psi.udir.no/ontologi/kl06/>
PREFIX d: <http://psi.udir.no/kl06/>
select (COUNT(DISTINCT ?kms) / COUNT(DISTINCT ?lp) AS ?kmsPrLp) where {
?lp a u:laereplan_lk20 ;
u:kompetansemaalsett ?kms ;
u:fagtype d:fagtype_grunnskolefag .
}
Husk å få med prefix d: når du legger inn u:fagtype d:fagtype_grunnskolefag
Her lærte vi noe om læreplaner; grunnskolefag har flere målgrupper for én og samme læreplan, mens det i videregående er mer spesialisert mot færre –målgrupper (trinn/programfag (kompetansemålsett kan representere både trinn, nivå og fag)
Forslag til løsning:
PREFIX u: <http://psi.udir.no/ontologi/kl06/>
PREFIX d: <http://psi.udir.no/kl06/>
select ?lp (COUNT(DISTINCT ?kms) / COUNT(DISTINCT ?lp) AS ?kmsPrLp) where {
?lp a u:laereplan_lk20 ;
u:kompetansemaalsett ?kms ;
u:fagtype d:fagtype_grunnskolefag .
}
GROUP BY ?lp
ORDER BY DESC(?kmsPrLp)
De to første læreplanene i resultatsettet (når vi har sortert synkende på ?kmsPrLp), sier at de har 16 kompetansemålsett. Ved første øyekast virker det ganske mye. Men hvis vi tar en titt på https://www.udir.no/lk20/NAT01-04 og https://www.udir.no/lk20/NAT02-04 (som er udir.no sin visning av disse to læreplanene), så ser vi at "Naturfag" og "Naturfag samisk" også har egne kompetansemål pr utdanningsprogram i tillegg til de "vanlige" kompetansemålsettene (2. til 10. trinn).
Men ba vi ikke kun om grunnskolefag? Hvorfor blir læreplaner for videregående (vgo) med? Jo, for å ta NAT01-04 som eksempel; kjør følgende spørring, så ser du:
PREFIX d: <http://psi.udir.no/kl06/>
PREFIX u: <http://psi.udir.no/ontologi/kl06/>
select * where {
d:NAT01-04 u:fagtype ?fagtype .
}
Med andre ord – læreplanen er både grunnskolefag og fellesfag.
Skulle vi ekskludert de som er noe annet enn grunnskolefag, ville spørringen vært en annen: Først summen av alle læreplanene i treffet:
PREFIX u: <http://psi.udir.no/ontologi/kl06/>
PREFIX d: <http://psi.udir.no/kl06/>
SELECT (COUNT(DISTINCT ?kms) / COUNT(DISTINCT ?lp) AS ?kmsPrLp)
WHERE {
?lp a u:laereplan_lk20 ;
u:kompetansemaalsett ?kms ;
u:fagtype d:fagtype_grunnskolefag .
FILTER NOT EXISTS {
?lp u:fagtype ?annenFagtype .
FILTER (?annenFagtype != d:fagtype_grunnskolefag)
}
}
Så med visning pr. læreplan:
PREFIX u: <http://psi.udir.no/ontologi/kl06/>
PREFIX d: <http://psi.udir.no/kl06/>
SELECT ?lp (COUNT(DISTINCT ?kms) / COUNT(DISTINCT ?lp) AS ?kmsPrLp)
WHERE {
?lp a u:laereplan_lk20 ;
u:kompetansemaalsett ?kms ;
u:fagtype d:fagtype_grunnskolefag .
FILTER NOT EXISTS {
?lp u:fagtype ?annenFagtype .
FILTER (?annenFagtype != d:fagtype_grunnskolefag)
}
}
GROUP BY ?lp
ORDER BY DESC(?kmsPrLp)