0

I am trying to rewrite an example provided by d3.js. The original code had a function like this:

function interpolateValues(values, year) {
var i = bisect.left(values, year, 0, values.length - 1),
    a = values[i];
if (i > 0) {
  var b = values[i - 1],
      t = (year - a[0]) / (b[0] - a[0]);
  return a[1] * (1 - t) + b[1] * t;
}
return a[1];
}

where 'values' is an array which looked like this:

"income":[[1800,359.93],[1820,359.93],[1913,556.12],[1950,3363.02], etc.

however, we store data in a different manner. Unlike the "name":[[year,value]],... format, our data is stored in a different manner, much like a Database (sample data to follow):

{"region":"A","income":1178.0,"lifeExpectancy":788.0,"year":1800.0,"population":1292.0,"country":"Angola"},
{"region":"B","income":847.0,"lifeExpectancy":1183.0,"year":1800.0,"population":803.0,"country":"Benin"},
{"region":"A","income":798.0,"lifeExpectancy":765.0,"year":1801.0,"population":967.0,"country":"Angola"},
{"region":"B","income":1293.0,"lifeExpectancy":1497.0,"year":1801.0,"population":792.0,"country":"Benin"},

I am looking to replace the interpolateValues() function with a different one that goes something like this:

SELECT income FROM dataset WHERE year = 1980

I know this is SQL, I'm just using it to try and get the idea across. Basically you have an array with data, an array with years and I am looking for a function that returns data for a specific year.

The interpolation feature would be nice to have, but it isn't too critical, for now. The problem is that I am just learning to use js, and whatever I tried so far, failed bigtime.

Thanks for your help!

Edit: Some extra information for clarification:

I have this function, which works:

function provideData(year) {
return nations.map(function(d) {
  return {
    name: d.country,
    region: d.region,
income: d.income,
    population: d.population,
    lifeExpectancy: d.lifeExpectancy
  };
});
}

But, as you would expect it returns the full arrays resulting in an output of well over a hundred years' data. Now if only there was a way to return d.income if d.year == year..

1
  • 2
    It looks like you not familiar with imperative code paradigm. In JS you don't tell to machine what do you want to get (as in SQL), you tell how to do it instead. So, you need to define new array, run cycle on old array, compare your condition and push to new array entities you want. Interpolation is a different feature I guess. Commented Jul 16, 2013 at 9:13

3 Answers 3

1

If you don't want to use underscore, this should be doable with a for loop.

var plotData = []

for(var i = 0; i < data.length; i++){
    if(data[i].year == targetYear){
        plotData.push(data[i]);
    }
}

I believe that underscore uses a loop as well, so not much of a loss in efficiency. You can improve the efficiency of the for loop if you know that your data is ordered by breaking the for loop once your year exceeds your target year, with something like this:

function getData(data){

    var plotData = []

    for(var i = 0; i < data.length; i++){
        if(data[i].year == targetYear){
            plotData.push(data[i]);
        } else if(data[i].year > targetYear){
            return 0;
        }
    }

    return 0;
}

To use interpolate, you can either build an array inside your for loop that matches the expected array, or call a.year and a.value instead of a[0] and a[1].

Sign up to request clarification or add additional context in comments.

1 Comment

This solutions worked, thank you. Of course, I had to adjust it to the already existing code a bit. But it all worked out in the end. Thank you for all your help.
1

You can try Underscore.js Find and take a look at the answer: Filtering through a multidimensional array using underscore.js

2 Comments

I have tried underscore.js before, but the problem I ran into was setting up the condition for the year array. It is logical, because there is no actual connection between the two arrays at this point, save their ordering.
what is your current issue !
0

You can do it with Alasql JavaScript SQL library.

This is an example:

var data = [ {"region":"A","income":1178.0,"lifeExpectancy":788.0,"year":1800.0,"population":1292.0,"country":"Angola"},
     {"region":"B","income":847.0,"lifeExpectancy":1183.0,"year":1800,"population":803.0,"country":"Benin"},
     {"region":"A","income":798.0,"lifeExpectancy":765.0,"year":1801,"population":967.0,"country":"Angola"},
     {"region":"B","income":1293.0,"lifeExpectancy":1497.0,"year":1801,"population":792.0,"country":"Benin"}];

var res = alasql('SELECT MATRIX year, SUM(income) FROM ? GROUP BY year',[data]);

Try this example in jsFiddle.

Alasql uses standard SQL with some JavaScript extensions, so you can construct any expression

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.