Published
Edited
Feb 22, 2022
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Inputs.table(co2Df)
Insert cell
<html>
<head>
<style>
.vizDiv {
border: 1px solid #D3D3D3;
width: 1000px;
height: 1000px;
text-align: left;
padding: 20px;
}
.leftDiv {
width: 18%;
float:left;
padding-right: 15px;
}
.rightDiv {
width: 80%;
float:left;
padding-left: 5px;
}
.blue{
color: steelblue
}
.smol {
font-size: 10px;
}
h1, h2, h3 {
text-align: left;
}
h4 {
margin-top: 8px;
color: #396a93
}
p, .txt {
font-size: 12px;
}
</style>

<body>
<div class='vizDiv'>
<h1>EuroTrip 2022: By Plane or By Train?</h1>
<p>Exploring six popular European routes routes, depending on your travel preferences.</p>
<div class='leftDiv'>
<h2> In a hurry?</h2>
<p> Travel by plane is up to <strong>6x</strong> faster, depending on your desired route. </p>
<p> London-Amsterdam or Zurich-Milan are the shortest routes at just 65 minutes each. </p>
</div>
<div class='rightDiv'>
<h4>Route Duration by Mode of Travel</h4>
${
timePlot
}
</div>
<div class='leftDiv'>
<h2> Or are you an eco-conscious traveler? </h2>
<p>Trains are by far the more carbon-conscious choice for every route.</p>
</div>
<div class='rightDiv'>
<h4>Emissions by Route and Mode of Travel</h4>
${
emPlot
}
</div>
<p class='smol'>&nbsp; </p>
<h2> Looking for travel deals, or just a last-minute planner?</h2>
<span class="txt">Booking earlier will usually yield the cheapest prices, independent of mode of travel, especially for London routes. Last-minute jet-setters will want to keep an eye on plane fares for Zurich-Milan and Berlin-Warsaw, whose prices stay fairly consistent.</span>
<h4>Travel Fares Typically Increase as Purchase Date Approaches Travel Date</h4>
${
pricePlot3
}
</div>

</body>
</head>
</html>
Insert cell
// emissions vs time scatterplot
evtPlot = Plot.plot({
width: width * 0.4,
height: width * 0.25,
marginLeft: 60,
x: {
grid: true,
label: "Travel Time (min)",
ticks: 4
},
y: {
grid: true,
label: "CO2 Emissions (kg/passenger)",
ticks: 8
},
marks: [
Plot.ruleY([0]),
Plot.dot(co2Df, { x: 'TravelTimeMinutes', y: 'CO2InKGramsPerPassenger', fill: 'Mode' })
],
color: {range: ["lightsteelblue", "lightgray"], type: 'categorical', legend: true}
})
Insert cell
Insert cell
// Emissions Plot
emPlot = Plot.plot({
style: {
fontSize: 20,
overflow: "visible"
},
width: width/1.4,
height: 180,
x: {
axis: null
},
y: {
grid: true,
label: 'Average CO2 Emissions (kg/passenger)'
},
fx: {
label: 'Route',
labelOffset: 40,
domain: d3.groupSort(co2Df, g => d3.min(g, d => d.TravelTimeMinutes), d => d.Route)
},
facet: {
data: co2Df,
x: d => d.Route
},
marks: [
Plot.barY(co2Df, Plot.groupX({y: "mean"}, {x: "Mode", y: "CO2InKGramsPerPassenger", fill: "Mode" })),
],
color: {range: ["lightsteelblue", "lightgray"], type: 'categorical', legend: false}
})
Insert cell
co2Df2 = FileAttachment("CO2_data-1.csv").csv({typed: true})
Insert cell
co2Df2.sort((a,b) => (a.Route > b.Route) ? 1 : ((b.Route > a.Route) ? -1 : 0))
Insert cell
Inputs.table(co2Df2)
Insert cell
Insert cell
function highlight(d) {
return /London/.test(d.Route)
}
Insert cell
// Price Fluctuations
pricePlot = Plot.plot({
style: {
fontSize: 20,
overflow: "visible"
},
width: width * .8,
height: width/4,
x: {
reverse: true,
label: 'Weeks ahead Purchased'
},
y: {
grid: true,
label: '% Change in Ticket Price'
},
facet: {
data: co2Df2,
x: "Mode"
},
marks: [
Plot.ruleY([-1]),
Plot.line(co2Df2, {
x: "WeeksAheadPurchased",
y: "PricePctChange",
z: "Route",
sort: highlight,
stroke: highlight,
curve: "linear"
}),
],
color: {
domain: [false, true],
range: ["#ccc", "steelblue"],
legend: false
},
})

Insert cell

pricePlotx = Plot.plot({
style: {
fontSize: 20,
overflow: "visible"
},
width: width * .8,
height: width/4,
x: {
reverse: true,
label: 'Weeks ahead Purchased'
},
y: {
grid: true,
label: '% Change in Ticket Price'
},
facet: {
data: co2Df2,
x: "Mode"
},
marks: [
Plot.ruleY([-1]),
Plot.line(co2Df2, {
x: "WeeksAheadPurchased",
y: "PricePctChange",
z: "Route",
sort: "Route",
stroke: "Route",
curve: "linear"
}),
],
color: {
// domain: [false, true],
range: ["#ccc"],
legend: false
},
})

Insert cell
pricePlot2 = Plot.plot(
{
width: width,
height: width/4,
x: {
reverse: true,
label: 'Weeks ahead Purchased'
},
y: {
grid: true,
label: '% Change in Ticket Price *'
},
facet: {
data: co2Df2,
x: "Route"
},
marks: [
Plot.ruleY([-1]),
Plot.line(co2Df2, {
x: "WeeksAheadPurchased",
y: "PricePctChange",
z: "Mode",
sort: 'Route',
stroke: 'Mode',
curve: "linear"
}),
],
color: {
range: ['steelblue', 'gray'],
legend: true
}
})
Insert cell
pricePlot3 = Plot.plot(
{
width: width,
height: width/4,
x: {
reverse: true,
label: 'Weeks ahead Purchased'
},
y: {
grid: true,
label: '% Change in Ticket Price'
},
facet: {
data: co2Df2,
x: "Mode"
},
marks: [
Plot.ruleY([-1]),
Plot.line(co2Df2, {
x: "WeeksAheadPurchased",
y: "PricePctChange",
z: "Route",
sort: 'Route',
stroke: 'Route',
strokeWidth: 2,
curve: "linear"
}),
],
color: {
scheme: 'set2',
type: 'categorical',
legend: true
}
})
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