🏠 back to Observable

Converting Date Ranges to Counts

Hello!

I have collected data on the books I have read over the past few years. I want to create a visualization in which I can see how many books I was reading each day of the year. Currently, the data I’ve collected contains the start and stop day of the books, along with the title and author as such:

data = [
	{title: 'War and Peace', author: 'Leo Tolstoy', start: '2021-01-01', stop: '2021-06-15'},
	{title: 'The Great Gatsby', author: 'F. Scott Fitzgerald', start: '2021-02-20', stop: '2021-03-30'},
	{title: 'Moby Dick', author: 'Herman Melville', start: '2021-05-06', stop: '2021-08-10'},
	{title: 'Pride and Prejudice', author: 'Jane Austen', start: '2021-05-25', stop: '2021-10-03'},
	{title: 'Mrs. Dalloway', author: 'Virginia Woolf', start: '2021-06-02', stop: '2021-11-10'},
]

I want to use Plot and the cell mark to show how many books I was reading on any given day. I am unsure how to transform a series of overlapping date ranges into an aggregated count of books by day. Any advice would help.

Thanks!

1 Like

Which chart type or combination of charts to you have envisioned? Would calendar view help?

I envisioned something similar to this:

That calendar view looks interesting :slight_smile:

If your dataset is called books, you can expand it to include all the days you were reading such and such book with a flatMap:

data = books.flatMap((book) =>
  d3.utcDays(d3.isoParse(book.start), d3.isoParse(book.stop))
    .map((date) => ({ ...book, date }))
)

You can then use this structure in a Plot:

Plot.rectY(
  data,
  Plot.stackY({
    x: "date",
    interval: d3.utcDay,
    inset: -0.5,
    fill: "title",
    title: "title",
    order: "appearance",
    reverse: true
  })
).plot({ width: 940, height: 200 })

or in a Calendar:

import { Calendar } from "@observablehq/calendar-component"

Calendar(data, {
  reduce: (d) => ({ value: d.length }),
  color: { scheme: "reds" }
})

notebook: How many books was I reading? / Fil / Observable

2 Likes

Thank you! This is great :slight_smile:

1 Like

Can’t wait to see what it gives with the actual data :slight_smile:

I’ve added a fix for the “degenerate” case of reading a book on a single day (start==end — maybe not War and Peace though); we still want it to show on the chart.

1 Like

@Fil Thanks again for the help! Here is an image with some real data.

I will post the completed notebook here at the end of the year :slight_smile:

2 Likes

Oops in your screenshot the months labels are somehow a bit off… any idea why this might be happening?