dc.js - Yearly average values for previous years + monthly for current year - dc.js

I'm trying to find a way in dc-js to draw a chart that would display monthly values for current year but yearly averages for previous years. Is this possible provided that the date axis is dynamic? I was thinking of grouping records by year before passing them to dc.js but the chart will just leave blank gaps on the x axis.
I would like to achieve the similar result to the attached excel screenshot but on a web-based interactive solution.

You will need to use an ordinal domain for this purpose.
If you use a time-based scale, then the bars will always be positioned based on a linear mapping of dates to X coordinates. This explains the gaps you are seeing.
Instead, you can define the ordinal domain explicitly:
var domain = ["2015 Average", "2016 Average", "2017 Average", "201801", "201802", ...];
chart
.x(d3.scaleOrdinal().domain(domain))
.xUnits(dc.units.ordinal)
You'll also need to change your group key function accordingly:
var group = dimension.group(function(d) {
return d.date.getYear() < 2018 ?
d.date.getYear() + " Average" :
d3.timeFormat('%Y%m')(d.date);
});
I'm not sure how you intend to calculate the averages, so I won't get into that.
Unfortunately (or fortunately, depending on your purposes) this will change the selection behavior so that instead of a continuous X brush that you can drag, you'll have to click on individual bars in order to select them. There are some ways around that, but they are kind of tricky, so lmk if this is a problem for you.

Related

Q: Recharts hide every other label?

Hiyas, I'm wondering if it's possible to render every other xAxis label in recharts?
I have a design I'm working from that has vertical grid lines on either side of an xAxis label. So, I'm using <ReferenceLines> in place of a <CartesianGrid>, and that seems to work well. However, I haven't found a way to render only some of the xAxis labels.
I could mutate the date coming into the chart, but then I lose the data-points date value in the <Tooltip> hover. Which if possible I'd like to keep.
Here's effectively what I have:
And here's what I'm aiming for:
Ok, so I found a "way" by leveraging the tickFormatter attribute on <XAxis />. Albeit, the best approach would be for tickFormatter to return index like some of the other recharts components offer with format. However, for the time being I'm simply finding the index of a given xAxis label, from my dataset, and then checking if it's an even/odd number.
What you're looking for is the interval attribute. This controls whether to show all or some of your xAxis labels. By default it is set to preserveEnd which auto calculates how many ticks to show.
If you want to show all ticks, you must set interval=0
Docs https://recharts.org/en-US/api/XAxis#interval

dc.js animated selection along x-axis

I'd like to have dc.js chart which slides along a selection, e.g. in the Nasdaq example https://dc-js.github.io/dc.js/ you would select a sub-selection of time then click "animate" button and the selection filter would slide along the x-axis at a pre-determined step size.
I'm a bit lost as to where one would start...does anyone have any ideas?
Most of what you need to do is set the current filter on the relevant chart based on a timer, instead of based on user interaction.
I've copied the relevant parts of the Nasdaq example into a fiddle to illustrate this: https://jsfiddle.net/0zkbyyqu/9/
Once the charts are in place, the animation is just a matter of changing the filter based on a setInterval. For obscure reasons, we want to use the focus method of the moveChart, not the filter method, but it's essentially doing the same thing, with a little more code to reflect the changes in the range chart:
var beginYear = 1985;
window.setInterval(function() {
moveChart.focus([
new Date(beginYear, 0,0,0,0,0,0),
new Date(beginYear+3, 0,0,0,0,0,0)]);
if(++beginYear > 2009)
beginYear = 1985;
}, 1000);
(If you were using the filter method, you'd have to construct a dc.filters.RangedFilter, as detailed here: Initial Range selection in DC.js chart)
I have left off your idea about the initial selection of the range coming from the user, and just gone with a range of 3 years. This example just starts animating as soon as it is loaded. You can fetch the current filter using chart.filter(); the result will be a RangedFilter, which is an array of two dates. Hopefully it is clear how to add start/stop buttons to the animation.
A couple of things are tricky about this approach:
It's tricky using a chart with transitions when you also have a timer or streaming data. In this case, I had to reduce the transitionDuration to 500ms for it to make any sense, but the cause-and-effect is still a little confusing. Not sure what to do about this.
The area chart transitions are incorrect so you get some weird artifacts.

Chart-like object (but not a gantt or stacked bar chart) in d3 -- where to start?

I have a chart I've created in excel that I'd like to replicate in d3, but I'm not sure where I should begin.
It's intended to show which character is speaking at which moment during a play, and so it visually looks similar to a gantt chart or stacked bar chart but it isn't working off of time the way a gantt chart would. Am I right in thinking that it'd be a bar chart or series of bar charts? Could I build it up by a series of 1 pixel wide bars, so that each pixel would equal a line in the play?
I'd provide code but I tried to modify the standard stacked bar chart and all I've really been able to do is either make the whole thing blank or modify the canvas dimensions. So I'd appreciate some suggestions to get me started.
it seems to me that the only (and big!) trouble you'll have here is creating the JSON. Once you have the JSON, it will be a piece of cake! Here is what I thought:
Create a very big JSON that is just 1 big array of hundreds of objects. Each object would be like this:
{"character": "John Doe", "place": "tavern", "duration": 5}
Then, you'll append the narrow rectangles using an ordinal scale for the places ("place") on y axis, setting the x position according to the cumulative duration of previous speeches and setting the width using the duration of each speech, and using CSS you can color the bars according to the character (using character for setting the class).
For this, you would use D3 only for the scales, avoiding the typical selection().data().enter().append() pattern and appending each rectangle in a for loop. Let me explain. Suppose you put your JSON in a variable named data. Then, you do:
for (var i = 0; i < data.length; i++){
var speech = data[i]
//rest of the code
}
This allow you, for each loop, to know the y position of the bar using speech.place, the name of the character using speech.character, for the colors, and the duration of the line using speech.duration. For calculating the x position, you declare a var duration; outside the loop and, inside it, you write:
duration += speech.duration;
In this approach, once you would use the cumulative duration for x position, the objects in the array must to be in the exact chronological order of the play.
PS: D3 is so nice that you can create an additional value named "line", for each object, with the actual line spoken by the character, and when the user hover over the rectangle he/she will see the text of the speech!

Birt: Formatting chart tooltip and adding aggregation to a chart tooltip?

I have three questions regarding Birt Tooltip
1) How do I format the number in the default tooltip (If I am not adding anything to the tooltip text). I tried to change the format of tooltip of Y Value Series but I realized that only works if I have put an expression in the tooltip of the Y Value series. I have not edited the tooltip of Y Value series, the chart will show the default data label instead and I am not sure how to format the default tooltip
2) I have plotted sum(revenue) on Y axis and months on x axis. I wanted a custom tooltip so I edited the tooltip expression of the Y Value series in chart. What I found was that the default tooltip was showing correct value but If I put the same expression row["revenue"] in the tooltip, the tooltip shows a data value that is much less than sum(revenue) that is plotted in the bar. I believe that this is because the tootltip is not aggregating the revenue? If Yes, then how do I put the sum(revenue) in the expression?
3) I wanted to add another information (count of units sold) so I created an aggregation count(unitssold). I called this cnt_unit_sold and added this to the tooltip of chart. The problem is that if I put my mouse over a month bar, the tooltip shows aggregated count for all months rather than that specific month. How can I add grouping to the aggregation so that it shows the aggregated count for each month rather than for all months
Regards
Arif
OK, so in case if someone has not found an answer to this question, here is the answer. In order to add aggregation to the tooltip, you need to create aggregate outside the chart's contains (for example create aggregation inside a grid). Then you can use that aggregation in the tooltip
Arif
I someone is still trying to achieve this, now you can use "valueData" instead.
row["dim1"]+" for "+row["period"]+" : "+valueData
in my example (the code goes in the tooltip expression) I asm using a stacked barchart, dim1 is the series used to stack values and period is the X series. Valuedata is the Y value (aggregated)

dc.js - is it possible to show the user grab handles upon page load

I'm building a basic dashboard for internal use. I've little experience with D3 / SVG etc so please excuse me if this is obvious:
Aim
I have a time series of values, one value per date for a full year. Inspired by the example on the dc.js wesbite, I'm displaying a 'mini' bar plot of the entire series, and allowing the user to select a range which in turn sets the limits of the axis scale range of a 'large' line plot.
By default (on page load / refreshAll()) I've set the limits of the large line plot to be the most recent 60 days.
The user is encouraged to set their desired range using the mini plot at the bottom, and when they do, the 'grab handles' appear and the chosen range is highlighted on the mini plot, for example:
My issue
On page load / refreshAll(), the grab handles and range highlighting aren't shown on the mini plot, for example:
Question
Is there a way I can set the grab handles to appear upon page load?
Here is how i do it by using crossfilter and dc.js. You can get the last x days by doing something like:
xrange = d3.extent(data, function(d) { return d.date; });
last60 = [d3.time.day.offset(xrange[1], -60), d3.time.day.offset(xrange[1], 1)]
Assuming you have a date in your data. Do this after reading the data with d3, but before feeding it into crossfilter.
Then for the bottom chart (mini plot) simply set the filter property to:
.filter(last60)
And also set the xrange for the top chart to the same range:
.x(d3.time.scale().domain(last60))
Something like this might also work for setting the xrange, but i havent had any success with that:
topchart.focus(bottomchart.filter())

Resources