d3.js scatter matrix with brushing - scale error - javascript

I try to reuse the example of 'scatter matrix with brushing': http://bl.ocks.org/mbostock/4063663
It seems that the code is not directly reusable with another csv. Scales seems to be somehow hard coded or so: i change the csv by adding 10 to 75% of the first column values, and the xscale is not directly updated.
To visualize the problem, see the fork of the mbostock gist: http://bl.ocks.org/fdeheeger/7249196
I cannot figure out where/how the scale is computed or updated in the javascript code.
Any advice from a d3 expert?

The scales are computed dynamically -- the problem is that the numbers in the CSV are parsed and processed as strings and not numbers. This is also the case in the original block, but there it doesn't matter because the ordering of the strings is the same as the ordering of the numbers.
All you need to do to fix this is parse the strings to numbers:
domainByTrait[trait] = d3.extent(data, function(d) { return +d[trait]; });
The plus makes all the difference here. Complete example here.

Related

Data being plotted is multiplied by 1000 on its own in Highcharts using Angular

The data I am trying to plot is of the form :
[
[24894174208.0, 1604842800],
[24903880704.0, 1604843100]
]
where x = data points; y = UNIX_EPOC_Time
while plotting I am interchanging x,y; so as to plot UNIX_EPOC_Time on X-axis & data points on Y-axis
I have to multiply UNIX_EPOC_Time by 1000 as: Javascript uses milliseconds internally, while normal UNIX timestamps are usually in seconds. ( Why do I need to multiply unix timestamps by 1000 in JavaScript? )
Also I am trying to find anomalies in the dataPoints which is being plotted with a dot (yellow/orange/red).
However, in the function
js[isIn(anomoly, point){...}]
where I find anomalies in dataPoints, I see the datapoints take the form as:
[1604923500000, 22179459072000]
instead of:
[1604923500, 22179459072.0]
due to which I have to divide the data point (here: 22179459072000) by 1000 to bring it to it's original form 22179459072.0 in order to plot it on the graph.
I am not sure why this is happening though.
I have reproduced the issue in stackblitz.
After some debugging, I finally found the source of the problem.
It is happening because of the way you are cloning your data.
let clone_element = { ...element };
The spread operator is not creating a deep copy of the element, it's just the shallow one meaning that some parts of the clone_element will still have a reference to the source of data causing mutation.
To fix that you could use for example the lodash's cloneDeep(). This function will produce a real deep copy, so there is no way you will mutate your initial data.
const clone_element = cloneDeep(element);
Live demo:
https://stackblitz.com/edit/highchart-highstock-pddlto?file=src%2Fapp%2Fapp.component.ts
Additional references:
What is the most efficient way to deep clone an object in JavaScript?
https://dassur.ma/things/deep-copy/
https://lodash.com/docs/4.17.15#cloneDeep

D3 multiline chart on update crosses axis

I am trying to plot a multiline d3 chart. I have created a method which should take a new dataset and try to plot it in the same d3 frame for new data update changes (possibly filters).
The first draw works fine but the next draw (mocked data: which is a slice of the previous data and few manipulated values) is not showing correct is crossing the x axis.
[See Image below]
Also the starting origin is missing a tick which should also be 2010 in this example
I also want to create few more lines if there is more datapoints in the future which should be dynamic. Current model is {date, actual, projected}, More expected is mean or difference which will only be shown on trigger.
Any help would be appreciated.
Here is a Stackblitz https://stackblitz.com/edit/angular-rhr39p
References:
Animated line chart: http://bl.ocks.org/atmccann/8966400
Multiline chart: https://bl.ocks.org/larsenmtl/e3b8b7c2ca4787f77d78f58d41c3da91
Dataset updates: https://bl.ocks.org/d3noob/7030f35b72de721622b8
Please keep just one problem per question here at Stack Overflow. This answer will deal with problem #1, consider asking separate questions for the other problems.
The issue here is just your enter/update methodology, that is not correct and. Stick with the idiomatic D3, which is along these lines:
const update = this.svg.selectAll('.records')
.data(records);
const enter = update.enter().append('g')
.attr('class', 'records');
Then, you append new paths using enter and update those paths using update.
You can also ditch the groups and create enter/update/exit selections for the paths directly. That will make your code simpler.
Here is the forked code: https://stackblitz.com/edit/angular-lyd79t?file=src%2Fapp%2Flinechart%2Flinechart.component.ts

Parallel coordinates with d3.js

I need to to represent a Parallel Coordinates with d3.js. First of all I have no idea if what I think is possible to achieve (and if the Parallel Coordinates is the right chart).
I will explain my idea: I take data from a database and I expose them in a JSON and I store them in an array of objects (with JavaScript).
This is an example of the data http://pastebin.com/DZcMqDMc.
I would like to represent along the abscissa axis years (though there are years repeating themself, as you can see from data example), while along the ordinate axis values of those years (values are in percent, ranging from 1 to 100).
I would like to represent two lines according to "value1" and "value2" property in the JSON file.
Is it possible? Is Parallel Coordinates the right chart?
The main problem I have right now is that I do not understand how to set right the two domains (abscissa and ordinate).
I am basing on the example Parellel Coordinates of Bostock.
For abscissa I am thinking something like that:
x.domain(
d3.extent(test,
function(d) {
return d.years;
}
)
);
It makes sense or?
Try a multi line chart.That might suit your need.
I am not sure what you are trying.
Simply do a line chart, and produce the vertical lines by formatting the ticks to go from 0 to height ( in your var xAxis code include .tickSize(0-height)). You will have to pick the right number of ticks, as in ticks(), so you just get the lines where you want them.
Check out Parcoords, a d3-based parallel coordinates library. For compatibility with d3 v5 see https://github.com/BigFatDog/parcoords-es which is based on the original Parcoords library (https://github.com/syntagmatic/parallel-coordinates) which relies on an outdated version of d3.
For examples and sample code, check out the following link: http://syntagmatic.github.io/parallel-coordinates/.

Error parsing data when drawing d3 line chart

I'm trying to draw a difference chart (like this one) but using a more modular style.
So far, I've got as far as reading in two dummy CSV files, combining the data, generating a chart, and am now trying to just draw a single line from one part of the data, but I keep getting an error. The full code is available on bl.ocks.org.
The error is:
Error: Problem parsing d="M0,221.73913043478262LNaN,182.60869565217394LNaN,195.6521739130435LNaN,156.52173913043478L500,91.30434782608697L500,91.30434782608697LNaN,156.52173913043478LNaN,195.6521739130435LNaN,182.60869565217394L0,221.73913043478262Z"
which occurs when doing this:
g.select('.line').attr('d', line);
At that point (as seen in the console), data is:
[{"year":1999,"imports":15,"exports":19},{"year":2000,"imports":18,"exports":20},{"year":2001,"imports":17,"exports":30},{"year":2002,"imports":20,"exports":32},{"year":2003,"imports":25,"exports":9}]
xScale.range() is:
[0, 500]
xScale.domain() is:
[1999, 2003]
yScale.range() is:
[300, 0]
and yScale.domain() is:
[9, 32]
I'm guessing there's a simple error somewhere in there, meaning the wrong data is being used to draw the line, but after several hours trying to fix this, I can't see what I've done wrong.
You are using an ordinal scale, which doesn't interpolate between values. The domain of that scale consists of two elements, and it will map those to the two elements in the output range. That is, 1999 is mapped to 0 and 2003 is mapped to 500. For any other inputs, the scale will return NaN as the value isn't in its input domain.
You can fix this by specifying all the years you want mapped in the domain and the corresponding output values in the range. In your case, the easiest would be to use a linear scale though as that seems to be what you're assuming will happen with your current scale. You would simply need to replace the definition of the scale and how the range is set. This is what I have done here.
Alternatively, you could use a time scale as that would give you potentially better labels.

NVD3 - configuring ticks on axis

I have a nvd3 line chart which displays a time series and can't get the ticks on the x axis right.
For longer time spans, it works as expected. But for shorter time spans (here: 12/31/05 to 01/01/06), the same date is displayed for multiple ticks:
Please have a look at the code for this chart on JSFiddle
I want the chart to only display ticks at data points, and not in between. Is that possible with a line chart? From my understanding, it is possible with d3, but I can't figure out if this functionality is exposed by nvd3.
I've tried explicitly setting the number of ticks with chart.xAxis.ticks() without success. The only thing that has any effect is explicitly setting the tick values with chart.xAxis.tickValues([...]), but I would prefer not having to calculate them myself.
The way to solve this in general is with custom multi-scale time formats. Note that this example itself will not work with NVD3 because it uses an older version of D3, the examples below will though.
The problem in your case is that the ticks aren't "clean" divisions of time and if you apply a multi-scale format, you get something like this. It always shows the more fine-grained format because anything else would involve a loss of precision.
You can however use a simple heuristic to show the date instead of the time if the hour is less than 3, which works reasonably well in your case. See here for an example. The proper way to do this would be to make your ticks clean divisions.
Which brings us to your actual question. There's no other way than to explicitly set .tickValues() for what you want to do, but you can compute the x positions in your data quite easily:
var xvalues = [],
tmp = data.map(function(e) {
return e.values.map(function(d) { return d[0]; });
});
xvalues.concat.apply(xvalues, tmp);
The code is not the prettiest because it's a nested structure, but fairly straightforward. Using this, you can set your tick values explicitly, full example here.

Categories