-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Parallel coordinates chart - design #1071
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
Comments
Checklists: Functionality:
Known issues:
Plotly coding conventions:
Performance (lower priority; just as an inventory of possibilities):
|
Datavis design notes
Technical notes
|
Questions (maybe rhetorical, as pieces fall into place during the API work) as they come up during
|
I'm having issue understanding your pt 1. Can give examples in terms of "data" / "layout" attributes?
What kind of svg overlays are talking about here? If the only SVG overlay is the hover layer (this is what I'm suspecting but I might mistaken), then no worry about SVG overlayer creation,
I thought we agreed on |
@etpinard thanks for your reply! 1.
I probably phrased it poorly; probably best to see these examples and reread Q.1. only then: for example, with pies the So the question is if I should strive to do
i.e. it represents one dimension (most importantly, the 2.
To clarify, the current 3.
Indeed I'm not currently planning with multiple datasets superimposed over one another, and there's no code support for it now (it wouldn't be particularly useful for 4.Just a note, I added this point above (glslify) |
I probably should have done this a while ago now. But here they are, some very preliminaries attribute sets for Option 1 (one-trace 2D values)data = [{
type: 'parcoord',
values: [
[ /* data for labels[0] */ ],
[ /* data for labels[1] */ ],
// ...
],
labels: [ 'A', 'B', ... ], // labels to appear on each axis
ranges: [
[ /* axis range for labels[0] / values[0] */ ],
[ /* axis range for labels[1] / values[1] */ ]
],
domain: { // similar to pie
x: [0, 1],
y: [0, 1]
}
]}
// and no additional layout container Option 2 (one trace with constraint array-container)data = [{
type: 'parcoord',
constraints: [{
values: [ /* */ ],
label: 'A',
axis: { /* axis settings */ }
}, {
values: [ /* */ ],
label: 'B',
axis: {
range: [0, 1]
// other axis settings
}
}, {
// more constraints
}],
domain: { // similar to pie
x: [0, 1],
y: [0, 1]
}
]}
// and no additional layout container Options 3 (one trace per constraint, axis settings in layout)data = [{
type: 'parcoord',
values: [ /* */ ],
label: 'A',
xaxis: 'x'
yaxis: 'y'
}, {
type: 'parcoord',
values: [ /* */ ],
label: 'B',
xaxis: 'x',
yaxis: 'y2'
}, {
// more constraints as traces
}}
layout = {
xaxis: {
domain: [0,1] // the only meaningful setting here (I think)
},
yaxis: {
domain: [0,1],
range: [],
// regular axis style settings
},
yaxis2: {
// similarly ...
},
yaxis3: { /**/ }
} At this stage, I believe option 2 is the most flexible. Although it does add an array-container to a trace object - which isn't the most fun to play with - it feels like the most flexible option. |
Thanks @etpinard, great, we're closest to option 2 already. I might rename the constraints to variables or dimensions. I'm a bit puzzled by the x/y domains in the layout though as parcoords have arbitrary dimensions. I'll make some updates and ask you to take a look at the code in the afternoon or tomorrow morning. |
That refers to the position / size of a subplot on the plot paper coordinates. Just like for pie charts or |
@etpinard as we discussed, here's a current version, it's closest to version 2 and also close to what it's been (I renamed a few things to match your version). I'm totally planning to aggregate them in logical units, e.g. for line styling; filter bar geometry etc., and to convert them to lowercase. Also, a bunch of attributes will change as I'm going to use the I can make it so all of these are in the [old JSON deleted] |
@monfera apart from Again assumeing that we go with option 2, as an exercise consider a multiple parcoord graph (spanning multiple rows), then all attributes that could be different from one parcoord trace (i.e. row) then another should be trace attributes - as there's only one By the way, plotly.js forbids camel case attributes, we prefer grouping attributes in nested objects. For example, the set of filter attributes above should be: {
filter: {
fillcolor: '',
opacity: '',
linewidth: '',
linecolor: ''
}
} |
Multiple rows: some of the geometry and styling options, I believe, should ideally be shared among rows. For example, the brush color, or brush width better be consistent across rows. Nesting / lowercase: indeed, this is what I meant by "I'm totally planning to aggregate them in logical units, e.g. for line styling; filter bar geometry etc., and to convert them to lowercase." |
Let's not do that (at least in v1). That will be up to user to defined their cross-trace (i.e. cross-row) interactions by adding handlers to |
@etpinard This is where the piecemeal evolution of the attribute structure is found: https://github.com/monfera/plotly.js/blob/parcoords-historical/src/traces/parcoords/mocks/k2.json At the time of this note, the Btw. it's not the final place for the mock, it just helps with a way of local testing (will move it later). Also, the I'll also need to switch to plotly-standard styling attributes for things like color/opacity and whatever helps DRY and consistency. |
Thanks Étienne, here's the new, squashed branch. |
Implementing PR merged. |
Just thought I'd throw in a request: it'd be really nice to be able to mouse over a part of a line and have that whole line highlighted. |
Thanks for the nice work. Is it possible to have log10 based axis for some of the coordinates? |
@tantrev yes, that'd be a good addition, it's not trivial due to how lines are currently rendered with WebGL and we didn't have it in the original scope, but an additional SVG overlay for a single polyline looks feasible. I'm not sure how this item would be scheduled, maybe the next time we need to make a round of improvements to parcoords. |
@ibayer thank you, I responded there. In short, it's not yet available, but we'd like to eventually add this, in the meantime only the pre-logging of the data would work, but that'll show log values in the axis ticks. |
@monfera Thanks for the feedback, do you have this already on some feature list or should I open a feature request issue? |
@ibayer I don't see an existing issue for it right now, it's a good idea to add one. |
@monfera Thanks I'll open a issue. (done) @monfera @tantrev Looks like something similar can be done with plotly in general. However, I'm not experienced enough with plotly to judge if this is already possible with parallel coordinates as well. |
@ibayer the Other events on interactions also show up. |
I'm not sure if this is the right place to put it (since it may be considered an entirely new feature), but "Parallel Sets" plots like those from this Mac application would be really great to have on Plotly. Just thought it might go here, since a Parallel Sets plot seems to be the sibling of a Parallel Coordinates plot. 😄 EDIT: ggparallel also produces similar plots. |
On a more direct note, is there any way to specify the precision of the max value in the parallel coordinates plot? I've tried doing it with truncated "range" values, but I am still getting seeing many decimals in the final parallel coordinates plot. An example may be viewed here. |
Uh oh!
There was an error while loading. Please reload this page.
Approach
This issue is dedicated to parallel coordinates. As this is the first new chart where we're moving away from past
gl-vis/***2d
charts, some of the discussions is broader than that.As we discussed on the requirements meeting, it's not easy to have both full, continuous interactivity and a lot of lines, because of the large number of lines (1k and up) either overload the shaders (no matter if WebGL or Canvas2d) or there's a need for time-consuming preprocessing e.g. splatting (we might be able to do on-GPU splatting but probably it's best to start with something simple, reasonably fast and direct).
So our requirements analysis said that - esp. with more than 1k lines - the axis sliders would be debounced, and would only render when the user stops for a bit or releases it. Even with this, a direct rendering is only good till about 10k..20k lines (around 100ms to generate) and beyond that, the direct approach would need incremental rendering. So here's an approach under consideration:
regl
) or Canvas2d, it looks almost identical (minuscule blending hue difference)regl
) for the heavy-lifting layer to see if it does better or worse - this way we don't end up with the rather large code differences between non-WebGL and WebGL versionsviewModel
and the rendererndarray
- it's already part of our dependency stack so no code increase, and perf profiling shows essentially no speed cost relative to indexing manually. It makes the code a lot more readable.plotly.js
practices):regl
alternative)The text was updated successfully, but these errors were encountered: