堆疊
範例 · 堆疊將長度轉換為連續的位置區間。例如,每月銷售的長條圖可以按類別分解為多系列長條圖,垂直堆疊長條並套用分類的顏色編碼。堆疊圖可以同時顯示總體價值和每個類別的價值;但是,由於只有堆疊的最底層是對齊的,因此通常很難跨類別比較。因此,請仔細選擇 堆疊順序,並考慮 流形圖。(另請參閱 群組圖。)
與 圓餅產生器 一樣,堆疊產生器不會直接產生形狀。相反,它會計算位置,然後您可以將其傳遞給 面積產生器 或直接使用,例如定位長條。
stack()
原始碼 · 建立一個具有預設設定的新堆疊產生器。有關用法,請參閱 stack。
stack(data, ...arguments)
原始碼 · 為給定的 data 陣列產生一個堆疊,並傳回一個代表每個系列的陣列。任何其他 arguments 都是任意的;它們會與 this
物件一起傳遞給存取器。
例如,考慮這個整理好的每月水果銷售表格
日期 | 水果 | 銷售量 |
---|---|---|
1/2015 | 蘋果 | 3840 |
1/2015 | 香蕉 | 1920 |
1/2015 | 櫻桃 | 960 |
1/2015 | 榴槤 | 400 |
2/2015 | 蘋果 | 1600 |
2/2015 | 香蕉 | 1440 |
2/2015 | 櫻桃 | 960 |
2/2015 | 榴槤 | 400 |
3/2015 | 蘋果 | 640 |
3/2015 | 香蕉 | 960 |
3/2015 | 櫻桃 | 640 |
3/2015 | 榴槤 | 400 |
4/2015 | 蘋果 | 320 |
4/2015 | 香蕉 | 480 |
4/2015 | 櫻桃 | 640 |
4/2015 | 榴槤 | 400 |
這可以用 JavaScript 中的物件陣列表示,也許是從 CSV 解析而來的
const data = [
{date: new Date("2015-01-01"), fruit: "apples", sales: 3840},
{date: new Date("2015-01-01"), fruit: "bananas", sales: 1920},
{date: new Date("2015-01-01"), fruit: "cherries", sales: 960},
{date: new Date("2015-01-01"), fruit: "durians", sales: 400},
{date: new Date("2015-02-01"), fruit: "apples", sales: 1600},
{date: new Date("2015-02-01"), fruit: "bananas", sales: 1440},
{date: new Date("2015-02-01"), fruit: "cherries", sales: 960},
{date: new Date("2015-02-01"), fruit: "durians", sales: 400},
{date: new Date("2015-03-01"), fruit: "apples", sales: 640},
{date: new Date("2015-03-01"), fruit: "bananas", sales: 960},
{date: new Date("2015-03-01"), fruit: "cherries", sales: 640},
{date: new Date("2015-03-01"), fruit: "durians", sales: 400},
{date: new Date("2015-04-01"), fruit: "apples", sales: 320},
{date: new Date("2015-04-01"), fruit: "bananas", sales: 480},
{date: new Date("2015-04-01"), fruit: "cherries", sales: 640},
{date: new Date("2015-04-01"), fruit: "durians", sales: 400}
];
若要計算堆疊系列(每個 水果 的一個系列或圖層;以及每個 日期 的一個堆疊或欄位),我們可以按 日期 然後按 水果 來 索引 資料,計算資料集中不同的 水果 名稱,最後取得每個 日期 和 水果 的 銷售量 值。
const series = d3.stack()
.keys(d3.union(data.map(d => d.fruit))) // apples, bananas, cherries, …
.value(([, group], key) => group.get(key).sales)
(d3.index(data, d => d.date, d => d.fruit));
結果陣列每個 系列 有 1 個元素。每個系列每個月份有 1 個點,每個點都有定義基線和頂線的下限值和上限值
[
[[ 0, 3840], [ 0, 1600], [ 0, 640], [ 0, 320]], // apples
[[3840, 5760], [1600, 3040], [ 640, 1600], [ 320, 800]], // bananas
[[5760, 6720], [3040, 4000], [1600, 2240], [ 800, 1440]], // cherries
[[6720, 7120], [4000, 4400], [2240, 2640], [1440, 1840]] // durians
]
然後通常將每個系列傳遞給 區域產生器 以呈現區域圖表,或用於建構長條圖的長方形。
svg.append("g")
.selectAll("g")
.data(series)
.join("g")
.attr("fill", d => color(d.key))
.selectAll("rect")
.data(D => D)
.join("rect")
.attr("x", d => x(d.data[0]))
.attr("y", d => y(d[1]))
.attr("height", d => y(d[0]) - y(d[1]))
.attr("width", x.bandwidth());
系列由 鍵存取器 決定;傳回陣列中每個系列 i 對應於第 i 個鍵。每個系列都是一個點陣列,其中每個點 j 對應於輸入 data 中的第 j 個元素。最後,每個點表示為一個陣列 [y0, y1],其中 y0 是下限值(基線),y1 是上限值(頂線);y0 和 y1 之間的差值對應於為此點計算的 值。每個系列的鍵可用作 series.key,索引 可用作 series.index。每個點的輸入資料元素可用作 point.data。
stack.keys(keys)
原始碼 · 如果指定 keys,將鍵存取器設定為指定的函式或陣列,並傳回這個堆疊產生器。
const stack = d3.stack().keys(["apples", "bananas", "cherries", "durians"]);
如果未指定 keys,傳回目前的鍵存取器。
stack.keys() // () => ["apples", "bananas", "cherries", "durians"]
鍵存取器的預設值為空陣列。會為每個鍵產生一個序列 (層級)。鍵通常為字串,但也可以是任意值;請參閱 InternMap。序列的鍵會傳遞給 值存取器,以及每個資料點,以計算點的值。
stack.value(value)
原始碼 · 如果指定 value,將值存取器設定為指定的函式或數字,並傳回這個堆疊產生器。
const stack = d3.stack().value((d, key) => d[key]);
如果未指定 value,傳回目前的鍵存取器。
stack.value() // (d, key) => d[key]
值存取器的預設值為
function value(d, key) {
return d[key];
}
注意
預設值存取器假設輸入資料為一個物件陣列,公開具有數字值的命名屬性。這是一個「寬」而非「簡潔」的資料表示方式,不再建議使用。請參閱 stack 以取得使用簡潔資料的範例。
stack.order(order)
原始碼 · 如果指定 order,將順序存取器設定為指定的函式或陣列,並傳回這個堆疊產生器。
const stack = d3.stack().order(d3.stackOrderNone);
如果 order 為函式,會傳遞給產生的序列陣列,並必須傳回一個表示堆疊順序的數字索引陣列。例如,要使用反向鍵順序
const stack = d3.stack().order(series => d3.range(series.length).reverse());
堆疊順序會在 偏移量 之前計算;因此,所有點的較低值在計算順序時為零。每個序列的索引屬性也會在計算順序後才設定。
如果未指定 order,傳回目前的順序存取器。
stack.order() // d3.stackOrderNone
順序存取器的預設值為 stackOrderNone;這會使用 鍵存取器 給出的順序。請參閱 堆疊順序 以取得內建順序。
stack.offset(offset)
原始碼 · 如果指定 offset,將偏移量存取器設定為指定的函式,並傳回這個堆疊產生器。
const stack = d3.stack().offset(d3.stackOffsetExpand);
偏移量函式會傳遞給產生的序列陣列和順序索引陣列;然後負責更新序列陣列中的較低和較高值。請參閱內建偏移量以取得參考實作。
如果未指定 offset,則傳回目前的偏移量存取器。
stack.offset() // d3.stackOffsetExpand
偏移量存取器預設為 stackOffsetNone;這會使用零基準線。請參閱 堆疊偏移量 以取得內建偏移量。
堆疊順序
堆疊順序通常不會直接使用,而是傳遞給 stack.order。
stackOrderAppearance(series)
const stack = d3.stack().order(d3.stackOrderAppearance);
來源 · 傳回一個系列順序,使最早的系列(根據最大值)位於底部。
stackOrderAscending(series)
const stack = d3.stack().order(d3.stackOrderAscending);
來源 · 傳回一個系列順序,使最小的系列(根據值的總和)位於底部。
stackOrderDescending(series)
const stack = d3.stack().order(d3.stackOrderDescending);
來源 · 傳回一個系列順序,使最大的系列(根據值的總和)位於底部。
stackOrderInsideOut(series)
const stack = d3.stack().order(d3.stackOrderInsideOut);
來源 · 傳回一個系列順序,使最早的系列(根據最大值)位於內側,而較晚的系列位於外側。建議將此順序與 波浪形偏移量 結合使用於串流圖。請參閱 Byron 和 Wattenberg 的 堆疊圖形 - 幾何與美學 以取得更多資訊。
stackOrderNone(series)
const stack = d3.stack().order(d3.stackOrderNone);
原始碼 · 傳回給定的序列順序 [0, 1, … n - 1],其中 n 為 series 中元素的數量。因此,堆疊順序由 鍵存取器 給出。
stackOrderReverse(series)
const stack = d3.stack().order(d3.stackOrderReverse);
原始碼 · 傳回給定序列順序的反向 [n - 1, n - 2, … 0],其中 n 為 series 中元素的數量。因此,堆疊順序由 鍵存取器 的反向給出。
堆疊偏移
堆疊偏移通常不會直接使用,而是傳遞給 stack.offset。
stackOffsetExpand(series, order)
const stack = d3.stack().offset(d3.stackOffsetExpand);
原始碼 · 套用零基準線,並將每個點的值正規化,使頂線始終為一。
stackOffsetDiverging(series, order)
const stack = d3.stack().offset(d3.stackOffsetDiverging);
原始碼 · 正值堆疊在零上方,負值 堆疊在零下方,零值堆疊在零處。
stackOffsetNone(series, order)
const stack = d3.stack().offset(d3.stackOffsetNone);
原始碼 · 套用零基準線。
stackOffsetSilhouette(series, order)
const stack = d3.stack().offset(d3.stackOffsetSilhouette);
原始碼 · 向下移動基準線,使流形圖的中心始終為零。
stackOffsetWiggle(series, order)
const stack = d3.stack().offset(d3.stackOffsetWiggle);
原始碼 · 移動基準線以最小化圖層的加權擺動。建議將此偏移量與 由內而外順序 一起用於流形圖。請參閱 Bryon 和 Wattenberg 的 堆疊圖形 — 幾何與美學 以取得更多資訊。