Public
Edited
Apr 13, 2023
Insert cell
Insert cell
## Overview
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
## Project: Are test passing?
Insert cell
githubtestjobs = FileAttachment("githubTestJobs.json").json()
Insert cell
Inputs.table(githubtestjobs)
Insert cell
Plot.plot({
marks: [
Plot.cell(
githubtestjobs,
{
x:"run_number",
y:"name"
}
)
],
width: width, // cell width
marginLeft: 160,
marginBottom: 50,
x: { tickRotate: -45} // x-labels rotation
}
)
Insert cell
Insert cell
Plot.plot({
marks: [
Plot.cell(
githubtestjobs,
{
x:"run_number",
y:"name",
// colors
fill:"conclusion"
}
)
],
width: width, // cell width
marginLeft: 160,
marginBottom: 50,
x: { tickRotate: -45} // x-labels rotation
}
)
Insert cell
*Scales configure channel's input(domain) and output(range). Scale your colors to overwrite the default colors*
Insert cell
Plot.plot({
marks: [
Plot.cell(
githubtestjobs,
{
x:"run_number",
y:"name",
fill:"conclusion"
}
)
],
// adding scales
color: {
domain: ['failure', 'success', 'cancelled'],
range: ['red', 'green', 'grey']
},
width: width, // cell width
marginLeft: 160,
marginBottom: 50,
x: { tickRotate: -45} // x-labels rotation
}
)
Insert cell
*Use **fillOpacity** to visualize test duration. The longer the darker*
Insert cell
Plot.plot({
marks: [
Plot.cell(
githubtestjobs,
{
x:"run_number",
y:"name",
fill:"conclusion",
fillOpacity: "minutes",
// to manage white colors
stroke: "conclusion"
}
)
],
color: {
domain: ['failure', 'success', 'cancelled'],
range: ['red', 'green', 'grey']
},
width: width,
marginLeft: 160,
marginBottom: 50,
x: { tickRotate: -45}
}
)
Insert cell
*Add tooltips*
Insert cell
Plot.plot({
marks: [
Plot.cell(
githubtestjobs,
{
x:"run_number",
y:"name",
fill:"conclusion",
fillOpacity: "minutes",
stroke: "conclusion",
// add tooltips
title: (o) => `${o.conclusion} after ${o.minutes.toFixed(1)} min`
}
)
],
color: {
domain: ['failure', 'success', 'cancelled'],
range: ['red', 'green', 'grey']
},
width: width,
marginLeft: 160,
marginBottom: 50,
x: { tickRotate: -45}
}
)
Insert cell
# Analytics
## Project: What size of devices are users browsing with?
Insert cell
deviceAnalytics = FileAttachment("device-analytics.csv").csv()
Insert cell
Insert cell
deviceAnalytics[0]
Insert cell
*Doing some **data wrangling** to split Resolution*
Insert cell
devices = deviceAnalytics.map((d) => {
let [Width, Height] = d.Resolution.split("x")
return {
Device: d.Device,
Resolution: d.Resolution,
Width: +Width, // + to convert strings to numbers
Height: +Height,
Users: d.Users,
Sessions: d.Sessions
}
})
Insert cell
Inputs.table(devices)
Insert cell
*Aggregations*
Insert cell
// Plot.markType(...).plot(options) ≃ o Plot.plot({marks:[Plot.markType(...)], ... options})
// use barY with groupX or barX with groupY

Plot.barY(
devices,
Plot.groupX(
{y: "count"}, // set the type of aggregation
{x: "Device"}
)
).plot({
marginLeft: 50
})
Insert cell
Insert cell
Plot.barY(
devices,
Plot.groupX(
{y: "sum", title: "sum"}, // outputs and which type of aggregation
{x: "Device", y: "Users", title: "Users", fill: "Device"} // inputs
)
).plot({
marginLeft: 100
})
Insert cell
Insert cell
Plot.dot(devices, {
x: "Width",
y: "Height",
fill: "Device",
fillOpacity: "Sessions",
r: ({Sessions}) => Math.log(Sessions),
title: ({Resolution, Sessions}) => [Resolution, Sessions].join(":")
}).plot({
// default values
width,
height: width * 0.5,
x: {grid: true, domain: [0, 4200]},
y: {grid: true, domain: [0, 2600]},
opacity: {type: "log"} // Mantiene visibles los puntos pequeños
})
Insert cell
*Separate in facets or small multiples. Overlapped points maintain.*
Insert cell
Plot.dot(devices, {
x: "Width",
y: "Height",
fill: "Device",
fillOpacity: "Sessions",
r: ({Sessions}) => Math.log(Sessions),
title: (d) => `Resolución: ${d.Resolution} con ${d.Sessions} sesiones`
}).plot({
width,
height: width * 0.5,
x: {grid: true, domain: [0, 4200]},
y: {grid: true, domain: [0, 2600]},
opacity: {type: "log"}, // Mantiene visibles los puntos pequeños
facet: {data: devices, x: "Device"}, // the code for divide x by type of device
})
Insert cell
Insert cell
apiLogData = (await FileAttachment("apiLogData.json").json())
.map((d) => ( { ...d, timestamp: new Date(d.timestamp) })) // Convert string timestamps to Date objects
Insert cell
Inputs.table(apiLogData)
Insert cell
Plot.dot(apiLogData, {
x: "timestamp",
y: "duration",
fill: "path",
fillOpacity: 0.5,
title: (d) => [d.path, `${d.duration} ms`, `status ${d.status_code}`].join("\n")
}).plot({
width,
height: width * 0.5,
marginLeft: 50
})
Insert cell
*Adding interactivity*
Insert cell
viewof favColors = Inputs.checkbox(["red", "orange", "yellow", "green", "blue", "purple"],
{label: "Color I like:"} )
Insert cell
Insert cell
Insert cell
Insert cell
Plot.dot(apiLogData.filter((d) => selectedCodes.includes(d.status_code)), {
x: "timestamp",
y: "duration",
fill: "path",
fillOpacity: 0.5,
title: (d) => [d.path, `${d.duration} ms`, `status ${d.status_code}`].join("\n")
}).plot({
width,
height: width * 0.5,
marginLeft: 50
})
Insert cell
*Adding to search by text too*
Insert cell
viewof pathSearch = Inputs.search(apiLogData)
Insert cell
Inputs.table(pathSearch)
Insert cell
Plot.dot(pathSearch.filter((d) => selectedCodes.includes(d.status_code)), {
x: "timestamp",
y: "duration",
fill: "path",
fillOpacity: 0.5,
title: (d) => [d.path, `${d.duration} ms`, `status ${d.status_code}`].join("\n")
}).plot({
width,
height: width * 0.5,
marginLeft: 50
})
Insert cell
Insert cell
Insert cell
# Wrapping up
Insert cell
Insert cell
Type Markdown, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

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