From 3202eac8072c1c10b36abf05ec22ba0d14ca99bd Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Sat, 17 Aug 2024 00:58:31 +0200 Subject: [PATCH] WIP --- src/charts/bar/clustered.typ | 7 ++- src/charts/bar/plotter.typ | 2 + src/charts/bar/stacked.typ | 108 ++++++++++++++++------------------- src/plot/elements/bar.typ | 13 ++--- 4 files changed, 60 insertions(+), 70 deletions(-) diff --git a/src/charts/bar/clustered.typ b/src/charts/bar/clustered.typ index 9d5995f..1e4d1b2 100644 --- a/src/charts/bar/clustered.typ +++ b/src/charts/bar/clustered.typ @@ -64,12 +64,13 @@ let series-data = () for (series-index, y-key) in y-keys.enumerate() { - series-data.push( ( - label: if label-key != none {labels.at(series-index)}, + label: if label-key != none { + labels.at(series-index, default: none) + }, data: for (observation-index, observation) in data.enumerate() { - let x = observation-index - cluster-width/2 + series-index * (bar-width + bar-spacing) + bar-width/2 + let x = observation-index - cluster-width / 2 + series-index * (bar-width + bar-spacing) + bar-width/2 let y = observation.at(y-key, default: 0) (( diff --git a/src/charts/bar/plotter.typ b/src/charts/bar/plotter.typ index 90fbbc0..3b4d4e4 100644 --- a/src/charts/bar/plotter.typ +++ b/src/charts/bar/plotter.typ @@ -17,6 +17,7 @@ ..plot-args, ) = { draw.group(ctx => { + /* // Setup styles let style = styles.resolve( ctx.style, @@ -64,5 +65,6 @@ ) } ) + */ }) } diff --git a/src/charts/bar/stacked.typ b/src/charts/bar/stacked.typ index 1c05c9c..38ffecd 100644 --- a/src/charts/bar/stacked.typ +++ b/src/charts/bar/stacked.typ @@ -1,23 +1,23 @@ -#import "/src/cetz.typ": canvas, palette -#import "plotter.typ": plotter +#import "/src/cetz.typ" as cetz: canvas, palette +#import "/src/plot.typ" +#import "/src/charts/environment.typ": chart + +//#import "plotter.typ": plotter /// Render a stacked bar chart /// ```example /// cetz-plot.chart.bar.stacked( -/// size: (4,4), -/// ( -/// ([One], 1, 1, 2, 3), -/// ([Two], 3, 1, 1 ,1), -/// ([Three], 3, 2, 1, 3), -/// ), +/// size: (4, 4), +/// (([One], 1, 1, 2, 3), +/// ([Two], 3, 1, 1 ,1), +/// ([Three], 3, 2, 1, 3)), /// label-key: 0, -/// y-keys: (1,2,3,4), +/// y-keys: (1, 2, 3, 4), /// labels: ( /// $0 -> 24$, /// $25 -> 49$, /// $50 -> 74$, -/// $75 -> 100$ -/// ), +/// $75 -> 100$), /// ) /// ``` /// - data (array): An array of clusers to plot. Each entry can include a label @@ -53,64 +53,52 @@ axes: ("x", "y"), ..plot-args ) = { - let cluster-count = data.len() - let cluster-width = cluster-count * bar-width - let offsets = (0,)*cluster-count + let num-cols = data.len() + let plot-args = plot-args.named() - let series-data = () + if "ticks" not in plot-args { + plot-args.x-ticks = data.enumerate().map(((x, col)) => { + (x, [#x]) + }) + } - for (series-index, y-key) in y-keys.enumerate() { + chart(x-tick-step: none, ..plot-args, style => { + import "/src/plot/add.typ" - series-data.push( - ( - label: if label-key != none {labels.at(series-index)}, - data: for (observation-index, observation) in data.enumerate() { - let x = observation-index - let y = observation.at(y-key, default: 0) - let y-offset = offsets.at(observation-index) - offsets.at(observation-index) += y - (( - x: x, - y: y, - y-offset: y-offset, - ),) - } - ) - ) - } + let y-offset = (0,) * num-cols + for (y, y-key) in y-keys.enumerate() { + let row-data = data.enumerate().map(((x, col)) => { + (x, col.at(y-key, default: 0), y-offset.at(x, default: 0)) + }) - plotter( - data, - series-data, - x-key: "x", - y-key: "y", - y-offset-key: "y-offset", - y-error-key: none, - label-key: label-key, - bar-width: bar-width, - bar-style: bar-style, - axes: axes, - ..plot-args, - ) + y-offset = y-offset.enumerate().map(((x, offset)) => { + offset + row-data.at(x).at(1) + }) + + add.bar(row-data, + x-key: 0, + y-key: 1, + y-offset-key: 2, + axes: axes, + style: bar-style) + } + }) } /// Render a stacked bar chart /// ```example /// cetz-plot.chart.bar.stacked100( -/// size: (4,4), -/// ( -/// ([One], 1, 1, 2, 3), -/// ([Two], 3, 1, 1 ,1), -/// ([Three], 3, 2, 1, 3), -/// ), +/// size: (4, 4), +/// (([One], 1, 1, 2, 3), +/// ([Two], 3, 1, 1 ,1), +/// ([Three], 3, 2, 1, 3)), /// label-key: 0, -/// y-keys: (1,2,3,4), +/// y-keys: (1, 2, 3, 4), /// labels: ( /// $0 -> 24$, /// $25 -> 49$, /// $50 -> 74$, -/// $75 -> 100$ -/// ), +/// $75 -> 100$), /// ) /// ``` /// - data (array): An array of clusers to plot. Each entry can include a label @@ -147,11 +135,13 @@ ..plot-args ) = stacked( data.map(d=>{ - let sum = y-keys.map(k=>d.at(k, default: 0)).sum() + let sum = y-keys.map(d.at.with(default: 0)).sum() + assert(sum != 0, + message: "Y value sum must be != 0!") for key in y-keys { d.at(key) /= sum } - d + return d }), labels: labels, label-key: label-key, @@ -161,6 +151,6 @@ bar-style: bar-style, axes: axes, y-tick-step: 0.2, - y-format: (it)=>{$#{it*100}%$}, + y-format: (it) => { $#{it * 100}%$ }, ..plot-args -) \ No newline at end of file +) diff --git a/src/plot/elements/bar.typ b/src/plot/elements/bar.typ index 80cb1c0..d2cdbbb 100644 --- a/src/plot/elements/bar.typ +++ b/src/plot/elements/bar.typ @@ -114,20 +114,19 @@ style: (:), axes: ("x", "y") ) = { - let x-domain = ( - calc.min(..data.map(it=>{it.at(x-key)-bar-width})), - calc.max(..data.map(it=>{it.at(x-key)+bar-width})), + calc.min(..data.map(it => {it.at(x-key) - bar-width / 2})), + calc.max(..data.map(it => {it.at(x-key) + bar-width / 2})), ) let y-domain = if y-offset-key != none { ( calc.min( - ..data.map(it=>{it.at(y-key)+it.at(y-offset-key, default: 0)}), + ..data.map(it=>{it.at(y-key) + it.at(y-offset-key, default: 0)}), ..data.map(it=>{it.at(y-offset-key, default: 0)}) ), calc.max( - ..data.map(it=>{it.at(y-key)+it.at(y-offset-key, default: 0)}), + ..data.map(it=>{it.at(y-key) + it.at(y-offset-key, default: 0)}), ..data.map(it=>{it.at(y-offset-key, default: 0)}) ) ) @@ -158,6 +157,4 @@ plot-fill: _fill, plot-legend-preview: _legend-preview ),) - - -} \ No newline at end of file +}