跳至內容

堆疊

範例 · 堆疊將長度轉換為連續的位置區間。例如,每月銷售的長條圖可以按類別分解為多系列長條圖,垂直堆疊長條並套用分類的顏色編碼。堆疊圖可以同時顯示總體價值和每個類別的價值;但是,由於只有堆疊的最底層是對齊的,因此通常很難跨類別比較。因此,請仔細選擇 堆疊順序,並考慮 流形圖。(另請參閱 群組圖。)

圓餅產生器 一樣,堆疊產生器不會直接產生形狀。相反,它會計算位置,然後您可以將其傳遞給 面積產生器 或直接使用,例如定位長條。

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 解析而來的

js
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}
];

若要計算堆疊系列(每個 水果 的一個系列或圖層;以及每個 日期 的一個堆疊或欄位),我們可以按 日期 然後按 水果索引 資料,計算資料集中不同的 水果 名稱,最後取得每個 日期水果銷售量 值。

js
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));

提示

請參閱 d3-array 中的 unionindex

結果陣列每個 系列 有 1 個元素。每個系列每個月份有 1 個點,每個點都有定義基線和頂線的下限值和上限值

js
[
  [[   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
]

然後通常將每個系列傳遞給 區域產生器 以呈現區域圖表,或用於建構長條圖的長方形。

js
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 是上限值(頂線);y0y1 之間的差值對應於為此點計算的 。每個系列的鍵可用作 series.key,索引 可用作 series.index。每個點的輸入資料元素可用作 point.data。

stack.keys(keys)

原始碼 · 如果指定 keys,將鍵存取器設定為指定的函式或陣列,並傳回這個堆疊產生器。

js
const stack = d3.stack().keys(["apples", "bananas", "cherries", "durians"]);

如果未指定 keys,傳回目前的鍵存取器。

js
stack.keys() // () => ["apples", "bananas", "cherries", "durians"]

鍵存取器的預設值為空陣列。會為每個鍵產生一個序列 (層級)。鍵通常為字串,但也可以是任意值;請參閱 InternMap。序列的鍵會傳遞給 值存取器,以及每個資料點,以計算點的值。

stack.value(value)

原始碼 · 如果指定 value,將值存取器設定為指定的函式或數字,並傳回這個堆疊產生器。

js
const stack = d3.stack().value((d, key) => d[key]);

如果未指定 value,傳回目前的鍵存取器。

js
stack.value() // (d, key) => d[key]

值存取器的預設值為

js
function value(d, key) {
  return d[key];
}

注意

預設值存取器假設輸入資料為一個物件陣列,公開具有數字值的命名屬性。這是一個「寬」而非「簡潔」的資料表示方式,不再建議使用。請參閱 stack 以取得使用簡潔資料的範例。

stack.order(order)

原始碼 · 如果指定 order,將順序存取器設定為指定的函式或陣列,並傳回這個堆疊產生器。

js
const stack = d3.stack().order(d3.stackOrderNone);

如果 order 為函式,會傳遞給產生的序列陣列,並必須傳回一個表示堆疊順序的數字索引陣列。例如,要使用反向鍵順序

js
const stack = d3.stack().order(series => d3.range(series.length).reverse());

堆疊順序會在 偏移量 之前計算;因此,所有點的較低值在計算順序時為零。每個序列的索引屬性也會在計算順序後才設定。

如果未指定 order,傳回目前的順序存取器。

js
stack.order() // d3.stackOrderNone

順序存取器的預設值為 stackOrderNone;這會使用 鍵存取器 給出的順序。請參閱 堆疊順序 以取得內建順序。

stack.offset(offset)

原始碼 · 如果指定 offset,將偏移量存取器設定為指定的函式,並傳回這個堆疊產生器。

js
const stack = d3.stack().offset(d3.stackOffsetExpand);

偏移量函式會傳遞給產生的序列陣列和順序索引陣列;然後負責更新序列陣列中的較低和較高值。請參閱內建偏移量以取得參考實作。

如果未指定 offset,則傳回目前的偏移量存取器。

js
stack.offset() // d3.stackOffsetExpand

偏移量存取器預設為 stackOffsetNone;這會使用零基準線。請參閱 堆疊偏移量 以取得內建偏移量。

堆疊順序

堆疊順序通常不會直接使用,而是傳遞給 stack.order

stackOrderAppearance(series)

js
const stack = d3.stack().order(d3.stackOrderAppearance);

來源 · 傳回一個系列順序,使最早的系列(根據最大值)位於底部。

stackOrderAscending(series)

js
const stack = d3.stack().order(d3.stackOrderAscending);

來源 · 傳回一個系列順序,使最小的系列(根據值的總和)位於底部。

stackOrderDescending(series)

js
const stack = d3.stack().order(d3.stackOrderDescending);

來源 · 傳回一個系列順序,使最大的系列(根據值的總和)位於底部。

stackOrderInsideOut(series)

js
const stack = d3.stack().order(d3.stackOrderInsideOut);

來源 · 傳回一個系列順序,使最早的系列(根據最大值)位於內側,而較晚的系列位於外側。建議將此順序與 波浪形偏移量 結合使用於串流圖。請參閱 Byron 和 Wattenberg 的 堆疊圖形 - 幾何與美學 以取得更多資訊。

stackOrderNone(series)

js
const stack = d3.stack().order(d3.stackOrderNone);

原始碼 · 傳回給定的序列順序 [0, 1, … n - 1],其中 nseries 中元素的數量。因此,堆疊順序由 鍵存取器 給出。

stackOrderReverse(series)

js
const stack = d3.stack().order(d3.stackOrderReverse);

原始碼 · 傳回給定序列順序的反向 [n - 1, n - 2, … 0],其中 nseries 中元素的數量。因此,堆疊順序由 鍵存取器 的反向給出。

堆疊偏移

堆疊偏移通常不會直接使用,而是傳遞給 stack.offset

stackOffsetExpand(series, order)

js
const stack = d3.stack().offset(d3.stackOffsetExpand);

原始碼 · 套用零基準線,並將每個點的值正規化,使頂線始終為一。

stackOffsetDiverging(series, order)

js
const stack = d3.stack().offset(d3.stackOffsetDiverging);

原始碼 · 正值堆疊在零上方,負值 堆疊在零下方,零值堆疊在零處。

stackOffsetNone(series, order)

js
const stack = d3.stack().offset(d3.stackOffsetNone);

原始碼 · 套用零基準線。

stackOffsetSilhouette(series, order)

js
const stack = d3.stack().offset(d3.stackOffsetSilhouette);

原始碼 · 向下移動基準線,使流形圖的中心始終為零。

stackOffsetWiggle(series, order)

js
const stack = d3.stack().offset(d3.stackOffsetWiggle);

原始碼 · 移動基準線以最小化圖層的加權擺動。建議將此偏移量與 由內而外順序 一起用於流形圖。請參閱 Bryon 和 Wattenberg 的 堆疊圖形 — 幾何與美學 以取得更多資訊。