How can I add custom data annotations to a dc.js chart? - javascript

I currently have a fairly basic composite line chart that looks like this:
I would like to add the following "dynamic" annotations to it:
By "dynamic" I mean that these totals and computed ratio need to be updated whenever the date filter is changed by the user, or there is a brush selection.
I am stuck on two aspects:
What is the recommended way to approach this? So far I have explored two paths:
Drawing SVG elements into the chart using a renderlet: I'm not able to access the crossfilter object to retrieve the data.
Create a custom D3 rendering outside of the chart: I'm not able to get the stats to update when the date selector is changed or the chart is 'brushed'. Also, this somehow reduces the flexibility of having the annotations within the chart itself (as far as I understand).
As an aside, can the ratio be computed directly in crossfilter? If so how?

The way you have this mocked up, I would recommend just setting these up as separate charts. Probably the best option is to use dc.numberDisplay.
Regarding computing ratios - yes, you can compute them in Crossfilter, but don't do that. Maintain both components of the ratio on a single Crossfilter group (using custom reducers, Reductio, or Universe) and do the division at reporting time. In dc.js, this means calculating the ratio in the valueAccessor of the chart.

Related

Bokeh, zoom only on single axis, adjust another axis accordingly

How can one make bokeh use zoom only on one axis and automatically scale objects, so they take exactly the space given and add some padding on extreme points off zoom-able axis parallels, while rendering empty space out of scope?
In other words (or "madskills" to be exact):
Example plot.
This is most widely used for stocks plotting, so consider I want to copy zoom behavior of https://www.tradingview.com/chart/?symbol=FX:XAUUSD with Bokeh.
Thank you in advance.
Zoom on X axis only by using 'xwheel_zoom' tool:
from bokeh.plotting import figure
fig = figure(tools='xwheel_zoom', active_scroll='xwheel_zoom')
Auto-scale the other (Y) axis by invoking a custom JavaScript event whenever the first axis changes. In this event, you scan through the visible data and amend the axis range. Like in the following gist example: https://gist.github.com/kernc/719918ada11298168efd956afc1a04a8
As of Bokeh 0.12.7 there is nothing built-in that will do this. Auto-ranging is always over the entire data set. There is no option to have auto ranging happen only over a subset of the data that is currently visible according to the extents of some other dimension.
It's possible to extend Bokeh, so it it conceivable that you could write a custom extension subclass of DataRange1d but it would not be a completely trivial matter:
http://docs.bokeh.org/en/latest/docs/user_guide/extensions.html
However, it seems like a reasonable feature request, so I'd encourage you to file a GitHub issue to discuss adding this capability directly to the core library:
https://github.com/bokeh/bokeh/issues
FWIW Bokeh now has ywheel_zoom along with a number of other options introduced: https://github.com/bokeh/bokeh/pull/4841/files#diff-b846337d25cde71b26a5158abd54a002de416da396954ec636ff006a6d80da81R222

Using dimensions with arrays in dc.js for treemap

Since crossfilter (1.4.0-alpha.6) allows use array as a dimension value, is it possible to use it for treemap viz for a nested tree? https://github.com/dc-js/dc.js/pull/1034 It works perfectly for one value, but what if I want more. It seems that approach that was used for dc.js treemap example can't work with the new feature of crossfilter.
I have a data structure with a couple of multiple values so I can't unwind them due to performance.
Now I'm thinking to create 2 treemaps for 2 different array dimensions, and after selecting the key on first, hide it and show the second treemap... Maybe, guys, you have much better ideas?

Merge two or more graphs using library

I am trying to make a dynamic graph something like as below:
Y-axis gives no. of users and x axis date range(For continuous graph )
x axis gives release of an algo on that date.(For discontinued graph)
I tried combined charts of highchart this and looked in google charts library.
Is there any way by how i can either directly generate a similar chart or merge two chart types in to one? Preferably using high charts or google graphs.
I guess we can merge two highcharts in to one but I am not very sure about it, also if we can Iam not sure how to do that.
Any help is appreciated.
Thanks
I am aware that you said "Preferably using high charts or google graphs", but I want to point out that this can be done very easily in C3.js using the "types" parameter to specify the graph type for each data item.
Demo: http://c3js.org/samples/chart_combination.html
I would suggest using plot bands to indicate release dates and types. You can dynamically add them using the addPlotBand() method (see http://api.highcharts.com/highcharts#Axis.addPlotBand). They would then overlay your "run of the mill" line chart showing number of users over time.
Assuming you have data that can distinguish between the release types, you could write code that adds a plot band of the desired color at the specific points on the x-axis.
I'd suggest making the plot bands have a from and to value thin enough (say, one interval or one date's worth) so it shows up as the thin stripes in your example.
You'd need to add a manual legend to show users what those colors mean, since plot bands wouldn't automatically show up in a Highcharts legend.
I hope this helps!

Custom Chart with Highcharts / Highstock

I'm trying to create a custom chart based on the Highstock Basic Line Chart.
To be more exact I'd like to create a drawdown-chart (see drawdown chart on wikipedia). I don't want to discuss the formula :), but the way to change the data display in Highstock/Highcharts following a certain rule. It could be a more simple one: imagine you want to display f(x) = 100 for every data point although your data is completely different.
The following requirements shall be fulfilled:
I want to use as much functionality as possible from Highstock like scaling the chart axes, call redraw on "dragging" the time line, etc.
I want to use the Highstock patterns to extend its charts: wrapping or pushing event listeners and in doing so, ensuring my code stays readable and maintainable.
The best try was to wrap the processData function. In its body I manipulated xData and yData and called the super method as explained here: Extending Highcharts
The chart broke displaying certain time ranges. The original data seemed to be displayed there.
I can't get any further unaided. I would be really happy if someone could help me with that.
Thanks in advance!
Niels
1) You can catch redraw event and then call your actions.
Scalling axis by parameters:
http://api.highcharts.com/highstock#yAxis.height
http://api.highcharts.com/highstock#yAxis.top
Dynamically
http://api.highcharts.com/highcharts#Axis.update

D3.js scattergraph with large (>500,000) points? Clustering?

I'm looking at plotting a scatterplot with a large number of points (500,000 and upwards).
Currently, we're doing this in Python with Matplotlib. It plots the points, and it provides controls to pan and zoom. I don't believe it provides any clustering or points, it just plots them all - doesn't make much sense at the zoomed out view, I suppose, but you can zoom in and they're all there.
I was looking at doing the chart in JavaScript, to make it a bit easier to distribute. I was looking at D3.js, to see if something similar is feasible there. I did find this example of a basic scatterplot:
http://bl.ocks.org/mbostock/3887118
Firstly, would you be able to plot that number of points? (500,000 and upwards) I was under the impression you couldn't due to the overhead of all the DOM objects? Are there ways around this?
Secondly, is there any kind of clustering available, either a library or even just an example of this being done in D3.js?
Thirdly, if anybody knows any good examples of pan/zoom functionality and clustering, or even just a packaged JS library that handles it, that would be awesome.
Fourth, it would be also nice to have click handlers for each point - and to display some text either in a overlay, or even just in a separate window. Any thoughts on this?
Can you draw half a million points with D3? Sure, but not with SVG. You'll have to use canvas (here's a simple example with 10,000 points that includes brush-based selection: http://bl.ocks.org/emeeks/306e64e0d687a4374bcd) and that means that you no longer have individual elements to assign click handlers to. You will not be able to render half a million points with SVG, because all those DOM elements will choke your interface, as you mentioned.
D3 does include quadtree support that can be leveraged for clustering. It's in use in the above example to speed up search but you could use it to nest elements in proximity at certain scales.
Ultimately, your choices are:
1) Some other library/custom implementation that renders in canvas and polls the mouse position to give you the data element rendered at that point.
2) A sophisticated custom D3 approach that nests elements in proximity and only renders SVG elements appropriate at the zoom level and canvas position (pan) you're at.
Yes, D3.js can be made to work with million scale data with two things:
pre-rendering on the server side. For more see here: https://mango-is.com/blog/engineering/pre-render-d3-js-charts-at-server-side/
By aggregating (or clustering) part of the data so that user can interact and expand the graph if need be. For this use collapsible nodes if you can (http://bl.ocks.org/mbostock/1062288).
Also avoid using force layout. It takes time to settle and converge to a stable positioning.
For clustering libraries, I would pick one up off the shelf. I would choose the scikits library from python, there are many in JavaScript but they are not very robust as they mostly cover k-means or hierarchical clustering. I would precalculate the coordinates using scikits by clustering and then render it using D3.
D3 handles Pan and zoom. Again click handlers and text display are available in D3. (http://bl.ocks.org/robschmuecker/7880033)

Categories