Public
Edited
Feb 25
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
data = {
const text = await FileAttachment("t-data.csv").text()
const rawdata = d3.csvParseRows(text)

return rawdata.map(d => ({
timestamp: d3.utcParse("%Y%m%dT%H%M%S.%LZ")(d[0]),
observation: 1
})
)
}

Insert cell
scatterData = data.map(d => ({
date: d3.utcFormat("%Y-%m-%d")(d.timestamp), // Extract date only
time: d.timestamp.getUTCHours() + d.timestamp.getUTCMinutes() / 60,
formattedTime: d3.utcFormat("%H:%M")(d.timestamp),
week: d3.timeWeek(d.timestamp),
weekNumber: d3.timeFormat("%U")(d.timestamp),
month: d3.timeFormat("%B")(d.timestamp)// Convert time to minutes
}));

Insert cell
minMaxDate = d3.extent(scatterData, d => new Date(d.date));
Insert cell
dateFrom = new Date(date_from);
Insert cell
dateTo = new Date(date_to);
Insert cell
filteredData = scatterData.filter(d => new Date(d.date) >= dateFrom && new Date(d.date) <= dateTo)
Insert cell
Insert cell
viewof date_from = Inputs.date({label: "From", value: minMaxDate[0]})
Insert cell
viewof date_to = Inputs.date({label: "To", value: minMaxDate[1]})
Insert cell
viewof scatter_days = vl.markPoint()
.data(filteredData)
.encode(
vl.x().fieldT("date")
.axis({ title: "Date", format: "%b %Y" }), // Show month & year
vl.y().fieldQ("time"),
vl.tooltip().fieldN("formattedTime")
)
.title("Overview of Observations Throughout Date and Time")
.width(800)
.height(600)
.render();
Insert cell
Insert cell
viewof selection = Inputs.radio(["Hours of the day", "Weekdays", "Weeks", "Months"], {label: "Choose Distribution Chart", value: "Hours of the day"})
Insert cell
makeChart(selection)
Insert cell
Insert cell
//function for .radio event listener to call accroding functions
makeChart = (selection) => {
if (selection === "Weekdays") {
return createWeekdayChart(filteredData);
} else if (selection === "Hours of the day") {
return createHourlyChart(filteredData);
} else if (selection === "Months") {
return createMonthChart(filteredData);
} else if (selection === "Weeks") {
return plotWeekly(filteredData);
}
};
Insert cell
function createWeekdayChart(filteredData) {
const weekdayData = d3.rollup(
filteredData,
v => v.length,
d => new Date(d.date).getUTCDay()
);
const weekdayDataCount = Array.from(weekdayData, ([weekday, count]) => ({ weekday, count }));
const weekdayLabels = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

weekdayDataCount.forEach(d => d.weekdayName = weekdayLabels[d.weekday]);
return vl.markBar()
.data(weekdayDataCount)
.encode(
vl.x().fieldN("weekdayName").sort(["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"])
.axis({ title: "Weekday" }),
vl.y().fieldQ("count").axis({ title: "Observations" }), // Y-axis: Count of observations
vl.tooltip([{ field: "weekdayName", type: "nominal" }, { field: "count", type: "quantitative" }])
)
.title("Weekday Data Distribution")
.width(800)
.height(400)
.render();
}
Insert cell
function createHourlyChart(filteredData) {
const hourlyData = d3.rollup(
filteredData,
v => v.length,
d => d.time
);
const hourlyDataCount = Array.from(hourlyData, ([hour, count]) => ({ hour, count }));

const monthsOrder = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
return vl.markBar()
.data(hourlyDataCount)
.encode(
vl.x().fieldQ("hour").axis({ title: "Hour of the Day", format: "d" }), // X-axis: Hours (0-23)
vl.y().fieldQ("count").axis({ title: "Observations" }), // Y-axis: Count of observations
vl.tooltip([{ field: "hour", type: "quantitative" }, { field: "count", type: "quantitative" }])
)
.title("Hourly Data Distribution")
.width(800)
.height(400)
.render();
}

Insert cell
function plotWeekly(filteredData) {
const weekData = d3.rollup(
filteredData,
v => v.length,
d => d.weekNumber
);
const weekDataCount = Array.from(weekData, ([weekNumber, count]) => ({
weekNumber: `Week ${weekNumber}`,
count: count
}));

weekDataCount.sort((a, b) => {
const weekA = parseInt(a.weekNumber.split(' ')[1]);
const weekB = parseInt(b.weekNumber.split(' ')[1]);
return weekA - weekB;
});
return vl.markBar()
.data(weekDataCount)
.encode(
vl.x().fieldN("weekNumber").axis({ title: "Week" }),
vl.y().fieldQ("count").axis({ title: "Observations" }),
vl.tooltip().fieldN("weekNumber").title("Week").fieldQ("count").title("Observations")
)
.title("Weekly Data Distribution")
.width(800)
.height(400)
.render();
}

Insert cell
function createMonthChart(filteredData) {
const monthData = d3.rollup(
filteredData,
v => v.length,
d => d.month
);
const monthDataCount = Array.from(monthData, ([month, count]) => ({
month,
count
}));
const monthsOrder = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
monthDataCount.sort((a, b) => monthsOrder.indexOf(a.month) - monthsOrder.indexOf(b.month));
return vl.markBar()
.data(monthDataCount)
.encode(
vl.x().fieldN("month").axis({
title: "Month"
}),
vl.y().fieldQ("count").axis({ title: "Observations" }), // Y-axis: Count of observations
)
.title("Montly Data Distribution")
.width(800)
.height(400)
.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