I'm using d3.js to make a simple line graph. I want to know if there's a way to create "holes" in the graph, that is, if the line can be interrupted or cut when there is no data available.
I'm looking into either delete the places I don't need from the domain, or setting the line weight to 0 in specific segments, but I can't find a way to do either of these.
Thanks for your help!
The D3 line generator has a built in function to do just this, line.defined. You can use this function to control where your line is defined and where it is not (like where you have missing data.) If you wanted to make your line undefined whenever the second value in the point array is a javascript NaN value, you could say:
line.defined(function(d) { return !isNaN(d[1]); });
Here is a good example of this in action.
Related
Is there a way to inspect which variables (and lines of code) contribute to a value in Javascript? For example if I would inspect the parameter input in this code
let x=5;
let y=x+3;
function a(input) {
// analyzing input in this scope/context,
// i would like to see that it is a combination of
// x from line 1 and a constant '3' from line 2.
inspectDataFlow(input);
}
a(y);
I would like to get as output a data structure that would be something like this:
input (line 8)
y (line 2)
x (line 1)
"3" (line 2)
Purpose and goal
My goal for this would be to have a tool where you could see/change the value of a Javascript variable and it would automatically adjust the variables that the value originates from.
For example, you could have a function to draw shapes. And when you adjust visually the shapes that were drawn, the original variables for color, shape positions etc would update accordingly.
Something a bit like this but for editing arbitrary code, even after a user has modified the code lines:
http://yining1023.github.io/p5PlayGround/
Another idea I was thinking was to visualize how a variable has been composed: which lines it is a combination of and how they affect the result.
Potential approach
One approach for this I'm thinking about is to add instrumentation to the code with Esprima/Acorn that is then called on runtime. The instrumentation would keep track on which variables have been called on which lines (and scopes) and how they relate to each other, a bit like this:
http://alltom.com/pages/instrumenting-javascript/
I wonder if this would work and if there is a framework one could use for this? Or if one would have to do the instrumentation from scratch?
Related themes
This could be related to data flow analysis or use-define chains, but I'm not sure, since I don't know much about compilers.
https://en.wikipedia.org/wiki/Use-define_chain
My first idea was that this could be done using static analysis with something like Esprima/Acorn, but I'm not sure if that is the right way, or if this could be done with some custom Javascript interpreter instead.
http://tobyho.com/2013/12/02/fun-with-esprima/
Yesterday Plotly release the new feature animation!!! So I was very eager to test this out, and with the current lack of documentations (temporary I suppose) I'm struggling quite a bit on how to use it.
I did have a peek into the code on GitHub, but ... not working.
I define my div element in the template:
<div id="plotDiv"> </div>
I wanted to have the plot responsive to resize events, thus I followed the example on the plotly website:
const d3 = Plotly.d3;
const gd3 = d3.select("#plotDiv")
.style({width: "95%", "margin-left": "2.5%"});
const gd = gd3.node();
Then generate the data (bits of angular magic and other things) but in the end it looks like this:
data = {x: [array_ot_dates], y: [array_of_not_so_random_values], type:'bar'};
According to the jsdocs for the animation function, you need to pass a frame:
let plotlyFrame = {data:data, layout:{}};
Try to call animation!!!
Plotly.animate(gd, plotlyFrame);
And there it goes Kaboum!
First error is: This element is not a Plotly plot: [object HTMLDivElement]
But when I try this:
Plotly.newPlot(gd, data, {});
I have my plot...
So I tried to "predefine" gd by calling Plotly.plot with empty data and then the animate function...
Plotly.plot(gd, [], {});
// make my data not empty
Plotly.animate(gd, plotlyFrame);
And then I get the following error:
plotly.js:116922 Uncaught (in promise) TypeError: Cannot read property '_module' of undefined(…)
Possibly the second could come from the fact I'm using angular and thus calling the function at one point 3 times in a close row.
Any advices? Ideas?
I'm the person who worked on the animation feature! First of all, you can find the documentation here.
Regarding your specific question, it looks like the answer is that you need to initialize the plot before you animate it (I'll add this to the documentation!). For example:
var frame = [{
data: {
y: [...new values...]
}
}]
Plotly.plot(gd, [{x: [...], y: [...]}]).then(function() {
Plotly.animate(gd, frame)
});
If some sort of user input is triggering the animation, the promise probably isn't necessary (since the input event will handle things and is pretty unlikely to get fired before Plotly.plot has had a chance to initialize).
Additionally, at the very least I believe you'll need to actually initialize the plot with the trace you wish to animate. I think you can probably get away with empty data, but you'll still need to at least have a trace defined, e.g. Plotly.plot(gd, [{x: [], y: []}]). I think the issue with your attempted fix is that [] for a list of traces is still empty as far as Plotly is concerned since that tells it nothing about the type of trace that exists. Also FYI, one thing the feature is not really designed to do is to draw the initial plot in a fancy manner. That could likely be accomplished, but it's not automatic given animate on an empty plot.
I hope that's enough to clarify issues! It was a pretty large feature, so we'd love feedback and to hear about successes/failures with it!
Is it possible to connect a line graph while passing over the values that are 0? Here is a fiddle:
standard highcharts code in fiddle.
http://jsfiddle.net/utnz2b9e/15/
What I would like to have happen is that rather than dipping all the way down to 0 in March and then all the way back up in April, I'd like it to just connect straight from February to April. However, I want to allow them to drag the point up from 0 and refresh the graph so I can't just skip over those points, and since I'm using dates I couldn't have gaps there anyways.
Any help with this would be much appreciated, thank you so much!
It is indeed possible.
Assuming the data you are presenting has unwanted 0 values in it, you can easily null them, and order highcharts to connect those null points with non nulls.
This is done by adding the property connectNulls:true which is added to the series object.
After that, you can go through your series data, and null the points. In your example Iv'e done that after the chart was rednered:
var chart = $('.actualPlansPlot').highcharts();
$.each(chart.series[0].data, function(i, point){
if(point.y == 0)
{
chart.series[0].data[i].update(null);
}
});
As you can see, Iv'e iterated through the series points and nulled any zero point, using the generic update method.
You can see this yourself:
http://jsfiddle.net/utnz2b9e/24/
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.
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.