Spring til indhold

Datasæt

en samling data, der udgives som én enhed

Hvad det er

Et datasæt, på engelsk dataset, er en afgrænset mængde data, som man håndterer som én ting: det har et navn, en kilde, en periode, det dækker, og en form, som alle dets poster deler, og de fire forhold siger, hvor det begynder og slutter. En måneds måleraflæsninger i én fil er et datasæt; det samme er en natlig eksport af tre relaterede tabeller. Ordet siger intet om størrelse eller format, kun at dataene indeni hører sammen.

Siderne på dette site bruger ordet i den praktiske betydning. Én taler om et historisk datasæt i JSONL-format og om datasæt på 1 dag og 30 dage brugt til benchmarks, en anden om kuraterede datasæt og tabeller, der eksporteres for at blive indlæst andetsteds, en tredje om enorme datasæt fra fjernaflæste elmålere. Hver gang trækker ordet en grænse om data, før der gøres noget ved dem.

W3C’s Data Catalog Vocabulary, DCAT, giver ordet en formel ramme. Version 3 blev W3C-anbefaling den 22. august 2024 og definerer et datasæt som en samling data, offentliggjort eller kurateret af én aktør og tilgængelig til adgang eller download i en eller flere serialiseringer eller formater. Begrebet er bredt med vilje: tal, tekst, billeder og lyd kan alle indgå. DCAT skiller derefter tre ting ad, som daglig tale blander sammen:

  • Dataset: dataene som idé, for eksempel timeforbrug pr. zone for 2024.
  • Distribution: én tilgængelig form af datasættet, for eksempel en CSV-fil til download; ét datasæt kan have flere.
  • Dataset series: datasæt, der udgives hver for sig, men har nok til fælles til at blive samlet, for eksempel én fil pr. måned.

To filer i forskellige formater kan altså være ét datasæt, og to månedsfiler under samme navn kan være to medlemmer af en serie.

I Google BigQuery har ordet en anden, snævrere betydning. Der er et datasæt en beholder til tabeller, views og andre ressourcer, og det ligger inde i et projekt. En tabel skal høre til et datasæt, så datasættet oprettes, før der indlæses data, og det adresseres som project.dataset i GoogleSQL og som project:dataset i kommandolinjeværktøjet bq. Sammenhængen afgør, hvilken betydning der er i spil.

Hvorfor det betyder noget

En grænse gør data sammenlignelige. To sæt aflæsninger kan kun sammenlignes, når begge dækker samme periode, samme steder og samme afstand mellem posterne, og at navngive et datasæt er måden, de vilkår fastlægges på. DCAT giver afstanden sin egen egenskab, temporal resolution, den mindste afstand mellem elementer i datasættet, skrevet som en varighed som P1D for én dag. Et datasæt, der oplyser sin opløsning, fortæller læseren, om rækkerne er timer, kvarterer eller noget uregelmæssigt, før den første sum.

Beskrivelsen skal følge med dataene. DCAT opregner, hvad en distribution kan sige om sig selv: medietype, format, komprimeringsformat, pakkeformat, størrelse i byte og en checksum, og den sidste lader modtageren kontrollere, at indholdet er uændret. Specifikationens eget eksempel på et komprimeringsformat er gzip. En fil, der ankommer med de oplysninger, kan kontrolleres og åbnes; en fil, der ankommer nøgen, må man gætte sig til.

Formatet på en distribution afgør, hvem der kan læse den. Tre er almindelige:

  • CSV. RFC 4180 fra 2005 beskriver det layout, de fleste implementeringer ser ud til at følge: én post pr. linje, en valgfri overskriftslinje, dobbelte anførselstegn om ethvert felt, der rummer et komma, et linjeskift eller et dobbelt anførselstegn, og et dobbelt anførselstegn inde i et felt skrevet to gange.
  • JSON Lines. Én gyldig JSON-værdi pr. linje, UTF-8, hver linje afsluttet med \n, gemt som .jsonl eller, komprimeret med gzip, .jsonl.gz. Programmer læser det én post ad gangen, og Unix-agtige tekstværktøjer, forbundet med pipes i en shell, håndterer det godt.
  • Parquet. Et open source-filformat, der er orienteret efter kolonner og bygget til effektiv lagring og hentning af data, med komprimerings- og kodningsmetoder til at håndtere komplekse data i store mængder.

Her er én post i de to første formater, hvor kommaet i noten tvinger anførselstegn frem i CSV-udgaven:

id,read_at,kwh,note
M-17,2024-01-08T10:00:00Z,3.21,"late, manual"

{"id":"M-17","read_at":"2024-01-08T10:00:00Z","kwh":3.21,"note":"late, manual"}

Sådan ser det ud i praksis

Eldata kom fra flere datakilder, som hver havde sin egen rapporteringsfrekvens, fra timeintervaller til intervaller på 15 minutter og i nogle tilfælde uregelmæssige tidsstempler, og det gjorde det svært at skabe et sammenhængende og sammenligneligt datasæt. Arbejdet tog rå hændelsesdata fra et historisk JSONL-datasæt og gjorde dem til timeforbrug med én række pr. time og pr. zone ved at summere produktionsmikset i hvert interval, lægge import til og trække eksport fra. Der blev skrevet tre varianter, i Python, JQ og SQL. Python-pipelinen parsede JSONL-filerne til dataframes, samplede tidsserierne om til timeintervaller og eksporterede resultaterne som CSV eller indlæste dem i en let SQLite-database, så de kunne efterses. I benchmarks med historiske datasæt på 1 dag og 30 dage var den den hurtigste af de tre: 34 ms for én dag og 180 ms for tredive. Arbejdet mellem input og output er et skift i granularitet, fra hver kildes egen takt til én fast række pr. time og zone.

Et datasæt bliver også flyttet, og et sæt på seks ETL/ELT-pipelines flyttede data fra et data warehouse bag en IPsec VPN til Google BigQuery. Dataene kom som komprimerede arkiver med Parquet-, CSV- og .bak-filer, og Bash- og Python-scripts klassificerede hver fil efter type og skema. Da procedurer havde renset, normaliseret og beriget rækkerne, blev kuraterede datasæt og tabeller eksporteret til mellemformater, komprimeret med gzip og overført til en Google Cloud Storage-bucket, hvorfra bq CLI og Python-scripts indlæste dem i BigQuery. For datasættene i BigQuery betød det friske data hver dag i stedet for hver uge, og hele turen fra arkiv til tabel tog under 20 minutter, hvor den før havde krævet over 3 timers manuelt arbejde.

Andre steder er datasættet noget, der skal læses. Fjernaflæste elmålere i flere geografiske regioner leverede enorme datasæt bag over 500 analyserapporter skrevet i ren SQL i PostgreSQL og BigQuery. Dataene omfattede geografiske koordinater, måler-id’er, tidsstemplet energiforbrug og miljømetadata. Hver rapport havde kommenteret SQL, så kolleger kunne reproducere og efterprøve den, og noter om fejlfinding dokumenterede almindelige datakvalitetsproblemer, for eksempel manglende GPS-koordinater eller korrupte målerværdier, med anbefalet håndtering. Siden tilskriver arbejdet en forbedring af effektiviteten i driftsplanlægningen på 10–15 %.

Hvor det går galt

Det meste besvær med datasæt er et faktum om dataene, der blev i ét menneskes hoved.

Granulariteten står ingen steder. Timerækker lagt sammen med kvartersrækker tæller nogle intervaller fire gange. Skriv granulariteten ned i én sætning, for eksempel én række pr. time pr. zone i UTC, og afstem hver kilde efter den, før der summeres.

Et hul læses som nul. Et tomt felt, en null og et 0 betyder tre forskellige ting, og en sum behandler stille en manglende aflæsning som intet forbrug. Manglende GPS-koordinater og korrupte målerværdier var almindelige nok i måleprojektet til at få dokumenteret håndtering. Afgør for hver kolonne, om et hul droppes, udfyldes eller markeres, og skriv valget i datasættets noter.

CSV-dialekten glider. RFC 4180 beskriver det almindelige layout, og virkelige filer afviger fra det: en anden separator, en manglende overskrift, et felt med komma, hvor anførselstegnene er glemt. RFC’en gør overskriftslinjen valgfri og lader den signalere med en MIME-parameter, som en fil kopieret til disk efterlader. Kontrollér hver ny fils første linje mod den forventede overskrift før indlæsning.

En kopi glemmer, hvor den kom fra. Et kurateret udtræk, der er indlæst i et andet system, ligner originalen til forveksling en måned senere. Notér kilde, periode, udtrækstidspunkt og en checksum ved hver kopi, så en rapport kan sige, hvilket udtræk den læste.

Et BigQuery-datasæt havner det forkerte sted. Et datasæts placering fastlægges ved oprettelsen; at flytte det betyder at kopiere eller genskabe datasættet. Alle tabeller i én SQL-forespørgsel skal ligge i datasæt med samme placering, så vælg placeringen før den første indlæsning.

Læs mere

Ordliste