DC.js 动态刷新图表以使用更新后的数据集
DC.js dynamically refresh charts to use updated dataset
我有包含多个数字列的 D3 数据集,我成功地使用它来呈现 DC.js 图表。该图表目前固定为仅使用其中一个数字列。
但是,我希望能够在数字列之间动态切换以将它们交换为 DC.js 图表中的值。
我计划通过使用页面顶部的一组 html 链接和 onclick
事件来创建变量来更改 D3 数据集中选定的列。这工作正常。
但是,我一直在思考如何刷新 DC.js 图表以使用更新后的数据集。
我看过其他类似的问题 and ,但它们对我没有帮助。
这是我的代码:
bucket.getObject({
Bucket: 's3-google-analytics',
Key: 'merged.csv'
},
function awsDataFile(error, data) {
if (error) {
return console.log(error);
}
mergedcsv = d3.csv.parse(data.Body.toString());
var parseDate = d3.time.format("%Y%m%d").parse;
var counter = 0;
var varMetric = 'sessions';
// Note, i can successfully manually change varMetric variable
//to change numeric column is used in chart.
mergedcsv.forEach(function(d) {
d.date = parseDate(d.date);
d.dateString = formatDateYYYYMMDD(d.date);
if (varMetric == 'sessions') {
d.metric = +d.sessions;
} else if (varMetric == 'users') {
d.metric = +d.users;
} else if (varMetric == 'bounceRate') {
d.metric = +d.bounceRate;
} else if (varMetric == 'newUsers') {
d.metric = +d.newUsers;
} else if (varMetric == 'sessionDuration') {
d.metric = +d.sessionDuration;
} else if (varMetric == 'sessionsPerUser') {
d.metric = +d.sessionsPerUser;
} else if (varMetric == 'twitterSessions') {
d.metric = +d.twitterSessions;
}
countLoop = counter++;
});
var ndx = crossfilter(mergedcsv);
// where to put this?
$('#metric a').click(function(e) {
var varMetric = $(e.target).text();
console.log(varMetric);
ndx.remove();
// which to use .. add or crossfilter?
//ndx.add(mergedcsv);
//ndx = crossfilter(mergedcsv);
// which to use .. redrawAll or renderAll?
//dc.redrawAll();
//dc.renderAll();
});
var yyyymmDim = ndx.dimension(function(d) { return d["yyyymm"]; });
var PPCCByYYYYMM = yyyymmDim.group().reduceSum( function(d) { return +d.metric; });
BarChartAlltimeByMonth = dc.barChart("#barchart-alltime-by-month");
BarChartAlltimeByMonth
.height(100)
.width(1000)
.margins({top: 0, right: 10, bottom: 50, left: 35})
.dimension(yyyymmDim)
.group(PPCCByYYYYMM)
dc.renderAll();
//on click put here but doesn't work
$('#metric a').click(function(e) {
var varMetric = $(e.target).text();
console.log('onclick ' + varMetric);
ndx.remove();
ndx.add(mergedcsv);
//dc.redrawAll();
dc.renderAll();
});
});
我将 onclick
处理程序放在脚本底部。
在上面的其他 SO 问题中,这似乎是通过 1) 删除旧数据,2) 添加新数据,以及 3) 重绘所有图表来完成的。
ndx.remove()
会删除数据,但 ndx.add(mergedcsv)
不会添加数据。
dc.redrawAll()
什么都不做,但 dc.renderAll()
确实会导致图表再次呈现,数据没有变化。
这可能既是 DC.js 又是一般 Javascript 问题,因为我对两者都不流利。
是的,你是对的,这些是编程和 JavaScript 问题,与 dc.js 或 d3.js 没有太大关系。
依赖回调的回调
首先,我们研究了将回调(如点击处理程序)放在哪里,这些回调处理由另一个回调(如接收数据处理程序)设置的可视化 and/or 数据。
问题是顶级范围内的数据和图表可能不可用。
最简单的解决方案是将点击处理程序放在数据处理程序中,这样它就可以访问图表和数据。
重用数据转换
您要处理的下一个问题是在何处放置数据转换,以便在绘制图表之前和单击之后调用它。
目前您的点击处理程序没有执行任何操作,因为它将数据替换为...相同的数据。 (悲伤的长号声)
有很多方法可以解决这个问题,但更改当前代码的最简单方法是将数据转换移动到可重用的 函数:
function transform_data(data, varMetric) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.dateString = formatDateYYYYMMDD(d.date);
if (varMetric == 'sessions') {
d.metric = +d.sessions;
} else if (varMetric == 'users') {
d.metric = +d.users;
} else if (varMetric == 'bounceRate') {
d.metric = +d.bounceRate;
} else if (varMetric == 'newUsers') {
d.metric = +d.newUsers;
} else if (varMetric == 'sessionDuration') {
d.metric = +d.sessionDuration;
} else if (varMetric == 'sessionsPerUser') {
d.metric = +d.sessionsPerUser;
} else if (varMetric == 'twitterSessions') {
d.metric = +d.twitterSessions;
}
countLoop = counter++;
});
}
现在这可以在绘制图表之前发生:
function awsDataFile(error, data) {
if (error) {
return console.log(error);
}
mergedcsv = d3.csv.parse(data.Body.toString());
var parseDate = d3.time.format("%Y%m%d").parse;
var counter = 0;
var varMetric = 'sessions';
transform_data(mergedcsv, varMetric);
var ndx = crossfilter(mergedcsv);
// ...
我们可以通过点击重复数据转换:
$('#metric a').click(function(e) {
var varMetric = $(e.target).text();
console.log('onclick ' + varMetric);
transform_data(mergedcsv, varMetric);
ndx.remove();
ndx.add(mergedcsv);
dc.redrawAll();
});
注意:使用 dc.js 时,您肯定希望只在第一次渲染,然后在数据更改时重绘。渲染从头开始,而重绘将执行(通常)漂亮的动画过渡。
我有包含多个数字列的 D3 数据集,我成功地使用它来呈现 DC.js 图表。该图表目前固定为仅使用其中一个数字列。
但是,我希望能够在数字列之间动态切换以将它们交换为 DC.js 图表中的值。
我计划通过使用页面顶部的一组 html 链接和 onclick
事件来创建变量来更改 D3 数据集中选定的列。这工作正常。
但是,我一直在思考如何刷新 DC.js 图表以使用更新后的数据集。
我看过其他类似的问题
这是我的代码:
bucket.getObject({
Bucket: 's3-google-analytics',
Key: 'merged.csv'
},
function awsDataFile(error, data) {
if (error) {
return console.log(error);
}
mergedcsv = d3.csv.parse(data.Body.toString());
var parseDate = d3.time.format("%Y%m%d").parse;
var counter = 0;
var varMetric = 'sessions';
// Note, i can successfully manually change varMetric variable
//to change numeric column is used in chart.
mergedcsv.forEach(function(d) {
d.date = parseDate(d.date);
d.dateString = formatDateYYYYMMDD(d.date);
if (varMetric == 'sessions') {
d.metric = +d.sessions;
} else if (varMetric == 'users') {
d.metric = +d.users;
} else if (varMetric == 'bounceRate') {
d.metric = +d.bounceRate;
} else if (varMetric == 'newUsers') {
d.metric = +d.newUsers;
} else if (varMetric == 'sessionDuration') {
d.metric = +d.sessionDuration;
} else if (varMetric == 'sessionsPerUser') {
d.metric = +d.sessionsPerUser;
} else if (varMetric == 'twitterSessions') {
d.metric = +d.twitterSessions;
}
countLoop = counter++;
});
var ndx = crossfilter(mergedcsv);
// where to put this?
$('#metric a').click(function(e) {
var varMetric = $(e.target).text();
console.log(varMetric);
ndx.remove();
// which to use .. add or crossfilter?
//ndx.add(mergedcsv);
//ndx = crossfilter(mergedcsv);
// which to use .. redrawAll or renderAll?
//dc.redrawAll();
//dc.renderAll();
});
var yyyymmDim = ndx.dimension(function(d) { return d["yyyymm"]; });
var PPCCByYYYYMM = yyyymmDim.group().reduceSum( function(d) { return +d.metric; });
BarChartAlltimeByMonth = dc.barChart("#barchart-alltime-by-month");
BarChartAlltimeByMonth
.height(100)
.width(1000)
.margins({top: 0, right: 10, bottom: 50, left: 35})
.dimension(yyyymmDim)
.group(PPCCByYYYYMM)
dc.renderAll();
//on click put here but doesn't work
$('#metric a').click(function(e) {
var varMetric = $(e.target).text();
console.log('onclick ' + varMetric);
ndx.remove();
ndx.add(mergedcsv);
//dc.redrawAll();
dc.renderAll();
});
});
我将 onclick
处理程序放在脚本底部。
在上面的其他 SO 问题中,这似乎是通过 1) 删除旧数据,2) 添加新数据,以及 3) 重绘所有图表来完成的。
ndx.remove()
会删除数据,但 ndx.add(mergedcsv)
不会添加数据。
dc.redrawAll()
什么都不做,但 dc.renderAll()
确实会导致图表再次呈现,数据没有变化。
这可能既是 DC.js 又是一般 Javascript 问题,因为我对两者都不流利。
是的,你是对的,这些是编程和 JavaScript 问题,与 dc.js 或 d3.js 没有太大关系。
依赖回调的回调
首先,我们研究了将回调(如点击处理程序)放在哪里,这些回调处理由另一个回调(如接收数据处理程序)设置的可视化 and/or 数据。
问题是顶级范围内的数据和图表可能不可用。
最简单的解决方案是将点击处理程序放在数据处理程序中,这样它就可以访问图表和数据。
重用数据转换
您要处理的下一个问题是在何处放置数据转换,以便在绘制图表之前和单击之后调用它。
目前您的点击处理程序没有执行任何操作,因为它将数据替换为...相同的数据。 (悲伤的长号声)
有很多方法可以解决这个问题,但更改当前代码的最简单方法是将数据转换移动到可重用的 函数:
function transform_data(data, varMetric) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.dateString = formatDateYYYYMMDD(d.date);
if (varMetric == 'sessions') {
d.metric = +d.sessions;
} else if (varMetric == 'users') {
d.metric = +d.users;
} else if (varMetric == 'bounceRate') {
d.metric = +d.bounceRate;
} else if (varMetric == 'newUsers') {
d.metric = +d.newUsers;
} else if (varMetric == 'sessionDuration') {
d.metric = +d.sessionDuration;
} else if (varMetric == 'sessionsPerUser') {
d.metric = +d.sessionsPerUser;
} else if (varMetric == 'twitterSessions') {
d.metric = +d.twitterSessions;
}
countLoop = counter++;
});
}
现在这可以在绘制图表之前发生:
function awsDataFile(error, data) {
if (error) {
return console.log(error);
}
mergedcsv = d3.csv.parse(data.Body.toString());
var parseDate = d3.time.format("%Y%m%d").parse;
var counter = 0;
var varMetric = 'sessions';
transform_data(mergedcsv, varMetric);
var ndx = crossfilter(mergedcsv);
// ...
我们可以通过点击重复数据转换:
$('#metric a').click(function(e) {
var varMetric = $(e.target).text();
console.log('onclick ' + varMetric);
transform_data(mergedcsv, varMetric);
ndx.remove();
ndx.add(mergedcsv);
dc.redrawAll();
});
注意:使用 dc.js 时,您肯定希望只在第一次渲染,然后在数据更改时重绘。渲染从头开始,而重绘将执行(通常)漂亮的动画过渡。