I hesitate to post this as I've made no significant progress. I should probably step away for a day. I am attempting to average values by date for use in HighStock charts. The data is in the form of json. The issue arises when I have two sets of data on the same day, I need to average these values based on the date. On a given day there may be 0,1, or 2 values. Days with no values need to be null rather than 0 so there highstock will show the gap. I have been trying to work on a js solution to the problem. Conceptually this seems very easy; group by date, sum and divide by the length. But I have not made good progress. Here is a fiddle without my blunders. Any assistance or nudge in the right direction is appreciated.
因为我没有取得任何重大进展,我对此发表评论犹豫不决。我应该离开一天。我试图按日期平均值在HighStock图表中使用。数据采用json的形式。当我在同一天有两组数据时出现问题,我需要根据日期对这些值进行平均。在给定的一天,可能有0,1或2个值。没有值的天数需要为零而不是0,所以highstock将显示差距。我一直在尝试解决问题的js解决方案。从概念上讲,这似乎很容易;按日期分组,总和除以长度。但我没有取得良好进展。这是一个没有我的错误的小提琴。任何协助或推动正确的方向表示赞赏。
{
"nfdrs": {
"row": [{
"@num": "141",
"sta_id": "350920",
"sta_nm": "HEHE 1",
"latitude": "44.9559",
"longitude": "-121.4991",
"nfdr_dt": "08\/10\/2016",
"nfdr_tm": "13",
"nfdr_type": "O",
"mp": "1",
"msgc": "7C2P2",
"one_hr": "5",
"ten_hr": "6",
"hu_hr": "11",
"th_hr": "10",
"xh_hr": "8",
"ic": "28",
"kbdi": "304",
"sc": "8",
"ec": "14",
"bi": "27",
"sl": "3-",
"lr": "0",
"lo": "0",
"hr": "0",
"ho": "0",
"fl": "19",
"hrb": "60",
"wdy": "78",
"adj": "M"
}, {
"@num": "142",
"sta_id": "352108",
"sta_nm": "WARM SPRINGS BASE",
"latitude": "44.7795",
"longitude": "-121.2501",
"nfdr_dt": "08\/10\/2016",
"nfdr_tm": "13",
"nfdr_type": "O",
"mp": "1",
"msgc": "7A2A2",
"one_hr": "5",
"ten_hr": "6",
"hu_hr": "8",
"th_hr": "8",
"xh_hr": "3",
"ic": "19",
"kbdi": "587",
"sc": "34",
"ec": "2",
"bi": "22",
"sl": "2",
"lr": "0",
"lo": "0",
"hr": "0",
"ho": "0",
"fl": "16",
"hrb": "5",
"wdy": "60",
"adj": "L"
},
And, how to do I control the size of that code sample while including all of the code>
而且,如何控制代码示例的大小,同时包含所有代码>
2 个解决方案
#1
1
I guess your main question is "how do I pro grammatically perform a groupBy on 2 different dataset".
我想你的主要问题是“如何在2个不同的数据集上以编程方式执行groupBy”。
There are many ways you can do this. One way is to use the reduce
function to merge the 2 datasets into one complete one.
有很多方法可以做到这一点。一种方法是使用reduce函数将2个数据集合并为一个完整的数据集。
Example:
例:
function printAverage(data) {
for (var time in data) {
// Do ec
var ec_totalValue = 0;
data[time].ec_values.forEach(value => { ec_totalValue += value; });
var ec_average = ec_totalValue / data[time].ec_values.length;
// do erc
var erc_totalValue = 0;
data[time].erc_values.forEach(value => { erc_totalValue += value; });
var erc_average = erc_totalValue / data[time].erc_values.length;
console.log("Time => " + time + ", average EC => " + ec_average + ", average ERC =>" + erc_average);
}
}
function getEpochTime(dateStr) {
return Date.parse(dateStr);
}
function hasDataForDate(dataset, epochTime) {
return dataset.hasOwnProperty(epochTime);
}
function addValue(dataset, item) {
var epochKey = getEpochTime(item.nfdr_dt);
if (!hasDataForDate(dataset, epochKey)) {
dataset[epochKey] = {};
dataset[epochKey].ec_values = [];
dataset[epochKey].erc_values = [];
}
if (item.ec) dataset[epochKey].ec_values.push(parseInt(item.ec));
if (item.erc) dataset[epochKey].erc_values.push(parseInt(item.erc));
return dataset;
}
function groupRows(data) {
return data.reduce(addValue, {});
}
var data =
{
"nfdrs": {
"row": [
{
"@num": "141",
"sta_id": "350920",
"sta_nm": "HEHE 1",
"latitude": "44.9559",
"longitude": "-121.4991",
"nfdr_dt": "08\/10\/2016",
"nfdr_tm": "13",
"nfdr_type": "O",
"mp": "1",
"msgc": "7C2P2",
"one_hr": "5",
"ten_hr": "6",
"hu_hr": "11",
"th_hr": "10",
"xh_hr": "8",
"ic": "28",
"kbdi": "304",
"sc": "8",
"ec": "14",
"erc": "80",
"bi": "27",
"sl": "3-",
"lr": "0",
"lo": "0",
"hr": "0",
"ho": "0",
"fl": "19",
"hrb": "60",
"wdy": "78",
"adj": "M"
},
{
"@num": "142",
"sta_id": "352108",
"sta_nm": "WARM SPRINGS BASE",
"latitude": "44.7795",
"longitude": "-121.2501",
"nfdr_dt": "08\/10\/2016",
"nfdr_tm": "13",
"nfdr_type": "O",
"mp": "1",
"msgc": "7A2A2",
"one_hr": "5",
"ten_hr": "6",
"hu_hr": "8",
"th_hr": "8",
"xh_hr": "3",
"ic": "19",
"kbdi": "587",
"sc": "34",
"ec": "2",
"erc": "100",
"bi": "22",
"sl": "2",
"lr": "0",
"lo": "0",
"hr": "0",
"ho": "0",
"fl": "16",
"hrb": "5",
"wdy": "60",
"adj": "L"
}]
}
};
var grouped = groupRows(data.nfdrs.row);
printAverage(grouped);
Essentially what the code does is that it loops through the data row and check if the "merged dataset" has already got that key defined.
本质上代码的作用是它遍历数据行并检查“合并数据集”是否已经定义了该键。
If it has then the code simply just pushes the values of that row into the value array. Otherwise it defines a JS {}
object and adds it under that key and then pushes the row value to it.
如果有,则代码只是将该行的值推送到值数组中。否则,它定义一个JS {}对象并将其添加到该键下,然后将行值推送到该对象。
For more example usages of reduce
and what it is.
更多示例使用reduce和它是什么。
See:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
请参阅:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
#2
1
The thing you're looking for can be solved through using objects (or 2 arrays)... Here's the example with objects:
您正在寻找的东西可以通过使用对象(或2个数组)来解决......这是带对象的示例:
$(document).ready(function() {
$("#driver").click(function(event) {
$.getJSON("", function(json) {
// USE objects instead of array
var tempObj = {};
JSONData.nfdrs.row.forEach(function(item) {
var erc = item.ec;
// before adding check if the date value is already present
if(!tempObj.hasOwnProperty(item.nfdr_dt)) {
tempObj[item.nfdr_dt] = parseInt(erc);
}else {
// if present it means that the date has other value.. so concat both the values by a UNIQUE seperator
tempObj[item.nfdr_dt] = tempObj[item.nfdr_dt] +'--'+parseInt(erc);
}
});
// Now proccess the object and wherever we find the string -- we can safely assume that its an extra value
var newObj = {};
Object.keys(tempObj).map(function(key){
if(typeof(tempObj[key])=='string' && tempObj[key].indexOf('--') > -1) { //use the function to convert string with unique seperator to int
newObj[key] = avg(tempObj[key]) ;
}else{
newObj[key] = tempObj[key] ;}
});
$('#stage').html('<p> date: ' + JSON.stringify(newObj) + '</p>');
});
});
});
//function to convert string with ints and unique separator to average of strings
function avg(val) {
var arr = val.split('--');
var sum =arr.reduce(function(p, c) {return parseInt(p) +parseInt( c);});
return sum/arr.length;
}
Working fiddle: https://jsfiddle.net/80Lfqmur/11/
工作小提琴:https://jsfiddle.net/80Lfqmur/11/
#1
1
I guess your main question is "how do I pro grammatically perform a groupBy on 2 different dataset".
我想你的主要问题是“如何在2个不同的数据集上以编程方式执行groupBy”。
There are many ways you can do this. One way is to use the reduce
function to merge the 2 datasets into one complete one.
有很多方法可以做到这一点。一种方法是使用reduce函数将2个数据集合并为一个完整的数据集。
Example:
例:
function printAverage(data) {
for (var time in data) {
// Do ec
var ec_totalValue = 0;
data[time].ec_values.forEach(value => { ec_totalValue += value; });
var ec_average = ec_totalValue / data[time].ec_values.length;
// do erc
var erc_totalValue = 0;
data[time].erc_values.forEach(value => { erc_totalValue += value; });
var erc_average = erc_totalValue / data[time].erc_values.length;
console.log("Time => " + time + ", average EC => " + ec_average + ", average ERC =>" + erc_average);
}
}
function getEpochTime(dateStr) {
return Date.parse(dateStr);
}
function hasDataForDate(dataset, epochTime) {
return dataset.hasOwnProperty(epochTime);
}
function addValue(dataset, item) {
var epochKey = getEpochTime(item.nfdr_dt);
if (!hasDataForDate(dataset, epochKey)) {
dataset[epochKey] = {};
dataset[epochKey].ec_values = [];
dataset[epochKey].erc_values = [];
}
if (item.ec) dataset[epochKey].ec_values.push(parseInt(item.ec));
if (item.erc) dataset[epochKey].erc_values.push(parseInt(item.erc));
return dataset;
}
function groupRows(data) {
return data.reduce(addValue, {});
}
var data =
{
"nfdrs": {
"row": [
{
"@num": "141",
"sta_id": "350920",
"sta_nm": "HEHE 1",
"latitude": "44.9559",
"longitude": "-121.4991",
"nfdr_dt": "08\/10\/2016",
"nfdr_tm": "13",
"nfdr_type": "O",
"mp": "1",
"msgc": "7C2P2",
"one_hr": "5",
"ten_hr": "6",
"hu_hr": "11",
"th_hr": "10",
"xh_hr": "8",
"ic": "28",
"kbdi": "304",
"sc": "8",
"ec": "14",
"erc": "80",
"bi": "27",
"sl": "3-",
"lr": "0",
"lo": "0",
"hr": "0",
"ho": "0",
"fl": "19",
"hrb": "60",
"wdy": "78",
"adj": "M"
},
{
"@num": "142",
"sta_id": "352108",
"sta_nm": "WARM SPRINGS BASE",
"latitude": "44.7795",
"longitude": "-121.2501",
"nfdr_dt": "08\/10\/2016",
"nfdr_tm": "13",
"nfdr_type": "O",
"mp": "1",
"msgc": "7A2A2",
"one_hr": "5",
"ten_hr": "6",
"hu_hr": "8",
"th_hr": "8",
"xh_hr": "3",
"ic": "19",
"kbdi": "587",
"sc": "34",
"ec": "2",
"erc": "100",
"bi": "22",
"sl": "2",
"lr": "0",
"lo": "0",
"hr": "0",
"ho": "0",
"fl": "16",
"hrb": "5",
"wdy": "60",
"adj": "L"
}]
}
};
var grouped = groupRows(data.nfdrs.row);
printAverage(grouped);
Essentially what the code does is that it loops through the data row and check if the "merged dataset" has already got that key defined.
本质上代码的作用是它遍历数据行并检查“合并数据集”是否已经定义了该键。
If it has then the code simply just pushes the values of that row into the value array. Otherwise it defines a JS {}
object and adds it under that key and then pushes the row value to it.
如果有,则代码只是将该行的值推送到值数组中。否则,它定义一个JS {}对象并将其添加到该键下,然后将行值推送到该对象。
For more example usages of reduce
and what it is.
更多示例使用reduce和它是什么。
See:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
请参阅:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
#2
1
The thing you're looking for can be solved through using objects (or 2 arrays)... Here's the example with objects:
您正在寻找的东西可以通过使用对象(或2个数组)来解决......这是带对象的示例:
$(document).ready(function() {
$("#driver").click(function(event) {
$.getJSON("", function(json) {
// USE objects instead of array
var tempObj = {};
JSONData.nfdrs.row.forEach(function(item) {
var erc = item.ec;
// before adding check if the date value is already present
if(!tempObj.hasOwnProperty(item.nfdr_dt)) {
tempObj[item.nfdr_dt] = parseInt(erc);
}else {
// if present it means that the date has other value.. so concat both the values by a UNIQUE seperator
tempObj[item.nfdr_dt] = tempObj[item.nfdr_dt] +'--'+parseInt(erc);
}
});
// Now proccess the object and wherever we find the string -- we can safely assume that its an extra value
var newObj = {};
Object.keys(tempObj).map(function(key){
if(typeof(tempObj[key])=='string' && tempObj[key].indexOf('--') > -1) { //use the function to convert string with unique seperator to int
newObj[key] = avg(tempObj[key]) ;
}else{
newObj[key] = tempObj[key] ;}
});
$('#stage').html('<p> date: ' + JSON.stringify(newObj) + '</p>');
});
});
});
//function to convert string with ints and unique separator to average of strings
function avg(val) {
var arr = val.split('--');
var sum =arr.reduce(function(p, c) {return parseInt(p) +parseInt( c);});
return sum/arr.length;
}
Working fiddle: https://jsfiddle.net/80Lfqmur/11/
工作小提琴:https://jsfiddle.net/80Lfqmur/11/