Public
Edited
Oct 8, 2023
4 stars
Insert cell
Insert cell
Insert cell
{
const margin = { top: 30, right: 30, bottom: 30, left: 100 };
//const width // set automatically
const height = 800;

const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;

// Build X scales and axis:
const x = d3
.scaleBand()
.range([0, innerWidth])
.domain(dataset.varitySorted)
.padding(0.15);

// Build X scales and axis:
const y = d3
.scaleBand()
.range([innerHeight, 0])
.domain(dataset.siteSorted)
.padding(0.15);

// Build color scale
const colorScaleRelY_ = d3
.scaleLinear()
.range(["white", "#006600"])
.domain([-2, dataset.yieldRelYextent[1]]);

const colorScaleRelY = d3
.scaleSequential(d3.interpolateRdYlGn)
.domain([0, dataset.yieldRelYextent[1]]);

let svg = d3.create("svg").attr("width", width).attr("height", height);

svg
.append("g")
.attr(
"transform",
"translate(" + margin.left + "," + (height - margin.bottom) + ")"
)
.call(d3.axisBottom(x));

svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(d3.axisLeft(y));

let rsvg = svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

rsvg
.selectAll("g.m")
.data(dataset.valuesAggregated)
.join("g")
.attr("class", "m")
.each(function (d) {
let rel = d.y1 - d.y2;
let relval = 1 / (1 + Math.exp(-rel));
let angle = relval * 200 - 100;
d3.select(this)
.call(cob(d.y1, d.y2, x.bandwidth() / 2, 6, 100))
.attr(
"transform",
`translate(${x(d.variety)} ${y(d.site)}) rotate(${angle} ${
x.bandwidth() / 2
} 0)`
);
});

return svg.node();
}
Insert cell
transform = (x, y) => {
return (g) => {
g.attr("transform", "translate(" + x + "," + y + ")");
};
}
Insert cell
dataset = {
let x = {};
x.values = [...barley];
x.years = _.uniq(barley.map((d) => d.year));
x.average = d3.mean(barley, (d) => d.yield);

// Calculate the averages for each year
x.averages = d3.rollup(
barley,
(v) => d3.mean(v, (d) => d.yield),
(d) => d.year
);
x.max = d3.rollup(
barley,
(v) => d3.max(v, (d) => d.yield),
(d) => d.year
);
x.averagesSite = d3.rollup(
barley,
(v) => d3.mean(v, (d) => d.yield),
(d) => d.site
);
x.averagesVariety = d3.rollup(
barley,
(v) => d3.mean(v, (d) => d.yield),
(d) => d.variety
);
x.siteSorted = _.uniq(barley.map((d) => d.site));
x.siteSorted.sort((a, b) => x.averagesSite.get(a) - x.averagesSite.get(b));
x.varitySorted = _.uniq(barley.map((d) => d.variety)).sort(
(a, b) => x.averagesVariety.get(a) - x.averagesVariety.get(b)
);

// calculate averags across all years for each combination of site and variety.
x.valuesAggregated = Array.from(
d3
.rollup(
barley,
(v) => ({
variety: v[0].variety,
site: v[0].site,
yieldRelY: d3.mean(v, (d) => d.yield) / x.average,
y1: v[0].yield / x.max.get(v[0].year),
y2: v[1].yield / x.max.get(v[1].year)
}),
(d) => d.variety + "," + d.site
)
.values()
);

// add the yieldRelY property that is relative to the year average
x.values.forEach((d) => {
d.yieldRelY = d.yield / x.averages.get(d.year);
});
x.yieldRelYextent = d3.extent(x.values, (d) => d.yieldRelY);
return x;
}
Insert cell
Array.from(
d3
.rollup(
barley,
(v) => ({
variety: v[0].variety,
site: v[0].site,
yieldRelY: d3.mean(v, (d) => d.yield),
y1: v[0].yield,
y2: v[1].yield
}),
(d) => d.variety + "," + d.site
)
.values()
)
Insert cell
barley
Insert cell
Insert cell
colorScale2 = d3
.scaleLinear()
.domain([0, 1])
.range(["#ff0077", "wheat"])
.interpolate(d3.interpolateRgb.gamma(2.0))
Insert cell
Insert cell
Insert cell
barley.json
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
Insert cell
Insert cell
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