Nasjonale prøver på kartet

De siste par ukene har jeg satt av litt tid hver kveld til å lage en liten tjeneste som viser resultatene fra de nasjonale prøvene geografisk på en skikkelig oversiktelig måte. Siden dette er en uformell øvelse i datadreven borgerjournalistikk tenkte jeg selve prosessen kunne være interessant å dokumentere for meg selv og muligens også for andre.

Det tok 15 kvelder og én arbeidsdag. Gitt at jeg har to små barn hvor den yngste gjerne skal bæres en timer hver kveld og den eldste våkner i 0600-tiden kan jeg umulig tenke meg at jeg har klart å bruke mer enn 2 timer i snitt per dag. Så rundt regnet gikk det en arbeidsuke.

Tjenesten står nå live på skoleporten.bengler.no.

Merk: Dette er ikke en spisset, gjennomarbeidet tekst, men heller en slumsete prosjektdagbok

Kveld 1

Skoleporten skal kjøre på:

  • Sinatra – Minirammeverk skrevet i Ruby
  • MongoDB – NoSQL database
  • JQuery – Fint Javascript hjelpebibliotek
  • CSS3 / HTML5

Jeg har ikke brukt noe av dette før så jeg leser dokumentasjon og setter opp prosjektet med Sinatra og MongoDB, en ny og artig database som kjører Javascript (wot). Til slutt spar jeg dataene fra excel-arket til Dagbladet inn i MongoDB.

Kveld 2

Så, hvor ligger disse skolene? Sånn på kartet.

Skoleporten har en asp.net løsning (i 2010, omg) som noen nisser har bygd for de. Den er så langt unna REST man kommer og når du søker etter Kampen Skole får du en URL på formen:


http://skoleporten.utdanningsdirektoratet.no/skolesoktreff.aspx?sokestreng=a2FtcGVu0&url=http://skoleporten.utdanningsdirektoratet.no/skolesoktreff.aspx%3fsokestreng%3d%26url%3dhttp://skoleporten.utdanningsdirektoratet.no/enhet.aspx%3fenhetsid%3d974589788%26vurderingsomrade%3dResultatoversikt%26skoletype%3d0%26enhetsid%3d974589788&enhetsid=974589788

OMG

Det er sikkert mulig baklengsengineere javascriptene deres for å finne ut hvordan de lager disse kaudervelske søkestrengene. Men hei, vi betaler for disse skolene. Noen må da kunne fortelle oss hvor de er.

Joda, på den superhjelpsomme portalen norge.no finner jeg dette i FAQen:

Hvor finner jeg adresser til skoler og barnehager?

Adresser til barnehager, grunnskoler og andre skoleslag finner du på Pedlex Norsk Skoleinformasjon

Så bra! Jeg tar meg en tur dit.

Fett, men hei, vent. Ser ikke adressen litt annerledes ut? Nei! Neeei! NEEEEEI! De har rendret teksten som grafikk. Men hvorfor?! Ah, selvfølgelig. De har en bok til salgs til kroner 215,- som de har lyst til å selge oss. Prisen for dette produkt i digital form må jeg maile de for å få. Bra saker. Takk norge.no for at dere lenket meg til denne uselviske og nyttige kilden.

Kanskje jeg skal skrape disse bildene ut av sidene til PedLex og kjøre OCR på de. Så hvordan får jeg kjørt OCR da? Hm, Tesseract, en urgammel open source OCR-maskin finnes i macports. Google finansierte open sourcingen av den for et par år siden så den er sikkert ikke helt ute. Om man gjør bildene litt likere innscannede dokumenter ved å skalere bildene til det tredobbelte, thresholde de og kjører Tesseract med en norsk treningsfil så ser det faktisk ut som det funker relativt bra. Men vent, det må være en bedre måte enn å gjøre tegngjenkjenning på 3000 GIFer.

Hva med Google Places? Som et ledd i sin katalogisering av det norske samfunnet vet jo Google faktisk hvor disse skolene er. Faktisk.

Så hvordan ser Places APIet ut? Det viser seg at Google har begynt å stramme inn litt i APIene sine og krever her at man er en slags ‘kunde’ av Google og søker om å få tilgang hvorpå man må skrive under på blant annet:

  • All developers wishing to use the service must already have an Adsense account, or must create one prior to applying.
  • Applications that wish to use the API must only issue queries in response to end user actions.
  • The results of every search made by applications using this API must be shown to a user.
  • Applications may not reorder or manipulate Search results.
  • Applications may not store any Place data permanently except References and IDs.
  • Place information collected using this API, or any data derived from it, such as Place location corrections, can not be distributed in any way, such as through an API, without the express permission of Google.

Så kanskje ikke det, siden jeg bryter mot 90% av vilkårene. Jeg kunne alltids skrapt det ut av Place-søkene, men det er garantert et brudd på de samme vilkårene det også. Vi vet heller ikke om Places vet om absolutt alle skolene.

Ok, en annen strategi. Hva med Google-søk på skolenavn avgrenset til skoleporten.utdanningsdirektoratet.no, oppslag i skoleporten med påfølgende skraping av adresse som vi slår opp i Googles geokoder? Det er skjøre saker og om noen bestemmer seg for å endre noe på skoleporten eller slenge disse sidene i robots.txt går det i dass, men er kanskje hakket bedre enn å OCRe 3000 GIFer. Får vi treff? Jada=. Holla!

Kveld 3 – Skrap skrap

Det første forsøket ser slik ut:

puts "\nGeocoding #{School.count} schools. Plz wait.\n\n"
School.find(:all)[0..1].each do |s|
puts "-- #{s.name} / #{s.county} / #{s.municipality} (#{s.normalized_tests.length} tests)"
url = "http://www.google.no/search?hl=en&q=" + CGI.escape("site:skoleporten.utdanningsdirektoratet.no -oversikt \"#{s.name}\"")
doc = Nokogiri::HTML(open(url))
address = doc.css('#ires .s')[0].text.match(/.*?\.(.*?\..*?)\./)[1].strip.gsub('.',',')
puts "School address: #{address}"
bounds = Geokit::Geocoders::GoogleGeocoder.geocode(s.municipality, :bias => 'no').suggested_bounds
res = Geokit::Geocoders::GoogleGeocoder.geocode("#{address}", :bias => bounds)
puts res.inspect
puts "\n\n"
sleep 0.8
end

Og visst gir det oss ikke:

-- Holla ungdomsskole / Telemark / Nome (3 tests)
School address: Kirkebakken 18, 3830 ULEFOSS
Provider: google
Street: Kirkebakken 18
City: Ulefoss
State: Telemark
Zip: 3830
Latitude: 59.2793002
Longitude: 9.2633128
Country: NO
Success: true

Holla! Bare 1 av de 5 første feiler. Nå på en enkodingsfeil i geokodingsbiblioteket jeg brukte for å gjøre livet mitt litt enklere. Herlig. Det er litt gammelt og har noen problemer relatert til Ruby 1.9 og Unicode. Som gode internettborgere rapporterer vi feilen, forker koden på github og legger inn de bittesmå fiksene våre.

Det er selvfølgelig noen flere små snags, men med litt taktisk wrangling er det stort sett bare skoler som:

  1. BELGIUMSHAPE International School Norwegian Sec / Utland / Utland (6 tests)
  2. BELGIUM – Scandinavian school in Brussels (Ecole R / Utland / Utland (6 tests)
  3. BOLIVIA – Colegio Noruego / Utland / Utland (6 tests)

som feiler og det ser ut som det er under 1% som ikke får noen adresse. Bolivia! Disse kan vi håndslå i excel etterpå om vi gidder. Fest!

Kveld 4 – Geokodeagogo

Dette gikk jo ganske bra. Det er sansynligvis et TOS-brudd å gjøre disse søkene og Google sperrer meg etter rundt 256 søk (noen hos Google må ha estetisk sans for 2^n). Det er noen skoler med utenlandsadresser og noen navn med stor diskrepans mellom navnet i nasjonale prøver og i den nåværende versjonen av SKoleporten. Men det er fortsatt ikke mer enn 50 etter å ha kjørt de første 2100 skolene. I tillegg feiler Google en del på adresser av typen Sandshamn, 6089 SANDSHAMN. Disse virker fint på maps.google.com, men feiler i APIet. Kanskje jeg får noe om jeg har en fallback som bare bruker stedsnavn. Det er virkelig stas å sjekke treffene jeg får. Ofte står det en skole plantet midt i satelittbildet. For småsteder mangler skoleporten gateadresser. Kanskje kommer posten fram uansett, men jeg får litt dårlig treff. Det får vi leve med.

Man får tårer i øynene av å tenke på at den danske staten leverer geokoding som en tjeneste på lik linje med ferskt vann i springen, mens vi her i landet må lene oss på Google eller aktører vi må skrive kontrakter med oppsigelsestid for å finne ut hvor en adresse er.

Mens jeg venter på en av-svartelisting fra Google bygger jeg en liten eksport til CSV slik at jeg kan gi dere disse dataene tilbake på Google Spreadsheet så snart det er ferdig.

Kveld 5 – Jern i skapet

Alle har rett noe de kan kalle et eget hjem. Vi har en urgammel maskin (2.6Ghz Xeon / 2 cores) som det for tiden ikke kjører noe tungt på. Den sitter i skapet sitt på coloc-rommet til snill snille Domeneshop nede ved Akerselva. Det står i andre enden av en fiber som går rett til NIX. Det bør holde. Eneste problemet er at den ikke har vært brukt til noe nytt på evigheter og kjørte inntil ikveld Ubuntu Hardy Heron 8.04 . For å brukes til noe nyttig må den oppgraderes til en moderne Ubuntu.

Det går med tre kvarter mens Ubuntu tålmodig river ifra hverandre og setter sammen et system bestående av en en bunke pakker og deres utallige avhengigheter. Med ett grep bygger den det om slik det står og presenterer det i ny støpning. Millioner av kodelinjer, et utall ørsmå tannhjul som griper inn i hverandre. Resten av kvelden går dermed med til å oppgradere og avknekke ting som faller i gulvet i prosessen.

Kveld 6 – These are not the schools you are looking for.

Kjære dagbok. M har trent i kveld. Begge barna gråt hele tiden. Nå sover alle sammen. Titter litt på resultatene fra geokodingen. 10 sprø verdier. Rundt 90 mangler ellers. Det er bare to som er store: Max Tau og Steinern i Oslo. Resten ligger i Bolivia eller på små nes langs kysten. Jeg forsøkte å geokode 10 av de manuelt og det er en royal rumpesmerte. Mange av de finnes hverken av Google Places, 1881.no eller andre kilder. Man ender opp med å søke etter kommunene eller stedsnavnene og det hele blir heller omtrentlig. Lurer på om jeg skal la disse ligge.

Kveld 7 – Tidlig i seng

Tidlig i seng, men stod opp klokken 0200 og la til alle markørene på et Google-kart.

Kveld 8 – Første pass GUI

Mens jeg får det minste barnet til å sove leser jeg meg opp på:

  • AJAX med JQuery siden jeg stort sett har brukt Prototype før
  • Canvas tegning av GMaps markører siden jeg skal rendre disse programmatisk

Jobber litt med stiling. Drar opp GMaps til fullskjerm og ser på CSS3.

Kveld 9 – Markører over AJAX I

Kikker på Google Table Fusion etter å ha kommet over denne sørgelige anvendelsen? hos the Guardian. Tenker det er et fint verktøy for noen, men knapt komplett for oss med tanke på at jeg ikke har ensartede markører og trenger å tegne fine markører for skolene. Det er synd, siden det er superfint at Google kan rendre digre datamengder som overlays på GMaps for oss med to linjer kode. Sikkert nyttig til noe annet.

Man kan tross alt ikke hente 2980 markers til Google maps så det må skrives noe javascript AJAX for å hente markører når man drar på kartet. Bruker litt tid på å finne ut av Geo2D within søket til Mongodb og banke dette inn i jQuery sitt getJSON kall.

Tror jeg trenger elevantall på hver skole. For det vil jeg vel visuelt indikere? Ser at Google har et JSON-kall som jeg kan bruke istedenfor denne skrapingen av googlesøk med Nokogiri. Det ser lurt ut. Siden Google sikkert ikke er like illsinte på svartelisting i et offisielt API.

Kveld 10 – PLZ WAIT, OK – Normalizing test results.

Nå begynner det å bli relevant å se på de faktiske testdataene. Jeg normaliserer de på en skala fra 0 til 1 i forhold til årstrinn (5. klasse løper fra 1-3, mens 8. løper fra 1-5) slik at vi kan slå sammen resultater for skoler som både er ungdomsskoler og barneskoler. I tillegg skriver jeg snittverdien inn i hver skole, kommune og fylke. Takket være en del kål med Mongoid, MongoDB-abstraksjonen for Ruby som jeg har valgt å bruke, tar dette 2 timer istedenfor 0.5. Kildekoden må ingen lese.

Kveld 11 – Size of school, size of problem may be.

Vi trenger å finne ut hvor store skolene er. Det å gjøre vanlige Google søk fikk meg svartelistet rundt hvert 256. kall hvorpå det tok rundt en halvtime for Google å tillate søk igjen. Ser derfor på JSON-APIet isteden. Ser fint ut. De viser seg imildertid at skoleporten AJAXer inn tabellen med elevantall. Gaargh. Who are these people? Må derfor Google, gjøre oppslag på skoleporten, finne tak i AJAX-kallet, hente HTML-fragmentet fra URLen den bruker og parse ut verdien av tabbelen i den siste cellen på andre linje. Takkskarruha.

Det virker, men tar litt tid. Med en del feilsøking og presisering av søket er det alt som blir gjort ikveld. Det er grenser for hvor nøyaktige det blir på denne måten. Om noe blir denne prosessen et slags langtrukkent argument for å sette APIer på offentlige tjenester.

Kveld 12 – Markører over AJAX II – The Revenge of Front End

Vi kan ikke hente 2930 kartmarkører og sette de på kartet. Det er altfor tungt. Vi kan bare vise de som er innenfor kartet til enhver tid. For utzoomede bilder må vi vise kommuner og fylker. Dette krever at Google Maps må snakke med serveren hver gang du flytter på kartet. Vi må også fjerne markører som detter utenfor delen av kartet vi ser på. Gmaps har en del fine funksjoner som forenkler dette, men vi må fortsatt skrive en liten MarkerManager som holder orden på markørene vi har satt.

Kveld 12 – Tegne kartmarkører med HTML5 canvas

Starter med en modifisert utgave av dette eksempelet. På kort tid har jeg for første gang fargelagte små infoboller for hver skole. Begynner med en mapping i HSL-fargerommet. Skolene legges i farge mellom rødt og grønt. De som ligger midt på treet blir gulbrune. I tillegg legger jeg på en sigmoid-kurve av dette slaget for å aksentuere forskjellene. Lurer på om ikke blått til oransj hadde vært en like effektiv, og litt mindre rotete fremstillingen av resultatene.

Kveld 13 – Estetisk frobbing av markører og kart.

Fjerner gradientene på markørene og legger til skalering på elevantall. Sørger for at markørene faktisk er sentrerte koordinatene sine. Elevantallet er ganske random vise seg. Det er små skoler i distriktene som dukker opp med 500 elever presumptivt fordi jeg har sanket tall fra hele kommunen eller fylket de ligger i. Håper utdanningsdirektoratet kan gi meg en fin liste over hvor store disse skolene er.

Markørene på kartet må bli tydeligere. Forsøker meg på å få tak i DOM-elementet som holder selve kart-flakene til Google for å gjøre de transparente mot en mørk bakgrunn. Viser seg å være mulig, men litt involvert og flaky om Google skulle oppdatere måten kartkomponenten er pakket på. Men hei, Google har laget stiling av kartene. Jeg har nesten ikke sett dette i bruk selv om det har vært live i månedsvis. Man kan skru av og på innholdstyper og bestemmer fargene deres helt etter eget forgodtbefinnende. Stas. Kartet blir mørkt og nattklubbaktig for å vise fram markørene. Går over og gjør markørene enda mer Walter Gropius-aktige.

Legger også ut prosjektet offentlig på Github. Koden, databasedumper, grunnlagsdataene, alt sammen.

Kveld 14 – Klargjøring av prodmiljø, visning av kommuner, twitter

Aftenposten ledet med nasjonale prøver i dag. Saken handlet om hvordan Oslo-skolene unntar de svakeste elevene fra prøvene for å heve resultatene. Det hadde vært interessant å se denne informasjnen sammen med prøveresultatene, men det får vente.

Klargjør produksjonsmiljøet med rvm og riktig ruby versjon (1.9.2) og ser på måter å kjøre sinatra sammen med lighttpd. Ser greit ut.

Når noen zoomer ut må vi gå over til å vise kommuner istedenfor skoler. Skriver støtte for dette. Tar en halvtime.

Oppretter en twitterkontoen @skoleporten. :)

Kveld 15 – Visning av resultater fra enkeltskoler i popups

Setter opp henting av data med JSON over AJAX for hver skole. Interessant informasjondesignsoppgave. Hva er den enkleste måten å vse informasjonen på. Gruppering, klare hierarkier og fargekoder som overenstemmer med hovedvisningen er sikkert klokt. Hey, JQuery har en liten templating engine så jeg kan kjøre JSON rett over i templates jeg har skrevet i HAML. Boggle.

Dag 16 – 3. november 2010

Setter av et par tre timer på jobben til å ferdigstille stiling av popups og skrive en about-tekst. Noier ut da jeg ser at ruby på serveren bruker rundt 200ms på serveren på å pakke 400 markører i JSON. Bruker en time på å se etter optimeringsforslag og roer meg ned da Alex foreslår et JSON-bibliotek med det poetiske navnet Yajl (yeah, Yet Another Json Library – om det hadde stått som et onematopoetikon i en tegneserie hadde det vært dødsralling) som kutter tiden ned til mellom 1/2 og 1/3 på benchmarkene. Laptopen min gjør dette på 1/5 av tiden forresten. Som før nevnt, gammel hardware.

Anways, vi står nå live på skoleporten.bengler.no.

Vist 5689 ganger. Følges av 9 personer.

Kommentarer

Herlig dokumentasjon på data-wrangling!

Kunne f.eks Gowalla eller Foursquare være til hjelp for å få bedre lokalisasjonsdata?

Kanskje, men jeg tror det som hadde vært det beste er bare å få disse adressene levert ferdig pakket over disk fra utdanningsdirektoratet. Har sendt de en mail nå i kveld hvor jeg ber om å få prøvene for de tre siste årene sammen med autorative tall for elevantall, fritaksprosent fra prøvene og andre godis.

Respect :-) …likte særs godt kveld 2.

Kredd! Det hørtes også veldig gøy ut. Spent på hva du får som svar. Fritaksprosenten er jo vinklet som skoleboling i nyhetene i dag.

Jeg er, som vanlig, imponert. Takk!

Bra tiltak, selv om jeg (som nybakt far) kjenner at jeg blir litt for interessert. Er det mulig å få tak i tall fra enda lengre tilbake?

Hei Rune, prøvene er gjennomført siden 2004 (historikk) og om du sender en mail til Utdanningsidrektoratet kan det hende du får de løs om de ikke regner det som særs arbeidskrevende. Det er verdt å nevne at resultatene er normalfordelt hvert år så om du lager tidsserier får du ut hvordan skolen gjorde det relativt til alle landets skoler det året. Om du får de løs så send de gjerne over til even at origo.no – veldig fint troll btw.

Takk for svar, og takk for trollkommentar! Jeg tror jeg venter litt med å ta kontakt, jeg har en følelse at det er et prosjekt som trenger overskudd og tid!

Berusende og inspirerende prosjektdagbok. Vi er mange som kan lære noe om nytten av å dele med omverdenen.

Takk.

Takk! Teksten over er for første versjon av prosjektet. Det som står live på skoleporten.bengler.no nå bruker resultatsett for 2009 og 2010 overlevert rett fra Utdanningsdirektoratet samt adresselister jeg genererte selv på GSI (Grunnskolens Informasjonssystem) – et halvobskurt rapportopplegg som er offentlig tilgjengelig og som vet en god del om skolene – f.eks besøksadresser og elevtall. Heldigvis nevnte utdanningsdirektoratet denne i bisetning i brevvekslingen vår og det sparte meg en del tid i siste runde samt hevet datavkvaliteten forbi det jeg kunne levert med skraping av skoleporten.udir.no selv.
Jeg har skrevet en logg om arbeidet med den nye versjonen også, men den består stort sett av problemene med å lage tidsserier av resultatene når skoler og kommuner driver og skifter navn mellom år (siden udir bektet å levere datagrunnlaget med skikkelig nøkler for skolene). Muligens noe kjedelig lesning, men jeg skal se om jeg får lagt den ut snart.

Annonse