0

I have n columns of data that I would like to make D3 scatter plots from. It takes 2 columns to make a plot so n columns would end up n-permutations of 2 times of the same code that I would like to make a plot function from. Problem is I don't know how to set the variable in D3 fashion. An example of data and the snippet of code are bellow. I appreciate for any hint. Thanks.

// Potentially, there are a lot more columns.
var data = [ 
    {"col1": 34, "col2": 54, "col3": 345, "col4": 35, "col5": 52},
    {"col1": 75, "col2": 98, "col3": 917, "col4": 03, "col5": 47},
    {"col1": 63, "col2": 23, "col3": 236, "col4": 34, "col5": 78},
    {"col1": 23, "col2": 38, "col3": 198, "col4": 12, "col5": 18},
    {"col1": 57, "col2": 48, "col3": 274, "col4": 67, "col5": 39},
    {"col1": 65, "col2": 12, "col3": 381, "col4": 27, "col5": 45}
]; 

// The code is long
// I just list here the parts that are involved
// How to replace FOO and BAR with a pair of parameters "col1", "col2", etc ...
var x = d3.scale.linear().range([0, width]),
    y = d3.scale.linear().range([height, 0]);
x.domain(d3.extent(data, function(q) {return q.FOO;}));
y.domain(d3.extent(data, function(q) {return q.BAR;}));

svg.selectAll("circle")
    .data(data)
    .enter().append("circle")
        .attr("r", 4)
        .attr("cx", function(d) {return x(d.FOO);})
        .attr("cy", function(d) {return y(d.BAR);})
        .style('fill', 'blue');

EDIT: I took a hint from mgold and make a function to rebuild the original dataset to a 2 columns dataset instead of a function of drawing scatter plot. It may not be elegant but just works. :) Thanks!

function get2Columns(foo, bar) {
    var tempArr = [];
    for (var i = 0; i < data.length; i++) {
        tempArr.push({"FOO":data[i][foo],"BAR":data[i][bar]});
    }
    return tempArr; 
}
data = get2Columns('col1', 'col2');
ngungo
  • 4,892
  • 4
  • 29
  • 36

1 Answers1

1

I'm not sure exactly what you're looking for, but I can try to talk about things that I think are relevant and hopefully give you some leads.

I would represent your data as an array of arrays, rather than an array of objects. This makes it much more amenable to array methods, from both vanilla JavaScript and D3. The transpose method may be especially useful, coupled with some mapping and reducing, for finding extents.

There are a handful of ways to choose two elements from an array or similar data structure. Zipping takes a pair of arrays and returns an array of pairs: the 0th items together, the 1st items together, and so on. Pairing takes one array and returns sequential pairs. Both of these have D3 implementations among those array methods.

Closer to what you want (maybe?) is the product of arrays, which given n arrays is every way to pick 1 item from each. This is typically represented as an array of arrays where the inner arrays have length n. There doesn't seem to be a D3 function to do this (I'd support adding one) but you can see this SO post. (No luck with Underscore either.)

But since you already have your matrix, maybe all you need to know is that functions like attr pass their second argument (when a function) not just the datum d but also the index i. You can also try using each and/or forEach to go from an array of values to individual values, keeping the indices distinct to get your 2D coordinate.

(On reread, the last paragraph is likely to be the most helpful.)

Community
  • 1
  • 1
mgold
  • 6,189
  • 4
  • 39
  • 41