bigfatdog / parcoords-es Goto Github PK
View Code? Open in Web Editor NEWES6 module of Syntagmatic's Parallel Coordinates
License: MIT License
ES6 module of Syntagmatic's Parallel Coordinates
License: MIT License
Per @ joshhjacobson 's feature request in issue #16
pc.scale allowed the user to specify the type of scale to use for the axis (log, linear, ordinal, custom). Perhaps pc.scale(input, [lower, upper], scale)? Maybe this is too much?
I've noticed that a single click on one of the column titles causes the entire chart to render with no data. Am I missing something or is this a bug?
If this is a bug, any pointers as to where it might be located, might be able to look at fixing it. I've noticed it on the slickgrid-hidex-axis.html
page.
@timelyportfolio contributed this bug in #15
Thank @timelyportfolio for also providing an online example that reproduces this issue.
@BigFatDog, not sure if this is related or should be a separate issue, but on reorder of axes (reproducible example), I get
Thanks so much for your ambitious upgrade of
parallel-coordinates
.
Is it possible to restore a manually saved order?
I am saving the value of .getOrderedDimensionKeys()
in localStorage.
I tried to use something like .reorder({ 1: -1, 355: 999999999, 21: -9, 778: 999 })
, .reorder(["355", "21", "778", "1"])
, .dimensions({ 355: 999999999, 21: -9, 778: 999, 1: -1 })
and .dimensions(["355", "21", "778", "1"])
with calling .render().updateAxes()
after each try, but nothing seems to reorder them.
In an example I managed to reorder them with the first variant but only with great differences of numbers and for manual inputs.
Is any of the function mentioned above supposed to work?
If yes, which one and how? Thank you in advice!
Currently numerical dimension types are recognized as strings.
Hi,
I'm trying to use pc.selected()
to return all data within brush extents ("1d-axes"). For example,
var pc = ParCoords()("#example")
.data([
[0,-0,0,0,0,1],
[1,-1,1,2,1,1],
[2,-2,4,4,0.5,1],
[3,-3,9,6,0.33,1],
[4,-4,16,8,0.25,1]
])
.alpha(0.4)
.render()
.shadows()
.reorderable()
.brushMode("1D-axes"); // enable brushing
.on("brushend", function(brushed) {
console.log(pc.selected());
});
However, I get a "TypeError: pc.selected is not a function"
Am I using this function correctly? If not, how else could I obtain all data within the brush extents as an array? Apologies if the solution is obvious, I'm still new to Javascript. Thanks!
is there an example of making the chart a responsive design fitting the window size?
When an axis is upside down, regardless of whether it was flipped by double-clicking the title or with pc.flipAxes
, brushing on that axis causes all polylines to disappear. However, if the axis is flipped back to its normal orientation, brushing works as expected. Interestingly, there is no console error...
Hi there,
I'd really like to be able to use pc.bundleDimension()
without having to include sylvester.js
in my html header. The vector
function in this library is used for computeCentroids
and returns Uncaught ReferenceError: $V is not defined at computeCentroids
when sylvester.js
is not included in the script.
The good news is there is a somewhat new library sylvester-es6 which should be compatible with parcoords-es
and would be a quick fix.
I'd be happy to submit a pull request if you're ok with the dependency. Let me know.
@joshhjacobson mentioned a bug in #14 's follow up:
Another strange thing happens when working with two ParCoords variables:
var pc1 = ParCoords()("#plot01")
.alpha(0.4)
var pc2 = ParCoords()("#plot02")
.alpha(0.4)
// load csv file and create the chart
d3.csv('data/cars.csv').then(function(data) {
pc1
.data(data)
.hideAxis(["name"])
.composite("darker")
.render()
.shadows()
.reorderable()
.brushMode("1D-axes") // enable brushing
.on("brushend", function(){
console.log(pc1.selected());
console.log(pc2.selected());
});
pc2
.data(data)
.hideAxis(["name"])
.composite("darker")
.render()
.shadows()
.reorderable()
.brushMode("1D-axes") // enable brushing
.on("brushend", function(){
console.log(pc1.selected());
console.log(pc2.selected());
});
});
d3.select('#brushReset').on('click', function () {
pc1.brushReset();
pc2.brushReset();
});
The two plots seem to be linked, in that console.log(pc1.selected()) and console.log(pc2.selected()) always return the same data even when brushes are different between plots. Could this be because of the way I'm loading the data?
Interestingly, you must also click the brushReset button twice in order for both plots to refresh.
The multi brush feature works nicely, but in that mode it seems we can no longer click on the axis to clear the brushes.
In single-brush mode, it click-to-reset still works fine.
This can be seen in the included demo for multi-brushes.
Hi again,
In the same way that a user can specify pc.color()
with the argument being either a single color or a function, I think it would be useful if they could also specify line type. Canvas has the lineWidth
property and setLineDash()
method. Using these tools in conjunction, the user could specify many different line types. It could look something like this:
pc.lineType(width = 2, dash = [5, 15])
or
pc.lineType(function)
For charts with lots of lines this could get messy, but for more simple charts I think this could be very powerful. What are your thoughts? Would this be straightforward to implement?
Best,
Josh
Hi again,
I believe this is a minor formatting bug as it did not happen in the original parallel-coordinates examples. For longer axis labels, the left-most text is cut off at the edge of the chart's canvas layer. Below is a screen shot of the example in basic.html
where the economy (mpg) variable is cut off.
Just thought I'd bring this to your attention.
Best,
Josh
calling compute_real_centroids(row) returns nothing for me.
Tried data.map((row) => compute_real_centroids(row))
and just return an empty array for each row.
What am I doing wrong?
@BigFatDog, as I thought more about this the commit comments d95b853#r29660382 probably are not the best way to discuss new features :). Promoting this to a new issue will give us a better opportunity to discuss and track.
this call
works perfectly internally within parallel-coordinates. I struggle though with determining externally which brush we are working with on('brushstart', ...)
and on('brushend', ...)
. This example (with a modified old parallel-coordinates) demonstrates the objective. Would it cause any problems to change
events.call('brushstart', pc, config.brushed);
to
events.call('brushstart', pc, config.brushed, arguments);
which leverages https://github.com/d3/d3-brush/blob/master/src/brush.js#L286?? If we do this, then the second argument to pc.on('brushend', function(a, args) {}
will be the arguments which contain dimension. I am happy to submit a pull if you agree this is worthwhile.
can the line curve be modified?
In #6, a very helpful brushExtents
method was fixed and provided to the API. However, when setting brushExtents, I think we should use brush.move
instead of brush.extents
. I'm not sure how best to provide a reproducible example, so I recorded the screenshot below. I will submit a pull. Thanks.
Changing the scale with .dimension(dimension) is not working for me.
Setting a custom scale with yscale has been removed from the dimensions object in the axis-config example as well.
Hi @BigFatDog
Thank you one more time for porting this to ES6.
For some reason when installing from NPM, module name is not parcoords-es
, but parcoord-es
,
so npm install parcoord-es --save
works, while npm install parcoords-es --save
doesn't.
First of all, let me thank you for this awesome library, just a small fix here
https://github.com/BigFatDog/parcoords-es/blob/master/demo/upload.html#L159
Use d3.csvParse instead of d3.csv.parse
Thanks
Is it possible to match the behaviour of the original pcoords as shown here?
http://syntagmatic.github.io/parallel-coordinates/examples/brushing.html
In the above example, after applying a brush on an axis, if I click somewhere on the axis, the brush and the selection gets reset for that axis
In this version of the lib, it's a bit difficult to use. You can never really clear the brush on a single axis.
Firstly great work on parallel coordinates with updates on much needed D3 V4.
I have found a sample parallel coordinate with numerical and string axis in D3 V4 like this
http://plnkr.co/edit/dCNuBsaDNBwr7CrAJUBe?p=preview
I am looking to have multiple brush feature on an axis in that example ,something like this http://bl.ocks.org/bollwyvl/8463137 .
So do you have a demo example of multi brush in d3 V4, that may have both numerical and string axis and multi brush enabled on every axis?
Thanks for your time
Hey @BigFatDog, Thanks for developing this awesome library.
I am wondering if you could implement the change in brushExtent()
to load data from ordinal scales. Currently, it fails because to my understanding you expect scaled and inverted values for input.
It may be a good idea to get raw selection inputs and make it work on ordinal scale as well.
Often in integrated applications with parallel coordinates, I need the ability to filter the parallel coordinates from outside with other controls, such as HTML inputs or supplementary visualizations. Here is a very minimal example demonstrating the concept with a modified version of the original parallel-coordinates. Would you be interested in a pull request targeting this functionality?
As I mentioned, for the previous example, I modified the original parallel-coordinates to add outsideFilters
to the API as shown in timelyportfolio/parallel-coordinates@40fa0dc. This poc only targeted categorical/discrete filtering, but ideally I envision robust filtering that would cover all data types.
In all the brush modes, we have something like this before determining what is selected.
...
// Resolves broken examples for now. They expect to get the full dataset back from empty brushes
if (actives.length === 0) return config.data;
...
return config.data.filter(d => {
switch (brushGroup.predicate) {
case 'AND':
return actives.every(function(p, dimension) {
return within[config.dimensions[p].type](d, p, dimension);
});
case 'OR':
return actives.some(function(p, dimension) {
return within[config.dimensions[p].type](d, p, dimension);
});
default:
throw new Error('Unknown brush predicate ' + config.brushPredicate);
}
});
We could filter config.data
here first and then perform the selected logic to the filtered config.data
.
// Resolves broken examples for now. They expect to get the full dataset back from empty brushes
if (actives.length === 0) return config.data;
...
// apply outside filters
// assuming we have created an appropriate filter function
let filteredData = filter(config.data);
...
return filteredData.filter(d => {
switch (brushGroup.predicate) {
case 'AND':
return actives.every(function(p, dimension) {
return within[config.dimensions[p].type](d, p, dimension);
});
case 'OR':
return actives.some(function(p, dimension) {
return within[config.dimensions[p].type](d, p, dimension);
});
default:
throw new Error('Unknown brush predicate ' + config.brushPredicate);
}
});
I discovered search.js that might help with the API for filtering spec.
pinging @gordonwoodhull since you had some interest in the other pull and you have an enormous wealth of knowledge from dc.js
Is there any way to draw a horizontal line based on some value like we will have a separate Y axis scale then we want draw a horizontal line in the pcp chart.
Hello,
I have been referring to https://bl.ocks.org/syntagmatic/482706e0638c67836d94b20f0cb37122
for progressive rendering in parallel coordinate d3 v4. Do we have an example where we can reorder the axis; like drag and put the axis from one end to other.
Any help or suggested examples will be highly appreciated.
Thanks
@joshhjacobson has discovered this bug in issue #15
Thank @joshhjacobson for the detailed information
Thanks! This seems to have handled all the console errors, and axis reordering is mostly functional. While testing, I noticed a bug where the right-most axis seems to become disconnected from the canvas. You can still interact with all the other axes by dragging them around and brushing, but the right-most one is unresponsive. If you drag another axis toward it, the polylines will adjust accordingly, but the svg axis itself will remain fixed.
This was produced using the example above where I start with one axis hidden, and then click the button to 'show' it.
pc.scale(input_axis, [lower, upper])
successfully adjusts the yscale domain and ticks of an axis, but the axis itself is the only thing affected -- the polylines are not adjusted. How would I go about updating the plot to match the new axis domain?
I'm guessing it has something to do with pc.applyAxisConfig()
but I'm unsure what the correct parameters should be. Thanks for the help!
Hi,
I'm wondering what the correct syntax to flip an individual axis or set of axes is? In the original parallel-coordinates library, it went something like this:
pc.flipAxes(["x", "y"]);
but when I try that code here, there is no effect. I noticed that the flipAxes
syntax is found in the sideEffects.js
file, but there is another file in the api called flip.js
. The following does work, but only for one axis:
pc.flip(["x"])
When I try to apply it to more than one axis (i.e. pc.flip(["x", "y"])
), I get the following error:
TypeError: Cannot read property 'yscale' of undefined
at Function.flip (parcoords.esm.js:2898)
If you can point me in the direction of a solution, I may be able to implement this and submit a pull request. However, if it's a quick fix and you think it would be faster to take care of it yourself, that would be great too. Let me know!
Happy holidays,
Josh
Currently it is not possible to change axis stroke color through css.
In the parcoords.css
such css property is set to a default, but it has no effect because these properties are set with d3s .style()
function, having priority over css.
The values set through javascript are the same as the ones on the css sheet leading me to believe they are set as defaults.
Some of these properties are merely stylistic in nature, which could be useful if configurable (through css specialy), however some of them could be tied to the shape of the plot.
I could find some properties that could outsourced solely to the css sheet making them instantly configurable:
Stroke and Fill in: (maybe shape-rendering)
parcoords-es/src/api/createAxes.js
Lines 47 to 57 in dfd8d02
parcoords-es/src/api/updateAxes.js
Lines 32 to 42 in dfd8d02
Font in:
Lines 33 to 38 in dfd8d02
Also tried on the 'reddit' example in the included demo folder.
Whenever there's a string axis, the brush doesn't appear and stuff is not filterable.
This feature works on the original parcoords.
Can this be fixed?
Were there heavy modifications in this fork?
I have an a dimension with a fixed domain for rating: ['A+', 'A', 'B', 'C', 'D', 'E', 'F']
I would like those values to appear on the rating axis even when there's no record with A+
Is that supported?
Using the https://github.com/syntagmatic/parallel-coordinates version, I was able to get the desired result using ordinalScale with fixed domain/range.
Using the following code, I'm trying to set a brush extent, I just took this from the demo example.
this.parcoords = ParCoords()('#parcoords')
.data([
[0,-0,0,0,0],
[1,-1,1,2,1,
[2,,4,4,0.5],
[3,,9,6,],
[4,-4,16,8,0.25]
])
.render()
.createAxes()
.brushMode('1D-axes')
.brushExtents({"2": [3,4]});
But when the brushExtents gets executed I get an error in the brushExtents function:
ERROR TypeError: pc.g(...).selectAll(...).reduce is not a function at Function.eval [as brushExtents] (parcoords.mjs:100)
BrushExtents function:
var brushExtents = function brushExtents(state, config, pc) {
return function (extents) {
var brushes = state.brushes;
if (typeof extents === 'undefined') {
return d3Collection.keys(config.dimensions).reduce(function (acc, cur) {
var brush = brushes[cur];
//todo: brush check
if (brush !== undefined && d3Brush.brushSelection(brushNodes[cur]) !== null) {
acc[d] = brush.extent();
}
return acc;
}, {});
} else {
//first get all the brush selections
var brushSelections = pc.g().selectAll('.brush').reduce(function (acc, cur) {
acc[cur] = select(this);
return acc;
});
// loop over each dimension and update appropriately (if it was passed in through extents)
d3Collection.keys(config.dimensions).forEach(function (d) {
if (extents[d] === undefined) {
return;
}
var brush = brushes[d];
if (brush !== undefined) {
//update the extent
brush.extent(extents[d]);
//redraw the brush
brushSelections[d].transition().duration(0).call(brush);
//fire some events
brush.event(brushSelections[d]);
}
});
//redraw the chart
pc.renderBrushed();
return pc;
}
};
};
This is from discussion #72 Is it necessary to provide a React version for this library?
Originally posted by @jvmanke in #72 (comment)
Hey @BigFatDog maybe not build a separate library but maybe add some examples using it with react? I personally am struggling to get it working properly. Do you have a snippet I could look?
Need to provide a simple react app that with parcoords-es
.
I have a parcoords component set up and I'm trying to get the 'marked' data to appear very similar to selection via brushing. I've found that the line width option for marked doesn't actually change anything.
I'd appreciate also an easier way to make marked lines appear same as brushed lines. I'm using mark() to select data points that are selected in other components, and passed into parcoords. Brushed lines are used to propagate selected data back to other components.
@BigFatDog Thanks for this awesome port! I'm trying to embed parcoords-es in a way that supports resizing, brushing, and updating data. The combination of these three creates problems for me when using brush modes "1D-axes" and "1D-axes-multi".
It seems like some of this may be addressed by autodesk-forks/parallel-coordinates#1 and other recent commits in https://github.com/autodesk-forks/parallel-coordinates.
Is there any interest in trying to pull over these fixes? Or has the code diverged too much for that to be helpful?
Hi,
I believe this is a minor bug. When you double click the axis title to flip an axis, the polylines will update but the axis itself does not. The console gives: TypeError: brushes[d].event is not a function brushReset.js:24:10
Very best,
Josh
Hi! I keep getting these errors on 'ng build
' and before renaming the file './node_modules/parcoord-es/dist/parcoords.mjs' to something like './node_modules/parcoord-es/dist/Xparcoords.mjsX'. I use Angular 6. As I understand, there are some problems with webpack and .mjs files. What is the best way to deal with this problem. I keep getting these errors after each 'npm update
' of parcoords-es:
ERROR in ./node_modules/parcoord-es/dist/parcoords.mjs
1035:12-17 Can't import the named export 'mouse' from non EcmaScript module (only default export is available)
ERROR in ./node_modules/parcoord-es/dist/parcoords.mjs
103:29-35 Can't import the named export 'select' from non EcmaScript module (only default export is available)
ERROR in ./node_modules/parcoord-es/dist/parcoords.mjs
1090:16-20 Can't import the named export 'drag' from non EcmaScript module (only default export is available)
ERROR in ./node_modules/parcoord-es/dist/parcoords.mjs
1285:14-18 Can't import the named export 'drag' from non EcmaScript module (only default export is available)
.....
.....
There's a way to change the alphaOnBrushed
setting which is great, but if I then use the highlight
functionality that no longer gets respected. Is there a way to change the alpha
for non highlighted polylines too?
Set the nullValueSeparator
to bottom
causes the following error in console:
ERROR ReferenceError: h is not defined
It looks like the height
property is not accessible. Maybe you've forgot to import the heigh utility in index,js
file.
Any ideas?
@joshhjacobson mentioned this bug in #14's conversion:
pc.selected() will return the entire data set when no axes are brushed. Since nothing is actually selected, wouldn't we want to return an empty array in this case?
Hello guys,
I'm wondering if it is necessary to build a React
version of this library.
Currently I'm using this library in React
apps with React hooks.
I feel it would be better if there were a React
version, but only slightly better because I cannot see too much improvements there. I haven't found reason that firmly demands a React
version so far.
What do you think?
Yours
Yun Xing
When using the updateAxes
function, I get the following error: TypeError: node is null
For a reproducible example, I've added it to brushing.html:
// load csv file and create the chart
d3.csv('data/cars.csv').then(function(data) {
parcoords
.data(data)
.hideAxis(["name"])
.composite("darker")
.render()
.shadows()
.reorderable()
.brushMode("1D-axes") // enable brushing
.on("brushend", function(brushed) {
parcoords.updateAxes();
});
});
Any insight would be appreciated!
My axis dimensions have long names,
Is there a way to make them appear on 2 lines nicely ?
@ManiacalAce has discovered this bug in issue #10 Click-axis-to-reset-brush does not work with multi brush?
Thanks @ManiacalAce for the detailed descriptions, the bug is described as below:
@BigFatDog Seems like my issue stems from something else related to colors.
I was trying to have one color for regular, untouched stuff, and a different color for brushed items - which i could swear was possible in the original fork of this lib.
For example, If I have this (with color and brushedColor)
var pc = ParCoords({nullValueSeparator: "bottom"})("#example")
.data([
[0,-0,0,0,0,1],
[1,-1,1,2,1,1],
[2,,4,4,0.5,1],
[3,,9,6,,],
[4,-4,16,8,0.25,1]
])
.color('#0000ff')
.render()
.shadows()
.createAxes()
.reorderable()
.brushMode("1D-axes-multi")
.brushedColor('#ff0000')
Initially, the lines are blue, as expected. Then when I brush some items, they become red. Then, when I click to reset, everything is red (when I expect it to be blue).
Thank you so much for converting this! I discovered that render
and resize
events are no longer exposed as they were before (see lines). Was this intentional?
First of all, thank you for this amazing library!
In react app: I'd like to know how to call highlight on pc chart from a react-table or similar 'mouseover' row action.
App has 2 components:
How can the chart register to another component mouseover event. what's the best practice here so both component are not tightly coupled? any idea?
When using brushmode "1D-axes-multi" and performing a hideAxis call an error occurs in brus\1d-multi\brushreset.js
It seems properties are read in a forEach of an object (the axis that was just hidden?) that does not exist.
I modified the slickgrid example file to create a ready to use example, this example adds a button that removes three axes. This works OK for brushmode "1D-axes" but fails for "1D-axes-multi"
eg below code save as 'demo/slickgrid2.html'
<!doctype html>
<title>Linking to SlickGrid</title>
<!-- SlickGrid -->
<link rel="stylesheet" href="lib/slickgrid/slick.grid.css" type="text/css"/>
<link rel="stylesheet" href="lib/slickgrid/jquery-ui-1.8.16.custom.css" type="text/css"/>
<link rel="stylesheet" href="lib/slickgrid/examples.css" type="text/css"/>
<link rel="stylesheet" href="lib/slickgrid/slick.pager.css" type="text/css"/>
<script src="lib/slickgrid/jquery-1.7.min.js"></script>
<script src="lib/slickgrid/jquery.event.drag-2.0.min.js"></script>
<script src="lib/slickgrid/slick.core.js"></script>
<script src="lib/slickgrid/slick.grid.js"></script>
<script src="lib/slickgrid/slick.pager.js"></script>
<script src="lib/slickgrid/slick.dataview.js"></script>
<!-- End SlickGrid -->
<link rel="stylesheet" type="text/css" href="./parcoords.css">
<link rel="stylesheet" type="text/css" href="style.css">
<style>
body, html {
margin: 0;
height: 100%;
width: 100%;
overflow: hidden;
font-size: 12px;
}
#grid, #pager {
position: fixed;
width: 100%;
}
#grid {
bottom: 0;
height: 300px;
}
#pager {
bottom: 306px;
height: 20px;
}
.slick-row:hover {
font-weight: bold;
color: #069;
}
</style>
<script src="lib/d3.v5.min.js"></script>
<script src="./parcoords.standalone.js"></script>
<script src="lib/divgrid.js"></script>
<button id="show_ext">remove axes</button>
<div id="example" class="parcoords" style="height:240px;"></div>
<div id="grid"></div>
<div id="pager"></div>
<script id="brushing">
var parcoords = ParCoords()("#example")
.alpha(0.4)
.mode("queue") // progressive rendering
.height(d3.max([document.body.clientHeight-326, 220]))
.margin({
top: 36,
left: 0,
right: 0,
bottom: 16
});
d3.select('#show_ext').on('click', function() {
let hiddencolumns =['cylinders', 'power (hp)', 'year'];
parcoords.hideAxis(hiddencolumns);
parcoords.render().updateAxes(0);
});
// load csv file and create the chart
d3.csv('data/cars.csv').then(function(data) {
// slickgrid needs each data element to have an id
data.forEach(function(d,i) { d.id = d.id || i; });
parcoords
.data(data)
.hideAxis(["name"])
.render()
.reorderable()
.brushMode("1D-axes-multi");
// setting up grid
var column_keys = d3.keys(data[0]);
var columns = column_keys.map(function(key,i) {
return {
id: key,
name: key,
field: key,
sortable: true
}
});
var options = {
enableCellNavigation: true,
enableColumnReorder: false,
multiColumnSort: false
};
var dataView = new Slick.Data.DataView();
var grid = new Slick.Grid("#grid", dataView, columns, options);
var pager = new Slick.Controls.Pager(dataView, grid, $("#pager"));
// wire up model events to drive the grid
dataView.onRowCountChanged.subscribe(function (e, args) {
grid.updateRowCount();
grid.render();
});
dataView.onRowsChanged.subscribe(function (e, args) {
grid.invalidateRows(args.rows);
grid.render();
});
// column sorting
var sortcol = column_keys[0];
var sortdir = 1;
function comparer(a, b) {
var x = a[sortcol], y = b[sortcol];
return (x == y ? 0 : (x > y ? 1 : -1));
}
// click header to sort grid column
grid.onSort.subscribe(function (e, args) {
sortdir = args.sortAsc ? 1 : -1;
sortcol = args.sortCol.field;
if ($.browser.msie && $.browser.version <= 8) {
dataView.fastSort(sortcol, args.sortAsc);
} else {
dataView.sort(comparer, args.sortAsc);
}
});
// highlight row in chart
grid.onMouseEnter.subscribe(function(e,args) {
// Get row number from grid
var grid_row = grid.getCellFromEvent(e).row;
// Get the id of the item referenced in grid_row
var item_id = grid.getDataItem(grid_row).id;
var d = parcoords.brushed() || data;
// Get the element position of the id in the data object
elementPos = d.map(function(x) {return x.id; }).indexOf(item_id);
// Highlight that element in the parallel coordinates graph
parcoords.highlight([d[elementPos]]);
});
grid.onMouseLeave.subscribe(function(e,args) {
parcoords.unhighlight();
});
// fill grid with data
gridUpdate(data);
// update grid on brush
parcoords.on("brush", function(d) {
gridUpdate(d);
});
function gridUpdate(data) {
dataView.beginUpdate();
dataView.setItems(data);
dataView.endUpdate();
};
});
</script>
In version 2.2.0, the bug fix in the brushFor
function had the side effect of partially breaking hideAxis
. The function works when data is first added to the chart, but if called individually there is an error. The following, taken from the brushing.html
demo, demonstrates the issue:
d3.csv('data/cars.csv').then(function(data) {
parcoords
.data(data)
.hideAxis(["name"])
.composite("darker")
.render()
.shadows()
.reorderable()
.brushMode("1D-axes"); // enable brushing
// next line is the problem (added for demonstration)
parcoords.hideAxis(['year']).render().updateAxes(0);
});
This gives:
Uncaught (in promise) TypeError: Cannot read property 'yscale' of undefined
at convertBrushArguments (brushFor.js:29)
at SVGGElement.<anonymous> (brushFor.js:63)
at Dispatch.apply (dispatch.js:61)
at customEvent (on.js:103)
at Emitter.emit (brush.js:286)
at Emitter.brush (brush.js:278)
at SVGGElement.<anonymous> (brush.js:222)
at Selection.selection_each [as each] (each.js:5)
at brush.move (brush.js:212)
at Selection.selection_call [as call] (call.js:4)
In versions prior to 2.2.0, this was not an issue. Now, it seems that the axis
being referenced in brushFor.js
here
const convertBrushArguments = args => {
const args_array = Array.prototype.slice.call(args);
const axis = args_array[0];
// ordinal scales do not have invert
const yscale = config.dimensions[axis].yscale;
has already been removed from config.dimensions
in sideEffects.js
here
.on('hideAxis', d => {
pc.dimensions(pc.applyDimensionDefaults());
pc.dimensions(without(config.dimensions, d.value)); // this line
})
thus, config.dimensions[axis]
is undefined.
I would attempt to fix this myself, but I'm not really sure why it's happening. @timelyportfolio do you have any thoughts on this? Maybe we could delay execution of pc.dimensions(without(config.dimensions, d.value))
until after brushFor
has been executed?
I like the concept of displaying null data outside of the main chart, but I also would like to be able to include items that have a null value in the selection when brushing on that axis.
Either by a switch (include_nulldata_in_brush) per viewer, or per axis or by using a multi brush per axis and extending the brushable area to the axis regions where the null values are plotted.
Why: we use the parallel coordinate viewer for selection but when a measurement was not (yet) made it is uncertain. So the items could be within the brush range, we dont know. To be safe we would like to include these items
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.