【发布时间】:2017-06-17 21:08:40
【问题描述】:
我正在使用 d3.js 通过加载外部 .CSV 文件来绘制图表。 到目前为止,我的代码在少量数据上运行良好,但是当我加载包含数千行的较大文件时,它会杀死页面。
数据有一个使用列,该列是全天每 30 分钟的一个值,将持续数月。
参见Plunker 示例。
var avgClientArr = [];
var dateArr = [];
var dateGroupArr = [];
function csvParseClient() {
d3.xhr('client.csv').get(function(err, response) {
var dirtyCSV = response.responseText;
var initialClientKeys = /TYPE,DATE,START TIME,END TIME,USAGE,UNITS,NOTES/i;
var newClientKeys = "TYPE,x,startTime,endTime,y,UNITS,NOTES";
var csvDataClient = dirtyCSV.replace(initialClientKeys, newClientKeys);
var validData = csvDataClient.substr(csvDataClient.indexOf(newClientKeys));
var csvData = d3.csv.parse(validData);
csvData.customForEach(function(val, i) {
// filter data
//var keep = ['x', 'startTime', 'endTime', 'UNITS', 'y'];
//for (var key in val[i]) {
// if (keep.indexOf(key) === -1) {
// delete val[i][key];
// }
//}
// parse data
var date = val.x;
var usage = val.y;
var startTime = val.startTime;
var endTime = val.endTime;
var x = new Date(date);
var y = parseFloat(usage);
dateArr.push({
"date": x,
"usage": y
})
dateGroupArr = groupBy(dateArr, 'date');
})
console.log(dateGroupArr);
var objDates = objectValues(dateGroupArr);
objDates.customForEach(function(f) {
var avg = f.reduce(function(a, b) {
return a + b.usage;
}, 0) / f.length;
var date = f.reduce(function(a, b) {
return new Date(b.date);
}, 0);
avgClientArr.push({
"x": date,
"y": avg
})
})
//console.log("avgClientArr", avgClientArr);
document.getElementById('arrayDiv').innerHTML = '<pre>' + JSON.stringify(avgClientArr, null, 4) + '</pre>';
})
}
function groupBy(arr, key) {
var reducer = (grouped, item) => {
var group_value = item[key]
if (!grouped[group_value]) {
grouped[group_value] = []
}
grouped[group_value].push(item)
return grouped
}
return arr.reduce(reducer, {})
}
function objectValues(object) {
var values = []
for (var property in object) {
if (object.hasOwnProperty(property)) {
values.push(object[property])
}
}
return values
}
function foreach(fn) {
var arr = this;
var len = arr.length;
for (var i = 0; i < len; ++i) {
fn(arr[i], i);
}
}
Object.defineProperty(Array.prototype, 'customForEach', {
enumerable: false,
value: foreach
});
var t0 = performance.now();
csvParseClient();
var t1 = performance.now();
console.log("Call csvParseClient() " + (t1 - t0) + " milliseconds.");
我需要做什么
我需要返回为y 的全天使用平均值,以及返回为x 的每一天的日期。
我的过程很慢
- 从 CSV 文件中的指定行开始循环,因为前几行有不需要的数据。
- 对唯一日期进行分组并将该日期的每个使用值存储在一个对象中。
- 平均每个日期的使用值。
- 输出一个对象数组,属性
x为日期,y为平均使用值。
如果你能给我任何关于如何让这个运行更快的帮助,那就太好了!
【问题讨论】:
-
在 CSV 文件中放入较少的数据,即在浏览器中处理之前对其进行聚合。
-
papaparse.com 似乎是一个有用的库,它具有流功能。我尝试学习足够的 clojurescript 来解决这个问题,但还没有做到。
标签: javascript arrays csv d3.js