Public
Edited
Feb 21, 2024
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
data = FileAttachment("t-data.csv").csv({array: true})
.then(data => {
return data.map(row => ({
timestamp: timeParser(row[0]),
phenomenon: 'allergy symptom',
count: 1,
duration: +row[2] // duration of the button press in ms
}))
})
Insert cell
printTable(data.slice(0,5))
Insert cell
Insert cell
Insert cell
viewof marginalHistograms = {
const x = vl.x().fieldO("timestamp").timeUnit("utchours").scale({ zero: false });
const y = vl.y().fieldO("timestamp").timeUnit("days").scale({ zero: false });
const color = vl.color().fieldN("count").scale({ scheme: "set2" });
const scatter = vl.markCircle()
.encode(x, y, color);
const right = vl.markBar()
.encode(
y.axis(null),
vl.x().count(),
color
)
.width(50);
const top = vl.markBar()
.encode(
x.axis(null),
vl.y().count(),
color
)
.height(50);
return vl.vconcat(top, vl.hconcat(scatter, right))
.data(data)
.config({ concat: { spacing: 0 } })
.render();
}
Insert cell
Insert cell
viewof ÝearlyDuration = {
const y = vl.y().fieldO("timestamp").timeUnit("year").scale({ zero: false }).title('Year');
const x = vl.x().fieldO("timestamp").timeUnit("month").scale({ zero: false }).title('Month');
const color = vl.color().average("duration").scale({scheme: "redyellowgreen", reverse: true});
const size = vl.size().count("duration");
const AverageDuration = vl.markRect({tooltip: {"content": "data"}, clip: true}).width(400).height(300)
.encode(x, y, color)
.encode(vl.tooltip().average('duration'));

const CountsRecords = vl.markCircle({tooltip: {"content": "data"}, clip: true}).width(400).height(300)
.encode(x, y, color,size)
.encode(vl.tooltip().count("duration"));

return vl.vconcat(vl.hconcat(AverageDuration.title("Average Allergy Symptom Duration"), CountsRecords.title("Allergy Symptom Records")))
.data(data)
.config({ concat: { spacing: 50 } })
.render();
}
Insert cell
Insert cell
viewof MonthDuration = {
const y = vl.y().fieldO("timestamp").timeUnit("month").scale({ zero: false }).title('Month');
const x = vl.x().fieldO("timestamp").timeUnit("day").scale({ zero: false }).title('Day');
const color = vl.color().average("duration").scale({scheme: "redyellowgreen", reverse: true});
const size = vl.size().count("duration");
const AverageDuration = vl.markRect({tooltip: {"content": "data"}, clip: true}).width(400).height(300)
.encode(x, y, color)
.encode(vl.tooltip().average('duration'));

const CountsRecords = vl.markCircle({tooltip: {"content": "data"}, clip: true}).width(400).height(300)
.encode(x, y, color,size)
.encode(vl.tooltip().count("duration"));

return vl.vconcat(vl.hconcat(AverageDuration.title("Average Allergy Symptom Duration"), CountsRecords.title("Allergy Symptom Records")))
.data(data)
.config({ concat: { spacing: 50 } })
.render();
}
Insert cell
A general overview of Thomas's allergy symptoms during days
Insert cell
viewof DayDuration = {
const y = vl.y().fieldO("timestamp").timeUnit("days").scale({ zero: false }).title('Day');
const x = vl.x().fieldO("timestamp").timeUnit("hours").scale({ zero: false }).title('Hour');
const color = vl.color().average("duration").scale({scheme: "redyellowgreen", reverse: true});
const size = vl.size().count("duration");
const AverageDuration = vl.markRect({tooltip: {"content": "data"}, clip: true}).width(400).height(300)
.encode(x, y, color)
.encode(vl.tooltip().average('duration'));

const CountsRecords = vl.markCircle({tooltip: {"content": "data"}, clip: true}).width(400).height(300)
.encode(x, y, color,size)
.encode(vl.tooltip().count("duration"));

return vl.vconcat(vl.hconcat(AverageDuration.title("Average Allergy Symptom Duration"), CountsRecords.title("Allergy Symptom Records")))
.data(data)
.config({ concat: { spacing: 50 } })
.render();
}
Insert cell
{
const brush = vl.selectInterval()
.encodings('x'); // limit selection to x-axis (year) values
// dynamic query histogram
const years = vl.markBar({width: 4})
.data(data)
.params(brush)
.encode(
vl.x().fieldO('timestamp').timeUnit("utcyearmonth").title('Records of Allergy symptoms'),
vl.y().count().title(null)
)
.width(600)
.height(50);
// durations scatter plot
const durations = vl.markCircle()
.data(data)
.encode(
vl.x().fieldO("timestamp").timeUnit("utcyearmonth"), // date parsing!
vl.y().fieldQ("duration"),
vl.tooltip().fieldN('duration'),
vl.opacity().if(brush, vl.value(0.75)).value(0.05)
)
.width(600)
.height(400);

return vl.vconcat(years, durations).spacing(5).render();
}
Insert cell
viewof Key = Inputs.radio(new Map([["Years", "year"], ["Date", "date"], ["Week day", "day"], ["Time", "hours"]]), {value: "hours", label: "Time :"})
Insert cell
viewof DayDuration1 = {
const y = vl.y().fieldO("timestamp").timeUnit(Key).title('Day');
const x = vl.x().fieldO("timestamp").timeUnit("Day").scale({ zero: false }).title('Hour');
const color = vl.color().average("duration").scale({scheme: "redyellowgreen", reverse: true});
const size = vl.size().count("duration");
const AverageDuration = vl.markRect({tooltip: {"content": "data"}, clip: true}).width(400).height(300)
.encode(x, y, color)
.encode(vl.tooltip().average('duration'));

const CountsRecords = vl.markCircle({tooltip: {"content": "data"}, clip: true}).width(400).height(300)
.encode(x, y, color,size)
.encode(vl.tooltip().count("duration"));

return vl.vconcat(vl.hconcat(AverageDuration.title("Average Allergy Symptom Duration"), CountsRecords.title("Allergy Symptom Records")))
.data(data)
.config({ concat: { spacing: 50 } })
.render();
}
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