3

I need to create a rowchart in dc.js with inputs from multiple columns in a csv. So i need to map a column to each row and each columns total number to the row value. There may be an obvious solution to this but i cant seem to find any examples. many thanks S

update: Here's a quick sketch. Apologies for the standard
Row chart;
column1 ----------------- 64 (total of column 1)
column2 ------- 35 (total of column 2)
column3 ------------ 45 (total of column 3)

Gordon
  • 19,811
  • 4
  • 36
  • 74
user3836998
  • 65
  • 1
  • 8
  • Can you change the structure of your data? Rather than have {cost: 1, revenue:2, overhead: 3} could you make it [{amount: 1, category: 'cost'}, {amount: 2, category: 'revenue'}, {amount: 3, category: 'overhead'}]; Once you do this change, you can use a standard row chart with a category dimension and reduceSum group. – DJ Martin Jul 14 '14 at 14:43
  • i tried this originally but i have quite a few different row charts that follow this pattern (4 so far) so it got confusing calling updates across multiple crossfilters. Ive already got two different structures of the data where a single row has a monthly version and i update across them throuh a unqiue id. I take it theres no easy solution for this then that i've missed – user3836998 Jul 14 '14 at 15:06
  • I think your options are 1) Composite Chart, 2) Stacked Chart, and 3) Change Data Structure. Composite chart sounds like your best fit. Once you build the "column" charts you can combine them into one chart using the composite chart. You'll likely need to manually manage row gaps and offsets, however, so that the rows don't overlap each other when you combine the charts. – DJ Martin Jul 14 '14 at 15:18

2 Answers2

5

Interesting problem! It sounds somewhat similar to a pivot, requested for crossfilter here. A solution comes to mind using "fake groups" and "fake dimensions", however there are a couple of caveats:

  • it will reflect filters on other dimensions
  • but, you will not be able to click on the rows in the chart in order to filter anything else (because what records would it select?)

The fake group constructor looks like this:

function regroup(dim, cols) {
    var _groupAll = dim.groupAll().reduce(
        function(p, v) { // add
            cols.forEach(function(c) {
                p[c] += v[c];
            });
            return p;
        },
        function(p, v) { // remove
            cols.forEach(function(c) {
                p[c] -= v[c];
            });
            return p;
        },
        function() { // init
            var p = {};
            cols.forEach(function(c) {
                p[c] = 0;
            });
            return p;
        });
    return {
        all: function() {
            // or _.pairs, anything to turn the object into an array
            return d3.map(_groupAll.value()).entries();
        }
    };
}

What it is doing is reducing all the requested rows to an object, and then turning the object into the array format dc.js expects group.all to return.

You can pass any arbitrary dimension to this constructor - it doesn't matter what it's indexed on because you can't filter on these rows... but you probably want it to have its own dimension so it's affected by all other dimension filters. Also give this constructor an array of columns you want turned into groups, and use the result as your "group".

E.g.

var dim = ndx.dimension(function(r) { return r.a; });
var sidewaysGroup = regroup(dim, ['a', 'b', 'c', 'd']);

Full example here: https://jsfiddle.net/gordonwoodhull/j4nLt5xf/5/

(Notice how clicking on the rows in the chart results in badness, because, what is it supposed to filter?)

Gordon
  • 19,811
  • 4
  • 36
  • 74
  • maybe a better name is `rotate` rather than `regroup` – Gordon Jul 14 '14 at 23:13
  • This worked perfectly for me. Thank you! To prevent filtering I found another solution someone had posted. For your code it would require the addition of sidewaysRow.filter = function() {}. This would prevent that filter "badness" – canyon289 Feb 17 '15 at 17:56
  • Hi Gordon, I need to calculate averages from this functionlity. I normally do this in the value assessor, how would I do it in this case ? Many Thanks – Simon Nov 16 '16 at 08:37
  • I'll try to answer that in http://stackoverflow.com/q/40627538/676195, thanks for asking it as a separate question. – Gordon Nov 17 '16 at 02:34
  • Note also the follow-up to allow filtering on the rows: http://stackoverflow.com/questions/34299017/dc-js-creating-a-row-chart-from-multiple-columns-and-enabling-filtering – Gordon Nov 20 '16 at 19:57
1

Are you looking for stacked row charts? For example, this chart has each row represent a category and each color represents a sub-category:

enter image description here

Unfortunately, this feature is not yet supported at DC.js. The feature request is at https://github.com/dc-js/dc.js/issues/397. If you are willing to wade into some non-library code, you could check out the examples referenced in that issue log.

Alternatively, you could use a stackable bar chart. This link seems to have a good description of how this works: http://www.solinea.com/blog/coloring-dcjs-stacked-bar-charts enter image description here

DJ Martin
  • 2,579
  • 20
  • 24
  • thanks for the quick reply but no im not after stacked im afraid. I'm really just looking at getting a single column to a single row and doing this for 5 columns. So its like setting the dimension across multiple columns. I thought i could maybe hack it to create it but i wouldnt know where to start. I could maybe just create 5 separate row charts for each column and just place them above eachother to make it look like all one chart but then i have to manage the max scale – user3836998 Jul 14 '14 at 13:59
  • I'm having trouble visualizing what you need. Could you provide an example or a mockup image? – DJ Martin Jul 14 '14 at 14:05
  • Perhaps you are looking for a composite chart? See http://stackoverflow.com/questions/21961551/multi-series-bar-chart-in-dc-js – DJ Martin Jul 14 '14 at 14:07
  • i've tried to update it with a bit more info, hopefully it helps. Im not sure if a composite chart works with row charts though – user3836998 Jul 14 '14 at 14:21