Public
Edited
Mar 16, 2023
3 forks
Insert cell
Insert cell
embed = require("vega-embed@5")
Insert cell
vegalite = require("@observablehq/vega-lite@0.1")
Insert cell
import { aq, op } from '@uwdata/arquero'
Insert cell
viewof trains = aq // viewof shows the table view, but assigns the table value
.fromCSV(await FileAttachment('small_trains.csv').text())
.view({ height: 240 })
Insert cell
viewof gares = aq // viewof shows the table view, but assigns the table value
.fromCSV(await FileAttachment('garesdep@1.csv').text())
.view({ height: 240 })
Insert cell
trainswithdate = trains.derive({date:d=>op.datetime(d.year, d.month-1)})
Insert cell
trainsByStationsAndDate = trainswithdate.groupby('date', 'departure_station', 'arrival_station',).rollup({total_num_trips: d => op.mean(d.total_num_trips), num_late_at_departure: d=>op.mean(d.num_late_at_departure),num_arriving_late: d=>op.mean(d.num_arriving_late)})
Insert cell
trainsByStations = trainsByStationsAndDate.groupby('departure_station', 'arrival_station').rollup({total_num_trips: d => op.sum(d.total_num_trips), num_late_at_departure: d=>op.sum(d.num_late_at_departure),num_arriving_late: d=>op.sum(d.num_arriving_late)}).derive({ratio_late_at_departure: d=>d.num_late_at_departure/d.total_num_trips})
Insert cell
Insert cell
embed({
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
width: 500,
height: 300,
data: {url: "https://mjlobo.github.io/teaching/eivp/departements.json",
format: {type: "topojson", feature: "departements"} // on doit indiquer quels objets on va dessiner
},
projection: {type :"mercator" },
mark: {
type: "geoshape"
}
})
Insert cell
Insert cell
embed({
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
width: 500,
height: 300,
data: {url: "https://mjlobo.github.io/teaching/eivp/departementswithid.json",
format: {type: "topojson", feature: "departements"}
},
projection: {type :"mercator" },
mark: {
type: "geoshape",
stroke: 'light-grey',
fill: 'grey',
strokeWidth: 0.5
}
})
Insert cell
Insert cell
garespardepartement = gares.groupby("CODE_DEP").count()
Insert cell
embed({
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
width: 500,
height: 300,
data: {
url: "https://mjlobo.github.io/teaching/eivp/departementswithid.json",
format: {type: "topojson", feature: "departements"}
},
transform: [{
lookup: "id", //lookup correspond à la clé dans le tableau d'origine, dans ce cas le topojson
from: {
data: {
values: garespardepartement.objects() // le tableau ou on va chercher les données
},
key: "CODE_DEP", // la clé dans le tableau secondaire
fields: ["count"] // les champs qu'on va recupérer
},
default:'0' // la valeur par default si il n'y a pas de match. Même si on veut un nombre, on doit l'écrire comme un string
}],
projection: {
type: "mercator"
},
mark: "geoshape",
encoding: {
color: {
field: "count",
type: "quantitative"
}
}
})
Insert cell
Insert cell
Insert cell
embed({
$schema: "https://vega.github.io/schema/vega-lite/v3.json",
width: 400,
height: 300,
layer: [
{
data: {
url: "https://mjlobo.github.io/teaching/eivp/departements.json",
format: {
type: "topojson",
feature: "departements"
}
},
projection: {
type: "mercator"
},
mark: {
type: "geoshape",
fill: "lightgray",
stroke: "white"
}
},
{
data: {
values: gares.objects()
},
projection: {
type: "mercator"
},
mark: "circle",
encoding: {
longitude: {
field: "X_WGS84",
type: "quantitative"
},
latitude: {
field: "Y_WGS84",
type: "quantitative"
},
size: {"value": 20},
color: {"value": "steelblue"}
}
}
]
})
Insert cell
Insert cell
Insert cell
embed({
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
width: 400,
height: 300,
layer: [
{
data: {
url: "https://mjlobo.github.io/teaching/eivp/departements.json",
format: {
type: "topojson",
feature: "departements"
}
},
projection: {
type: "mercator"
},
mark: {
type: "geoshape",
fill: "lightgray",
stroke: "white"
}
},
{
params: [
{
name: "selected", //la variable qui va stocker l'objet(s) selectionné
select: {type: "point", "on": "mouseover"} //type de selection, ici on va sélectionner un point lorsque la souris survole le point
}
],
data: {
values: gares.objects()
},
projection: {
type: "mercator"
},
mark:
{
type: "circle",
tooltip: true
},
encoding: {
longitude: {
field: "X_WGS84",
type: "quantitative"
},
latitude: {
field: "Y_WGS84",
type: "quantitative"
},
tooltip: [{field: "LIBELLE", "type": "nominal"}],
size: {
condition: {param: "selected", "value": 200, "empty": false}, // ici la condition veut dire que si l'objet correspond à l'objet selected, la taille sera 200, sinon 50. Le paramètre permet de dire que si la sélection est vide on la considère pas comme dans l'objet "selected".
value: 50
},
color: {"value": "steelblue"}
}
}
]
})
Insert cell
Insert cell
Insert cell
maxNumTrains = trainsByStations.rollup({ maxNumTrains: d => op.max(d.total_num_trips) }).objects()[0].maxNumTrains
Insert cell
embed({
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
width: 600,
height: 300,
params:
[
{
name: "MinNumTrains", "value": 0,
bind: {"input": "range", "min": 0, "max": maxNumTrains, "step": 100} // on definit le type de l'input et les valeurs minimales et maximales possibles
}
],
layer: [
{
data: {
url: "https://mjlobo.github.io/teaching/eivp/departements.json",
format: {
type: "topojson",
feature: "departements"
}
},
projection: {
type: "mercator"
},
mark: {
type: "geoshape",
fill: "lightgray",
stroke: "white"
}
},
{
data: {
values: gares.objects()
},
projection: {
type: "mercator"
},
mark: {type: "point"},
encoding: {
longitude: {
field: "X_WGS84",
type: "quantitative"
},
latitude: {
field: "Y_WGS84",
type: "quantitative"
},
tooltip: {field: "LIBELLE", "type": "nominal"},
size: {"value": 20},
color: {"value": "steelblue"}
}
},
{ //on ajoute une layer pour représenter les trajets
data: {
values: trainsByStations.objects()
},
transform: [
{
lookup: "departure_station", // on va chercher les coordonnées des gares avec lookup
from: {
data: {values: gares.objects()},
key: "LIBELLE",
fields: ["X_WGS84", "Y_WGS84"],
},
as: ["X_WGS84_departure", "Y_WGS84_departure"]
},
{
lookup: "arrival_station",
from: {
data: {values: gares.objects()},
key: "LIBELLE",
fields: ["X_WGS84", "Y_WGS84"],
},
as: ["X_WGS84_arrival", "Y_WGS84_arrival"]
},
{filter: "datum.X_WGS84_departure != null && datum.Y_WGS84_departure != null && datum.X_WGS84_arrival != null && datum.Y_WGS84_arrival != null && datum.total_num_trips>MinNumTrains"} //on ajoute un filtre pour ne pas considerer les trajets avec des gares qui n'ont pas de coordonnées, et pour utiliser le valeur venant du slider.
],
projection: {
type: "mercator"
},
mark: "rule",
encoding: {
longitude: {
field: "X_WGS84_departure",
type: "quantitative"
},
latitude: {
field: "Y_WGS84_departure",
type: "quantitative"
},
longitude2: {
field: "X_WGS84_arrival",
type: "quantitative"
},
latitude2: {
field: "Y_WGS84_arrival",
type: "quantitative"
},
color: {"value": "steelblue"}
}
}
]
})
Insert cell
Insert cell
Insert cell
embed({
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
width: 400,
height: 300,
hconcat:[ // les vues dans se tableau vont être disposées horizontalement
{
layer: [
{
data: {
url: "https://mjlobo.github.io/teaching/eivp/departements.json",
format: {
type: "topojson",
feature: "departements"
}
},
projection: {
type: "mercator"
},
mark: {
type: "geoshape",
fill: "lightgray",
stroke: "white"
}
},
{
params: [
{
name: "selected", //la variable qui va stocker l'objet(s) selectionné
select: {type: "point", "on": "mouseover"} //type de selection, ici on va sélectionner un point lorsque la souris survole le point
}
],
data: {
values: gares.objects()
},
projection: {
type: "mercator"
},
mark:
{
type: "circle",
},
encoding: {
longitude: {
field: "X_WGS84",
type: "quantitative"
},
latitude: {
field: "Y_WGS84",
type: "quantitative"
},
tooltip: [{field: "LIBELLE", "type": "nominal"}],
size: {
condition: {param: "selected", "value": 200, "empty": false}, // ici la condition veut dire que si l'objet correspond à l'objet selected, la tailler sera 100, sinon 50. Le paramètre permet de dire que si la sélection est vide on la considère pas comme dans l'objet "selected".
value: 50
},
color: {"value": "steelblue"}
}
}
]},
{
layer: [
{
data: {
url: "https://mjlobo.github.io/teaching/eivp/departements.json",
format: {
type: "topojson",
feature: "departements"
}
},
projection: {
type: "mercator"
},
mark: {
type: "geoshape",
fill: "lightgray",
stroke: "white"
}
},
{
params: [
{
name: "selected", //la variable qui va stocker l'objet(s) selectionné
select: {type: "point", "on": "mouseover"} //type de selection, ici on va sélectionner un point lorsque la souris survole le point
}
],
data: {
values: gares.objects()
},
projection: {
type: "mercator"
},
mark:
{
type: "circle",
},
encoding: {
longitude: {
field: "X_WGS84",
type: "quantitative"
},
latitude: {
field: "Y_WGS84",
type: "quantitative"
},
tooltip: [{field: "LIBELLE", "type": "nominal"}],
size: {
condition: {param: "selected", "value": 200, "empty": false}, // ici la condition veut dire que si l'objet correspond à l'objet selected, la tailler sera 100, sinon 50. Le paramètre permet de dire que si la sélection est vide on la considère pas comme dans l'objet "selected".
value: 50
},
color: {"value": "steelblue"}
}
}
]
}
]
})
Insert cell
Insert cell
trainsByStationFiltered = trainsByStations.semijoin(gares,['arrival_station', 'LIBELLE']).semijoin(gares,['departure_station', 'LIBELLE']).orderby('total_num_trips').reify().slice(0,40)
Insert cell
embed({
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
hconcat: [
{
width:300,
height:300,
data: {
values: trainsByStationFiltered.objects()
},
params: [
{
name: "selected",
select: {type: "point"}
}
],
config: {
view: {
strokeWidth: 0,
step: 13
},
axis: {
domain: false
}
},
mark: "rect",
encoding: {
x: {
field: "departure_station",
type: "nominal"
},
y: {
field: "arrival_station",
type: "nominal",
},
color: {
field: "total_num_trips",
type: "quantitative",
legend: {
"title": null
}
},
stroke: {
condition: {
param: 'selected', value: 'orange', "empty": false
},
value:null
}
}
},
{
layer: [
{
data: {
url: "https://mjlobo.github.io/teaching/eivp/departements.json",
format: {
type: "topojson",
feature: "departements"
}
},
projection: {
type: "mercator"
},
mark: {
type: "geoshape",
fill: "lightgray",
stroke: "white"
}
},
{
data: {
values: gares.objects()
},
projection: {
type: "mercator"
},
mark: {type: "point"},
encoding: {
longitude: {
field: "X_WGS84",
type: "quantitative"
},
latitude: {
field: "Y_WGS84",
type: "quantitative"
},
tooltip: {field: "LIBELLE", "type": "nominal"},
size: {"value": 20},
color: {"value": "steelblue"}
}
},
{ //on ajoute une layer pour représenter les trajets
data: {
values: trainsByStationFiltered.objects()
},
params: [
{
name: "selected",
select: {type: "point"}
}
],
transform: [
{
lookup: "departure_station", // on va chercher les coordonnées des gares avec lookup
from: {
data: {values: gares.objects()},
key: "LIBELLE",
fields: ["X_WGS84", "Y_WGS84"],
},
as: ["X_WGS84_departure", "Y_WGS84_departure"]
},
{
lookup: "arrival_station",
from: {
data: {values: gares.objects()},
key: "LIBELLE",
fields: ["X_WGS84", "Y_WGS84"],
},
as: ["X_WGS84_arrival", "Y_WGS84_arrival"]
},
{filter: "datum.X_WGS84_departure != null && datum.Y_WGS84_departure != null && datum.X_WGS84_arrival != null && datum.Y_WGS84_arrival != null"} //on ajoute un filtre pour ne pas considerer les trajets avec des gares qui n'ont pas de coordonnées, et pour utiliser le valeur venant du slider.
],
projection: {
type: "mercator"
},
mark: "rule",
encoding: {
longitude: {
field: "X_WGS84_departure",
type: "quantitative"
},
latitude: {
field: "Y_WGS84_departure",
type: "quantitative"
},
longitude2: {
field: "X_WGS84_arrival",
type: "quantitative"
},
latitude2: {
field: "Y_WGS84_arrival",
type: "quantitative"
},
color: {
condition: {param: 'selected', value: 'orange', empty: false},
value: 'steelblue'
}
}
}
]
}
]
})
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more