Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add food example #1548

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

<a href="https://observablehq.observablehq.cloud/framework-example-food-imports/"><img src="../docs/assets/eia.webp" alt="U.S. electricity grid" width="312" height="237"></a>

[Source](./food-imports) · This dashboard .
[Source](./food-imports) · This dashboard visualizes the distribution of food imports to the United States. With complex data, advanced chart types. Hierarchical and relative values, adapting / small ammendations to existing chart types. Marimekko, Sunburst, and normalized stream graph. Explain each, mention source. Approach.

### [`hotel-bookings`](https://observablehq.observablehq.cloud/framework-example-hotel-bookings) - Resort hotel bookings

Expand Down
1 change: 1 addition & 0 deletions examples/food-imports/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This page displays statistics about food imports to the United States.

## Charts

Elaborate...
A combination of charts express various aspects of the data:

- a Marimekko chart shows the relative sizes of various commodities by origin country;
Expand Down
14 changes: 3 additions & 11 deletions examples/food-imports/src/components/Sunburst.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function Sunburst(
startAngle = 0, // the starting angle for the sunburst
endAngle = 2 * Math.PI, // the ending angle for the sunburst
radius = Math.min(width - marginLeft - marginRight, height - marginTop - marginBottom) / 2, // outer radius
color = d3.interpolateRainbow, // color scheme or scale, if any
color = d3.interpolateRainbow, // color scheme, if any
fill = "var(--theme-background)", // fill for arcs (if no color encoding)
fillOpacity = 0.99 // fill opacity for arcs
} = {}
Expand All @@ -54,7 +54,7 @@ export function Sunburst(
d3.partition().size([endAngle - startAngle, radius])(root);

// Construct a color scale.
if (Array.isArray(color)) {
if (color != null) {
color = d3.scaleSequential([0, root.children.length], color).unknown(fill);
root.children.forEach((child, i) => (child.index = i));
}
Expand Down Expand Up @@ -89,15 +89,7 @@ export function Sunburst(
cell
.append("path")
.attr("d", arc)
.attr(
"fill",
color
? (d) => {
const branch = d.ancestors().reverse()[1];
return branch ? color(branch.data.name) : fill;
}
: fill
)
.attr("fill", color ? (d) => color(d.ancestors().reverse()[1]?.index) : fill)
.attr("fill-opacity", fillOpacity);

if (label != null)
Expand Down
32 changes: 26 additions & 6 deletions examples/food-imports/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ import {Marimekko} from './components/Marimekko.js'
import {Sunburst} from './components/Sunburst.js'
```

```js
// todo:
// make sure color schemes work
// delete colors
// attend to color arg for sunburst and marimekko
// make sure marimekko rows don't change height
// flesh out read mes
// add selector to alternate btw views of stream graph
// final clean-up
```

```js
// full palette from dictionary-of-colour-combinations by Sanzo Wada,
// source: https://github.com/mattdesl/dictionary-of-colour-combinations/blob/master/colors.json
Expand Down Expand Up @@ -39,9 +50,10 @@ const sample = recent.filter((d) => topN.includes(d.Country));
```

```js
// Food categories
const categories = d3.groupSort(sample, (v) => -d3.sum(v, (d) => d.FoodValue), (d) => d.Category);

// Food categories, sorted by size over first 4 countries, with "other" moved to the end
const sampleSlice = sample.filter(d => topN.slice(0,4).includes(d.Country))
const categories = d3.groupSort(recent, (v) => -d3.sum(v, (d) => d.FoodValue), (d) => d.Category)
categories.push(categories.splice(categories.indexOf('Other'), 1)[0]);
const categoryColor = d3.scaleOrdinal().domain(categories).range(["#bce4e5", "#a7d4e4", "#a5c8d1", "#97acc8", "#96d1aa", "#78cdd0", "#62c6bf", "#0093a5", "#00939b", "#099197", "#5a82b3", "#006eb8", "#007190", "#005b8d"]);
```

Expand All @@ -55,9 +67,14 @@ const byCountryAndCategory = d3.sort(
(d) => d.Category
)
.map(([Country, Category, value]) => ({Country, Category, value})),
({Country}) => topN.indexOf(Country),
({Category}) => -categories.indexOf(Category),
({Country}) => topN.indexOf(Country),
({Category}) => categories.indexOf(Category),
);

const rowOneHeight = 200
const rowOnePortion = d3.sum(byCountryAndCategory.filter(d => d.Country === topN[0]), d => d.value)
const all = d3.sum(byCountryAndCategory, d => d.value)
const mekkoHeight = rowOneHeight * all / rowOnePortion
```

```js
Expand All @@ -74,6 +91,8 @@ const nest = {
children: Array.from(children, ([name, value]) => ({name, value}))
}))
};
// reorder nodes to match category order established above
nest.children = d3.sort(nest.children, (a,b) => categories.indexOf(a.name) - categories.indexOf(b.name))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
nest.children = d3.sort(nest.children, (a,b) => categories.indexOf(a.name) - categories.indexOf(b.name))
nest.children = d3.sort(nest.children, (d) => categories.indexOf(d.name))

d3.sort accepts an accessor, which is often simpler than using a comparator. You can inline this in L74.

```

```js
Expand Down Expand Up @@ -101,7 +120,7 @@ const areaData = byYearAndCountry;
<h3>from top ${n} countries, 2023</h3>
${resize((width) => Marimekko(byCountryAndCategory, {
width,
height: n * 60, // TODO constant scaling
height: mekkoHeight,
color: categoryColor
}))}
</div>
Expand All @@ -113,6 +132,7 @@ const areaData = byYearAndCountry;
value: (d) => d.value,
label: (d) => d.name,
color: categoryColor,
sort: null, // to avoid default sorting and instead inherit order in the data
title: (d, n) => `${n.ancestors().reverse().map(d => d.data.name).join(".")}\n${n.value.toLocaleString("en")}`
}))}
</div>
Expand Down