Published
Edited
Apr 14, 2021
1 fork
Insert cell
Insert cell
dataset = await FileAttachment("US.json").json()
Insert cell
drawChart = {

// // 1. Access data
// // console.log(dataset[0])

// // console.log(dateAccessor)

// dimensions.boundedWidth = dimensions.width - dimensions.margin.left - dimensions.margin.right
// dimensions.boundedHeight = dimensions.height - dimensions.margin.top - dimensions.margin.bottom
// dimensions.boundedRadius = dimensions.radius - ((dimensions.margin.left + dimensions.margin.right) / 2)

// const svg = d3.create('svg')
// .attr("width", dimensions.width)
// .attr("height", dimensions.height)

// const bounds = svg.append("g")
// .style("transform", `translate(${ dimensions.margin.left + dimensions.boundedRadius }px,
// ${ dimensions.margin.top + dimensions.boundedRadius }px)`)
// // draw peripherals
// const peripherals = bounds.append("g")
// .attr('id','griddy')
// const months = d3.timeMonths(...angleScale.domain())
// // console.log('months',months)
// // const gridLines = months.forEach(month => { // duplicate of below
// // const angle = angleScale(month)
// // return peripherals.append("line")
// // })

// months.forEach(month => {
// const angle = angleScale(month)
// const [x,y] = getCoordinatesForAngle(angle)

// peripherals.append("line")
// .attr("x2", x)
// .attr("y2", y)
// .attr("class", "grid-line")
// const [labelX, labelY] =
// getCoordinatesForAngle(angle, 1.38)
// peripherals.append("text")
// .attr("x", labelX)
// .attr("y", labelY)
// .attr("class", "tick-label")
// .text(d3.timeFormat("%b")(month))
// .style("text-anchor",
// Math.abs(labelX) <5 ? "middle" :
// labelX > 0 ? "start":
// "end")
// })

// const scale =2
// const circles = bounds.append("g")
// .attr('id','circles')
// .selectAll("circle")
// .data(dataset)
// .join("circle")
// .attr("r", d => d.numerator*scale) // further scaling could be does using a scale function
// .attr('cx', (d,i) => getXFromDataPoint(d)[0])
// .attr('cy', (d,i) => getYFromDatePoint(d)[1])
// .attr("fill", "#f2d974")
// .attr('opacity',0.2)

// return svg.node()
}

Insert cell
Insert cell
t=dataset[0]
Insert cell
dateAccessor(t)
Insert cell
angleScale(dateAccessor(t))
Insert cell
getXFromDataPoint(t)
Insert cell
Insert cell
getXFromDataPoint = (d, offset=1) => getCoordinatesForAngle( angleScale(dateAccessor(d)), offset )
Insert cell
getYFromDatePoint = (d, offset=1) => getCoordinatesForAngle( angleScale(dateAccessor(d)), offset )
Insert cell
randomRadiusScale = d3.scaleSqrt()
.domain(d3.extent(dataset, random))
.range([0, 1])
Insert cell
dimensions = ({
width: width,
height: width,
radius: width/2,
margin: {
top: 120,
right:120,
bottom:120,
left:120,
},
})
Insert cell
width = 800
Insert cell
dateParser = d3.timeParse("%d/%m/%Y")
Insert cell
random = d => d.numerator
Insert cell
dateAccessor = d => dateParser(d.date)
Insert cell
angleScale = d3.scaleTime()
.domain(d3.extent(dataset, dateAccessor))
.range([0, Math.PI * 2])
Insert cell
getCoordinatesForAngle = (angle, offset=1) => [
Math.cos(angle - Math.PI / 2) * dimensions.boundedRadius * offset,
Math.sin(angle - Math.PI / 2) * dimensions.boundedRadius * offset,
]

Insert cell
lots = {
dataset.sort(function compare(a, b) { // sort dataset by date
var dateA = new Date(a.date);
var dateB = new Date(b.date);
return dateA - dateB;
})

let data = new Map()

dataset.map(d=>{
data.set( d.date, [] ) // create a set of unique dates
})

dataset.map(d=>{
data.get(d.date).push(d.numerator); // put all numerators from the same day into an array
})

data.forEach((values,keys)=>{
values.sort() // sort the days numerators
})

return data
}
Insert cell
lots.size
Insert cell
lots.get('01/08/2020')
Insert cell
Insert cell
Insert cell
days_svg = {

const svg = d3.create('svg')
.attr("width", cw)
.attr("height", ch)
const Dates = svg.append("g").attr('id','Dates')
let index = 0
lots.forEach((values,key)=>{
Dates.append("g").attr('id',`day_${_.snakeCase(key)}`)
.selectAll("circle")
.data(values)
.join("circle")
.attr("cx", d=> d*cw)
.attr("cy", 0) //scaleDayz(index) ) // if this is zero, translates consistant
.attr("r", d=> d*12) // or 2
.style('opacity','50%')
.attr('fill','red')
.attr('stroke','gold')
index++
})

// move the lines into a circle position.

index=0
lots.forEach((values,key)=>{
svg.select(`#day_${_.snakeCase(key)}`)
.attr('transform',`translate(400 400) scale(0.49) rotate(${index++}) `) // rotate needs a scale function to go from 0 360
} )
return svg.node()
}
Insert cell
// scale the date entry to the height
scaleDayz = d3.scaleLinear()
.domain([0,lots.size])
.range( [5,ch-5]) // the lenght of the svg can be adjusted here.

Insert cell
timeScale = d3.scaleTime()
.domain([new Date(dateParser(Array.from(lots)[0][0])), new Date(dateParser(Array.from(lots)[lots.size-1][0]))] )
.range( [0, 360]); // degrees because radians hurts my brain
Insert cell
cw = width
Insert cell
ch = 800
Insert cell
Insert cell
Insert cell
d3=require('d3')
Insert cell
_ = require('lodash')
Insert cell
Insert cell
viewof selected = Table(search, {sort: "date"})
Insert cell
selected
Insert cell
import {Table, Search} from "@observablehq/inputs"
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