3
\$\begingroup\$

I have data like:

var data = 
    [{
        "date":"1-1-2013",
        "answer":"yes"
    },{
        "date":"1-1-2013",
        "answer":"no"
    },{
        "date":"2-1-2013",
        "answer":"no"
    },{
        "date":"2-1-2013",
        "answer":"no"
    },{
        "date":"2-1-2013",
        "answer":" "       //this is not answered!
    },,{
        "date":"2-1-2013",
        "answer":"no"       
    }];

I need to return[array] percentages of responses for that day(groupedBy) which have a value of “yes” for the “answer”.

For above the result is: [50, 0...]

I have written this below code, it works but i believe it can be simplified a lot.

var freshData =  _.map(data,function(key){
    if (key.answer == "") return false;
    return key;

});

var reducedData = _.filter(freshData, function(n) {
    return n != false;
});

var groups = _.groupBy(reducedData, function(value){
        return value.date + '#' + value.answer;
});

var result = _.map(groups,function(key){
    if (key[0].answer == "") return false;
    return {
        date : key[0].date,
        answer : key[0].answer,
        length :key.length
    };
});

var result2 = _.chunk(result,2);

var result3 =  _.map(result2,function(key){
    return {
        date:key[0].date,
        yes:key[0].length,
        no:key[1].length,
        percentage : (key[1].length/(key[0].length + key[1].length) * 100)
    }
});

var result4 =  _.map(result3,function(key){
return  key.percentage;
});

console.log(result4);

I need to use lodash. Thanks.

\$\endgroup\$
0

4 Answers 4

3
\$\begingroup\$

solution with lodash:

var data = [{
    "date": "1-1-2013",
        "answer": "yes"
}, {
    "date": "1-1-2013",
        "answer": "no"
}, {
    "date": "2-1-2013",
        "answer": "no"
}, {
    "date": "2-1-2013",
        "answer": "no"
}, {
    "date": "2-1-2013",
        "answer": " " //this is not answered!
}, {
    "date": "2-1-2013",
        "answer": "no"
}];

//var grouped = _.groupBy(data, 'date');
var all = _.map(_.groupBy(data, 'date'), function (item, key) {
    console.log(key);
    var size = item.length,
        obj={};
    var positiveCount = _.countBy(item, function (i) {
        return i.answer == "yes" ? "yes" : "no";
    });
    var percentagePossitive = (positiveCount.yes / size) * 100;
    obj[key] = percentagePossitive || 0;
    return obj;
});

console.log(all)
\$\endgroup\$
5
\$\begingroup\$

Create a lodash chain, use _.groupBy() to get a dates map, and then reduce it to percentages:

function getNumOfYes(data) {
  return _(data).groupBy('date').reduce(function(percentage, answers) {
    var numOfYes = _.countBy(answers, 'answer').yes || 0;
    percentage.push(numOfYes / answers.length * 100);
    return percentage;
  }, []);
}

var data = [{
  "date": "1-1-2013",
  "answer": "yes"
}, {
  "date": "1-1-2013",
  "answer": "no"
}, {
  "date": "2-1-2013",
  "answer": "no"
}, {
  "date": "2-1-2013",
  "answer": "no"
}, {
  "date": "2-1-2013",
  "answer": " " //this is not answered!
}, , {
  "date": "2-1-2013",
  "answer": "no"
}];

var numOfYes = getNumOfYes(data);

console.log(numOfYes);

document.getElementById('results').innerText = JSON.stringify(numOfYes);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>

<pre id="results"></pre>

\$\endgroup\$
3
\$\begingroup\$

You can utilize a temporary object for counting and returns an array of objects with date and percentage.

var data = [{
        "date": "1-1-2013",
        "answer": "yes"
    }, {
        "date": "1-1-2013",
        "answer": "no"
    }, {
        "date": "2-1-2013",
        "answer": "no"
    }, {
        "date": "2-1-2013",
        "answer": "no"
    }, {
        "date": "2-1-2013",
        "answer": " "       //this is not answered!
    }, , {
        "date": "2-1-2013",
        "answer": "no"
    }];

function getPercentage(data) {
    var obj = {};
    data.forEach(function (a) {
        if (~['yes','no'].indexOf(a.answer)) {                
            obj[a.date] = obj[a.date] || { yes: 0, no: 0 };
            obj[a.date][a.answer]++;
        }
    });
    return Object.keys(obj).map(function (k) {
        return { 
            date: k,
            percent: obj[k].yes * 100 / (obj[k].yes + obj[k].no)
        };
    });
}
document.write('<pre>' + JSON.stringify(getPercentage(data), 0, 4) + '</pre>');

\$\endgroup\$
3
\$\begingroup\$

Answer in JS fiddle (check console)

Note, I've used Lodash, but you don't really need it to this :-)

var sortedResults = {}; // create empty object

/**
 * sort all the answers on date
 */
_.map(data, function(val){
    if(typeof val !== 'undefined'){ // check if not undefined
        if(val.answer==='yes' || val.answer==='no'){ // should be yes or no
            if (typeof(sortedResults[val.date]) === 'undefined') {
                sortedResults[val.date] = []; // if data is not available, add it as an array
            }
            sortedResults[val.date].push(val.answer); // push the answer to the array
        }
    }
});

/**
 * Calculate the percentages of 'yes'
 */
_.map(sortedResults, function(val, key){
    var percentage    = val.length, // get total length
        percentageYes = 0; // before map function percentage = 0
    _.each(val, function(singleVal){
        if(singleVal === 'yes'){ percentageYes++; }
    });
    sortedResults[key] = { yesPercent: percentageYes / percentage * 100 };
});

/**
 * Percentage is available in sortedResults;
 */
console.log(sortedResults);
\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.