Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

better scatter plot indexing? #621

Open
gordonwoodhull opened this issue Jun 22, 2014 · 10 comments
Open

better scatter plot indexing? #621

gordonwoodhull opened this issue Jun 22, 2014 · 10 comments

Comments

@gordonwoodhull
Copy link
Contributor

The shrinking of dots when the value goes to zero implemented for #491 points out a possible design flaw in the way the scatterplot is currently implemented.

Indexing by the position is intuitive, and helps slightly with rectangular brushing, but it doesn't allow points to disappear from the set except by the value going to zero. And they must maintain the same order because there is no key function specified for d3.data. Implicitly it gets keyed by the order of the points supplied.

Going forward toward 3.0, I want to consider whether the indexing was better for bubble plots (where you usually explicitly index by order and supply X and Y accessors), or whether a dataKey accessor should be added to the scatter plot interface.

In terms of efficiency, probably neither is very good for crossfilter. There isn't any key you could use that would allow a rectangular range to map to a range of records.

@gordonwoodhull gordonwoodhull added this to the v2.1 milestone Jun 22, 2014
@martingraham
Copy link

Caveat: "it works for me", and only tested on a stand-alone chart, but I've used this key function in the dc source to keep the point mapping in the scatterplot constant between renderings/filterings. This way they transition rather than zip back and forward across the screen.

function keyButIgnoreValue (d) {
    var val = _chart.valueAccessor()(d);
    var dd = d.key.filter (function (part) { return part !== val; });
    return dd.join (":");
}

_chart.plotData = function () {
    var symbols = _chart.chartBodyG().selectAll('path.symbol')
        .data(_chart.data(), keyButIgnoreValue)
    ;

@danielhomola
Copy link

@martingraham , I tried this and although the transitions are now mapping in a constant way across renderings I don't get a smooth transition, but rather my scatter plot freezes, each point appears at its new location (so for a moment I see both the old and new renderings), then the old ones disappear. How did you overcome this? Cheers!

@gordonwoodhull
Copy link
Contributor Author

@martingraham, if you have a unique key in your data, and it is available in the reduced data produced by the group you are using, you should be able to modify keyButIgnoreValue to fetch that. That should cause the dots to move around instead of the insert - then - delete behavior you're seeing.

If this works, we could add an optional feature for this.

@danielhomola
Copy link

I see, so if I modify keyButIgnoreValue to return a valid group object with key attribute, _chart.data can use that directly like
.data(keyButIgnoreValue)
instead of:
.data(_chart.data(), keyButIgnoreValue)

Does it have to be a crossfilter group object? Just asking to find the relevant docs for writing it.. Cheers!

@gordonwoodhull
Copy link
Contributor Author

gordonwoodhull commented Jun 3, 2016

Actually, I just meant, have keyButIgnoreValue return the unique key, and leave the data as it is. I think it should work, haven't actually tested it.

If it sort of works but the transitions are wrong, we can fix that.

@gordonwoodhull
Copy link
Contributor Author

The problem is that this does require the reduced data to have a unique key within its data, and those kinds of complex reductions are hard. (reductio helps.)

@danielhomola
Copy link

Alright, I see. I'm actually having trouble figuring out what exactly keyButIgnoreValue should return. In the example above by @martingraham it simply returns a list of strings, each being the key only, not the value. I made sure that these are absolutely unique, but the insert - then - delete behavior is still persistent. Also, I thought the .data() function (judging from the docs) should accept a single callback function, so I'm not even sure, why would it accept the keyButIgnoreValue function as a 2nd callback..

Could you please explain what's going on here? Thanks so much!

@gordonwoodhull
Copy link
Contributor Author

It depends on your data. You simply want to return a string or integer that is unique for the semantic objects you want to see. Here's a good introduction to joining by key.

So, if you want a dot to move, it should have the same key from one redraw to the next. If you want it to disappear, that key should go away. If you want it to appear, the key should be new.

This information is outside of dc.js and crossfilter, so there's nothing that can be done automatically. Unfortunately, getting crossfilter to pass along this information from your data requires custom reduce magic, but perhaps if you are building a framework you already have that overhead covered.

@danielhomola
Copy link

Got it, this is fantastic. I had to write custom reduce functions to get the color-changing of the scatterplots to work anyway, so I can use one of that custom IDs I added to the value of the reduce function of the scatterplot's group.

I'll post a working example in an hour or so.

Thanks a lot for your help with this!

@gordonwoodhull
Copy link
Contributor Author

Maybe we can do what the dc.leaflet marker chart does, and default location to key but also allow keys that, umm, work better.

intellipharm-pty-ltd/dc-addons#16 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants