Published
Edited
Jan 31, 2022
1 fork
3 stars
Insert cell
# Radar Plot

Insert cell
chart = {
const svg = d3.select(DOM.svg(width, height+(margin*2)));
const containerWidth = width-(margin*2);
const containerHeight = height-(margin*2);
const container = svg.append('g')
.attr("width", containerWidth)
.attr("height", containerHeight)
.attr('transform', `translate(${(width/2)+margin}, ${(height/2)+margin})`);
var axisGrid = container.append("g")
.attr("class", "axisWrapper");
axisGrid.selectAll(".levels")
.data(d3.range(1,(axisCircles+1)).reverse())
.enter()
.append("circle")
.attr("class", "gridCircle")
.attr("r", (d, i) => radius/axisCircles*d)
.style("fill", "#CDCDCD")
.style("stroke", "#CDCDCD")
.style("fill-opacity", 0.1);
const axis = axisGrid.selectAll(".axis")
.data(axesDomain)
.enter()
.append("g")
.attr("class", "axis");

axis.append("line")
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", (d, i) => rScale(maxValue*1.1) * Math.cos(angleSlice*i - Math.PI/2))
.attr("y2", (d, i) => rScale(maxValue*1.1) * Math.sin(angleSlice*i - Math.PI/2))
.attr("class", "line")
.style("stroke", "white")
.style("stroke-width", "2px");

axis.append("text")
.attr("class", "legend")
.style("font-size", "11px")
.attr("text-anchor", "middle")
.attr("font-family", "monospace")
.attr("dy", "0.35em")
.attr("x", (d, i) => rScale(maxValue * axisLabelFactor) * Math.cos(angleSlice*i - Math.PI/2))
.attr("y", (d, i) => rScale(maxValue * axisLabelFactor) * Math.sin(angleSlice*i - Math.PI/2))
.text(d => d);
const plots = container.append('g')
.selectAll('g')
.data(formattedData)
.join('g')
.attr("data-name", (d, i) => type(i))
.attr("fill", "none")
.attr("stroke", "steelblue");

plots.append('path')
.attr("d", d => radarLine(d.map(v => v.value)))
.attr("fill", (d, i) => color(i))
.attr("fill-opacity", 0.1)
.attr("stroke", (d, i) => color(i))
.attr("stroke-width", 2);

plots.selectAll("circle")
.data(d => d)
.join("circle")
.attr("r", dotRadius)
.attr("cx", (d,i) => rScale(d.value) * Math.cos(angleSlice*i - Math.PI/2))
.attr("cy", (d,i) => rScale(d.value) * Math.sin(angleSlice*i - Math.PI/2))
.style("fill-opacity", 0.8);

return svg.node();
}
Insert cell
axesDomain = [
"AS_rank_source",
"AS_rank_iso",
"AS_rank_continent",
"AS_rank_numberAsns",
"AS_rank_numberPrefixes",
"AS_rank_numberAddresses",
"AS_hegemony",
"AS_rank_total",
"AS_rank_peer",
"AS_rank_customer",
"AS_rank_provider",
"peeringDB_ix_count",
"peeringDB_fac_count",
"peeringDB_policy_general",
"peeringDB_info_type",
"peeringDB_info_ratio",
"peeringDB_info_traffic",
"peeringDB_info_scope",
"is_personal_AS"
]
Insert cell
axesLength = 19

Insert cell
formatPercent = d3.format(',.0%')
Insert cell
wrapWidth = 60
Insert cell
axisLabelFactor = 1.12
Insert cell
axisCircles = 2
Insert cell
dotRadius = 4
Insert cell
radius = 270
Insert cell
margin = 30
Insert cell
height = 600
Insert cell
maxValue = 0.6

Insert cell
angleSlice = 0.33052631578
Insert cell
data = FileAttachment("Test_bias_values_for_radar@1.csv").csv({typed:true})
Insert cell
type = d => ["RIPE Atlas","RIPE RIS"][d]
Insert cell
ripeRisData = data.map((datum)=> {
return {axis: datum.tag, value: datum["RIPE RIS"]}
});

Insert cell
ripeAtlasData = data.map((datum)=> {
return {axis: datum.tag, value: datum["RIPE Atlas"]}
});
Insert cell
formattedData = [ripeAtlasData, ripeRisData]
Insert cell
radarLine = d3.lineRadial()
.curve(d3["curveLinear"])
.radius(d => rScale(d))
.angle((d, i) => i * angleSlice)
Insert cell
rScale = d3.scaleLinear()
.domain([0, maxValue])
.range([0, radius])
Insert cell
color = d3.scaleOrdinal()
.range(["#EDC951","#00A0B0"])
Insert cell
import {select} from "@jashkenas/inputs"

Insert cell
import {curveTypes} from "@palewire/d3-curves-inputs"
Insert cell
_ = require("underscore")
Insert cell
d3 = require("d3@5")
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