dc.js - rowChart - removing elements after filter

4,322 views
Skip to first unread message

Chris Malek

unread,
Jul 25, 2013, 6:57:33 PM7/25/13
to dc-js-us...@googlegroups.com

I have a simple rowChart built with dc.js. When another chart gets filtered, the row chart will show all the category rows.  Is there an easy way to filter out these zero rows and not show that category/row? On the charts I am working on now, I just want to only show the rows that have a non-zero count. 

I don't see an obvious way looking at the dc.js api nor do I see this done on any of the various sample sites. I may just need  a cup of coffee.  

This screenshot will hopefully help.



 

Nick Zhu

unread,
Jul 26, 2013, 10:28:35 AM7/26/13
to Chris Malek, dc-js-us...@googlegroups.com
Currently the row chart does not remove the row when its value is 0. You can achieve this by either having your own custom reduce function to remove group when they have zero value in crossfilter or use a different chart that does not visualize zero value groups e.g. bubble chart perhaps

david....@cantab.net

unread,
Sep 2, 2013, 5:05:58 AM9/2/13
to dc-js-us...@googlegroups.com, Chris Malek
What exactly would you need to put in the reduce function in order to remove the group? I presume you'd need to use group.dispose(), but in this case, what syntax do you use to refer to the group that you want to remove?

Thanks for your help - it's very much appreciated.

Cheers,

Dave

Nick Zhu

unread,
Sep 2, 2013, 10:20:12 AM9/2/13
to david....@cantab.net, dc-js-us...@googlegroups.com, Chris Malek
I believe what Chris meant was removing the rows (svg:rect) not the group themselves. To remove the rows basically you need to use a renderlet to remove the elements and also shift row below up to fill the space or move them down depends on your visualization design.

Jacob Rideout

unread,
Sep 3, 2013, 2:22:10 PM9/3/13
to dc-js-us...@googlegroups.com, david....@cantab.net, Chris Malek
In my data table fork, I include a keep callback, under the presumption that the data is sorted. So you can sort numerically, then keep all values >0 for example. I'd like to think of a way to generalize the approach.

Dongyun Shin

unread,
Sep 23, 2013, 10:59:58 PM9/23/13
to dc-js-us...@googlegroups.com, david....@cantab.net, Chris Malek
I think it is very useful feature which removes some groups whose value is below a criteria such as 0 or some value.
It prevent people from being embarrassed  with large dataset which has zero value.

Is it still under developing?


2013년 9월 4일 수요일 오전 3시 22분 10초 UTC+9, Jacob Rideout 님의 말:

Nick Zhu

unread,
Sep 24, 2013, 12:02:43 PM9/24/13
to Dongyun Shin, dc-js-us...@googlegroups.com, david....@cantab.net, Chris Malek
My original thinking was to introduce a concept called "drivers". Drivers can be used to hook back-end data analysis framework (crossfilter/mongo db) into dc.js library, and they can also be used to filter group and dimensions as what is needed in this case. However never got around to implement them; hopefully in the future I or other contributor will have some extra bandwidth to introduce this flexibility.

NK

unread,
Nov 5, 2013, 6:48:47 PM11/5/13
to dc-js-us...@googlegroups.com
Hey there, I'm coming across a similar problem, except that I'm attempting to remove a group from the data table instead of rowChart. I ended up grouping 0 values into an 'undefined' group, which is the one that i'm trying to hide from rendering on the dataTable. Would this be as simple as specifying what groups to return if they fulfill a certain value within renderlet? Or would this have to be done in the source code as Jacob mentioned with a .keep added in there? 

Any input would be appreciated. Thanks.

-N

Nick Zhu

unread,
Nov 6, 2013, 2:26:24 PM11/6/13
to NK, dc-js-us...@googlegroups.com
You can try the following solution leveraging the new data function introduced on master:

               .data(function (g) {
                    return _.select(g.all(), function (e) {
                        return e.key != 'others';
                    });
                })

In this case I removed the group with key == 'others' obvious you can put any kind of filtering logic here for example e.value > 0.

PS: you need to get the bleeding-edge dc.js build on master for this to work.


Nick

Nadia Kiamilev

unread,
Nov 6, 2013, 5:01:18 PM11/6/13
to Nick Zhu, dc-js-us...@googlegroups.com
Ah, thanks for the feedback. Any suggestions on how to filter out this specific group within the stable released version though, instead of utilizing the bleeding-edge version?

-N

Nick Zhu

unread,
Nov 6, 2013, 9:09:20 PM11/6/13
to Nadia Kiamilev, dc-js-us...@googlegroups.com
Hmm.. dont think there is a easy to do it pre-v2.0. This is partly the reason why data function was introduced in v2.

Gordon Woodhull

unread,
Nov 6, 2013, 9:37:17 PM11/6/13
to Nick Zhu, Nadia Kiamilev, dc-js-us...@googlegroups.com
I think you may be able to create a "fake group" like
var group2 = {all: function() { return group1.all().filter( ... ); }

Definitely a hack though.

Dirk Gorissen

unread,
Jun 23, 2014, 6:40:09 AM6/23/14
to dc-js-us...@googlegroups.com, nick....@gmail.com, nadia.k...@gmail.com
Hello,

Trying to do the same here but not getting it working. Assuming the correct way to do this is in the preRedraw() handler as follows:

            statusPerWardChart\
                    .width(w)
                    .height(h)
                    .margins({top: 20, left: 40, right: 10, bottom: 60})
                    .group(statusPerWard,"Functional")
                    .dimension(wards)
                    .ordering((d) -> -d.value.functional / d.value.count)
                    .valueAccessor((p) -> p.value.functional)
                    .stack(statusPerWard, "Needs Repair", (d) -> d.value["needs repair"])
                    .stack(statusPerWard, "Not Functional", (d) -> d.value["not functional"])
                    .x(d3.scale.ordinal())
                    .xUnits(dc.units.ordinal)
                    .elasticY(true)
                    .elasticX(true)
                    .renderlet((chart) ->
                                chart.selectAll("g.x text")
                                .attr('dx', '-30')
                                .attr('transform', "rotate(-65)"))
                    .label((d) -> d.key)
                    .title((d) ->
                        d.key +
                         "\nFunctional: " + d.value.functional +
                         "\nNot functional: " + d.value["needs repair"])
                    .legend(dc.legend().x(w-100).y(10))
                    .on("preRedraw", (chart) ->
                        group = chart.group()
                        group2 = {
                            all: () ->
                                group.all().filter((d) -> d.value.count > 0)
                        }
                        chart.group(group2))
                    .on("preRender", (chart) ->
                        chart.rescale())

Before:

After:

Verifying group2 in the console shows it should be fine. However it seems only one stack layer is filtered? Whats going on?
Using current master.

Cheers
Dirk

Enis Pilavdzic

unread,
Aug 12, 2014, 6:40:30 PM8/12/14
to dc-js-us...@googlegroups.com, nadia.k...@gmail.com
I have dc.js 2.0.0-alpha.2 but dc.rowChart().data is still undefined, that seems to be the latest as of 12 days ago is there a later version somewhere?

I also need to filter out dimensions that have a groupAll().reduceCount().value() of zero. 

Anyone have a simple solution for this working?

Gordon Woodhull

unread,
Aug 12, 2014, 7:48:17 PM8/12/14
to Enis Pilavdzic, dc-js-us...@googlegroups.com, nadia.k...@gmail.com
.data() is on the base mixin


It interacts poorly with the cap mixin, however (disables capping iirc), so maybe better to use the "fake group" trick for now

Blair Nilsson

unread,
Aug 13, 2014, 12:46:31 AM8/13/14
to dc-js-us...@googlegroups.com
I thought I just answered this in another thread :)

Using the othersGrouper should work well... I've just finished testing it myself - so I know it works.

   chart.othersGrouper(
      function(data) {
        results = []
        for (i in data) {
          if (data[i].value != 0 ) {
            results.push(data[i]);
          }
        }
        return results;
      }
   )

It takes the data just before it is displayed (I think...) so it seems like a nicer place to muck around with it.

Wladimir Coka

unread,
Aug 26, 2014, 2:01:56 AM8/26/14
to dc-js-us...@googlegroups.com
I submit a PR https://github.com/dc-js/dc.js/pull/683 to be able to myRowChart.ignoreZeroValue(true) and prevent having this empty elements.
Reply all
Reply to author
Forward
0 new messages