Catalunya 👀 en dades Col·labora al repositori

Qüestions tècniques

Per on començar

El projecte el tenim a GitHub, per col·laborar eficaçment —i mantenir totes les discussions de les propostes en obert.

Imatge del repositori a GitHub

Clona el projecte. Entra a la carpeta, instal·la’l amb npm i i executa npm run dev. Veuràs aixó …

Observable Framework v1.8.0
↳ http://127.0.0.1:3000/

Un nou panell, una nova branca a GitHub, una nova pàgina

Per enviar la vostra proposta, vosaltres (o nosaltres) haureu creat un Issue a GitHub —com s’explica a la pàgina de participació. Aquest Issue tindrà assignada una branca primària.

Per exemple, si heu proposat un panell de dades sobre ‘Consum d’energia elèctrica per municipis i sectors de Catalunya’:

Sigueu breus, concises i utilitzeu sempre kebab-case.

Estructura del teu projecte

.
├─ src
│  ├─ projectes
│  │  └─ nom-projecte
│  │     ├─ data
│  │     │  └─ data-a.json
│  │     │  └─ data-b.json
│  │     │  └─ mapa.json
│  │     │  └─ ...
│  │     └─ index.md
│  └─ docs
│  └─ ...
└─ ...

Un resum del procés:

Us recomanem fer servir GitHub Desktop per gestionar l’accés al repositori o directament des de Visual Studio Code.

Gràfics amb Plot

Plot és una biblioteca de JavaScript desenvolupada per Observable per a la visualització de dades, especialment dissenyada per accelerar l’anàlisi exploratòria de dades. Ofereix una interfície concisa i expressiva que permet crear gràfics sofisticats amb menys codi. Plot està construït sobre d3, però simplifica moltes de les seves operacions per facilitar-ne l’ús.

Exemple de codi per a gràfic de línies

Aquest exemple visualitza dades anuals d’atur per província a Catalunya.

dadesAtur

const lineChart = (width) => Plot.plot({
  width,
  height: width * 0.5,
  marginRight: 60,
  marks: [
    Plot.lineY(dadesAtur, {x: "year", y: "Barcelona", stroke: blue, title: "Barcelona", marker: true, curve: "monotone-x", tip: true}),
    Plot.lineY(dadesAtur, {x: "year", y: "Girona", stroke: yellow, title: "Girona", marker: true, curve: "monotone-x", tip: true}),
    Plot.lineY(dadesAtur, {x: "year", y: "Lleida", stroke: grey, title: "Lleida", marker: true, curve: "monotone-x", tip: true}),
    Plot.lineY(dadesAtur, {x: "year", y: "Tarragona", stroke: purple, title: "Tarragona", marker: true, curve: "monotone-x", tip: true}),
    Plot.text(dadesAtur, Plot.selectLast({x: "year", y: "Barcelona", text: d => "Barcelona", textAnchor: "start", dx: 6})),
    Plot.text(dadesAtur, Plot.selectLast({x: "year", y: "Girona", text: d =>  "Girona", textAnchor: "start", dx: 6})),
    Plot.text(dadesAtur, Plot.selectLast({x: "year", y: "Lleida", text: d =>  "Lleida", textAnchor: "start", dx: 6})),
    Plot.text(dadesAtur, Plot.selectLast({x: "year", y: "Tarragona", text: d =>  "Tarragona", textAnchor: "start", dx: 6}))
  ],
  x: {
    label: "Any",
    tickFormat: d3.format("d")
  },
  y: {
    grid: true,
    label: "Taxa d'atur (%)"
  }
});

Normalment, utilitzareu els gràfics dins de targetes en un panell de dades. Llegiu més sobre les nostres guies sobre com estructurar panells per a aquest projecte i sobre com funcionen les grids a Observable Framework.

A sota es mostra un exemple de quatre cards per a les quatre províncies.

<div class="grid grid-cols-4" style="grid-auto-rows: 240px;">
  <div class="card">
    ${resize((width, height) => lineChartProvince(width, height, "Barcelona", blue))}
  </div>
  <div class="card">
    ${resize((width, height) => lineChartProvince(width, height, "Tarragona", purple))}
  </div>
  <div class="card">
    ${resize((width, height) => lineChartProvince(width, height, "Girona", yellow))}
  </div>
  <div class="card">
    ${resize((width, height) => lineChartProvince(width, height, "Lleida", grey))}
  </div>
</div>

Més examples de gràfics aqui.

Mapes amb Mapbox

Mapbox és una llibreria per produïr mapes interactius en aplicacions web. En aquesta secció, explorarem com utilitzar Mapbox a Observable Framework per crear, per example, mapes coroplètics per mostrar dades geoespacials.

Exemple de codi per a un mapa bàsic

Aquest exemple mostra com integrar un mapa bàsic de Mapbox dins d’Observable.

const simple = display(document.createElement("div"));
simple.style = "height: 480px;";

const map = new mapboxgl.Map({
  container: simple,
  accessToken: MAPBOX_TOKEN,
  style: 'mapbox://styles/fndvit/clx4zgywv00af01qq1jp42apa',
  center: [2.1745, 41.404],
  zoom: 16,
  pitch: 62,
  bearing: -20
});

invalidation.then(() => map.remove());

Exemple de codi per a un mapa de coropletes

Aquest exemple mostra com crear un mapa coroplètic, que fa servir color per representar la variable estadística al mapa. En aquest cas es visualitzen dades d’atur per província.

const choropleth = display(document.createElement("div"));
choropleth.style = "height: 540px;";

const map = new mapboxgl.Map({
  container: choropleth,
  accessToken: MAPBOX_TOKEN,
  style: 'mapbox://styles/fndvit/clvnpq95k01jg01qz1px52jzf',
  center: [2.1745, 41.65],
  zoom: 6.8
});

const unemploymentData = [
  { province: "Barcelona", rate: 8 },
  { province: "Girona", rate: 6 },
  { province: "Lleida", rate: 5 },
  { province: "Tarragona", rate: 7 }
];

const createColorExpression = (data) => {
  const colorExpression = [
    "step",
    ["get", "rate"],
    "#f0f0f0",
    5,
    "#fec3b8",
    6,
    "#c289a8",
    7,
    "#885198",
    8,
    "#4c1787"
  ];

  const matchExpression = ["match", ["get", "name"]];

  data.forEach((entry) => {
    matchExpression.push(entry.province, entry.rate);
  });

  matchExpression.push(0);

  colorExpression[1] = matchExpression;

  return colorExpression;
};

map.on('load', function () {
  map.addSource('unemployment', {
    type: 'geojson',
    data: 'https://raw.githubusercontent.com/codeforamerica/click_that_hood/master/public/data/spain-provinces.geojson'
  });

  map.addLayer({
    id: 'unemployment-layer',
    type: 'fill',
    source: 'unemployment',
    paint: {
      'fill-color': createColorExpression(unemploymentData),
      'fill-opacity': 0.5,
      "fill-outline-color": createColorExpression(unemploymentData)
    }
  }, "waterway");
});

Carregadors de dades

Els carregadors de dades (data loaders) permeten generar instantànies de dades pre-processades durant el procés de construcció del projecte. Poden ser escrits en qualsevol llenguatge de programació i són útils per accedir, transformar i preparar dades per a la seva visualització.

Avantatges dels carregadors de dades

Exemple de codi per a un carregador de dades en JavaScript

Suposem que volem carregar dades dels embassaments a Catalunya des de l’API del Portal de Transparència de Catalunya.

const response = await fetch("https://analisi.transparenciacatalunya.cat/resource/gn9e-3qhr.json?$limit=32877");
if (!response.ok) throw new Error(`fetch failed: ${response.status}`);
const json = await response.json();

const data = json.map((d) => {
  const capacity = (100 * d.volum_embassat) / d.percentatge_volum_embassat;
  const date = new Date(d.dia);
  const pct = +d.percentatge_volum_embassat;
  const level = +d.volum_embassat;
  return { date, pct, level, capacity };
}).sort( (a,b) => a.date - b.date);

process.stdout.write(JSON.stringify(data));

Aquest carregador de dades obté dades des d’una API, les transforma al format adequat i genera un fitxer JSON amb les dades dels embassaments.

Com utilitzar els carregadors de dades

Si el carregador aquest es diu per exemple embassaments.json.js, haurà generat un fitxer embassaments.json: ara pots accedir-hi des del client utilitzant FileAttachment.

const embassaments = FileAttachment("data/dades.json").json();

FileAttachment retorna una Promise, podeu utilitzar les dades en un bloc de codi diferent només cridant embassaments.

embassaments

Per a més informació i exemples sobre com escriure carregadors de dades en diferents llenguatges, pots visitar la documentació d’Observable Framework.

Bones pràctiques

Per mantenir el projectes ordenat i comprensible —donat que es un projecte col·laboratiu— cal que tingueu en compte aquestes bones pràctiques per mantenir el codi ben organitzat i ben comentat.