areaY stacked problem with pos/neg values #1963
Replies: 5 comments 7 replies
-
Areas are continuous, which explains the problem; so maybe try instead:
Plot.areaY(
data1.flatMap((d) => [
{ ...d, y: Math.max(0.00001, d.y), series: `positive ${d.z}` },
{ ...d, y: Math.min(-0.00001, d.y), series: `negative ${d.z}` }
]),
{
x: "x",
y: "y",
fill: "z",
z: "series"
}
), |
Beta Was this translation helpful? Give feedback.
-
To add to @Fil’s answer, here is complete working code. I would probably apply the interval option to the x scale rather than the rect mark so that you get an ordinal axis, but it’s really a stylistic preference as to whether you want to draw the bars between the ticks or centered on the ticks (and hence whether you want to represent time as a continuous interval or discrete periods). Plot.plot({
x: {interval: "quarter", label: null},
y: {grid: true},
color: {legend: true},
marks: [
Plot.rectY(data1, {x: "x", y: "y", fill: "z", tip: true}),
Plot.ruleY([0])
]
}) Another simple solution to this problem is to avoid interpolation by using the step curve instead of the default linear. Plot.plot({
y: {grid: true},
color: {legend: true},
marks: [
Plot.areaY(data1, {x: "x", y: "y", curve: "step", fill: "z"}),
Plot.ruleY([0])
]
}) |
Beta Was this translation helpful? Give feedback.
-
Thanks for your generous replies! These are monetary amounts that sometimes switch between positive and negative, so the zig-zag lines would be rather meaningless and impossible to interpret. It is only because I understand that they are artifacts of interpolation that I can try and ignore them. But the ordinary user won't understand that and would be quite confused about the zig-zags. But I prefer using lines as opposed to bars / steps because I think the lines look very pretty here :-) @Fil's last suggestion is exactly what I expect to see. I have updated the Notebook to show this desired result: https://observablehq.com/d/a1c4060fcfcc75b4 Ideally this would be done automatically "behind-the-scenes" so I don't have to worry about it. It should also work with brushing / selection of data. Would it be possible to add this to the Thanks! |
Beta Was this translation helpful? Give feedback.
-
If you like @Fil’s solution, I would recommend a different implementation that is simpler and avoids the need for near-zero values (such as 0.0001). Essentially, this duplicates the stacked area so that there is a positive stacked area (growing upwards) and a negative stacked area (growing downwards), rather than alternating the two. Plot.plot({
y: {grid: true},
color: {legend: true},
marks: [
Plot.areaY(data1, {x: "x", y: (d) => Math.max(0, d.y), fill: "z"}),
Plot.areaY(data1, {x: "x", y: (d) => Math.min(-0, d.y), fill: "z"})
]
}) Personally, I prefer the rect or step curve approach to avoid interpolation in this case. |
Beta Was this translation helpful? Give feedback.
-
Yes, maybe in the stackY transform, where values are grouped by z, they could be further duplicated with alternating zeroes… might be a lot of code overindexing on this particular example, though 🤔 |
Beta Was this translation helpful? Give feedback.
-
When data is plotted using
areaY
that contains both positive and negative values, it creates very confusing zig-zag lines due to the linear interpolation between pos/neg values. It took me a moment to realize what was happening when I first saw this, and I don't think the average user of my web-site will understand this. So I hope you can remove this artifact. Thanks!Example: https://observablehq.com/d/a1c4060fcfcc75b4
PS: Your HQ Notebook system is amazing! I just wish it supported Python as well.
Beta Was this translation helpful? Give feedback.
All reactions