使用 dc.js 生成的图表比例返回 NaN
Scale of chart generated by using dc.js is returning NaN
我对 DC/D3 图书馆还很陌生。我试图通过一个单独的纯 JS 文件将 DC 与 ReactJS 结合起来,该文件是一个可重用的 D3 组件。我在这里关注 example。这是我正在使用的虚拟数据:
json snippet.
这是我的 App.js:
state = {
data: null,
};
componentDidMount() {
console.log("componentDidMount");
d3.json("dummy_data.json").then(data => {
this.setState({data: data});
console.log("Data is updated!");
})
this.createVisualization();
}
componentDidUpdate() {
console.log("componentDidUpdate");
this.updateVisualization();
}
createVisualization = () => {
console.log("createVisualization");
this.visualization = new Dashboard({
parentElement: d3.select(this.node)
});
}
updateVisualization = () => {
this.visualization.updateVis(this.state.data);
console.log("updateVisualization finished");
}
render() {
return (
<div style={{width: '100vw'}} id="app"
ref={node => this.node = node}>
<h1>Hello World!!!</h1>
</div>
)
}
这是我用于 generate/render 图表的 JS 文件 (dashboard.js):
export default class Dashboard {
constructor(_config) {
// setting up based on input config
this.parentElement = _config.parentElement;
this.initVis();
}
initVis() {
let vis = this;
vis.chartContainer = vis
.parentElement
.append("div")
.attr("id", "chart-container")
.style("width", "100%");
vis.chart = new dc.ScatterPlot("#chart-container");
vis
.chart
.width(768)
.height(480)
.margins({top: 0, right: 10, bottom: 20, left: 50})
.x(d3.scaleLinear())
.elasticX(true)
.elasticY(true)
.brushOn(false) // turn off brush-based range filter
.symbolSize(8) // set dot radius
.clipPadding(10);
const f = vis.chart.x();
console.log(f.domain());
console.log("Finish initVis")
}
updateVis(newData) {
let vis = this;
vis.cf = crossfilter(newData);
console.log(newData);
vis.chart
.on('pretransition', () => {
// console.log(vis)
// const xext = d3.extent(vis.chart.group().all(), d => d.key);
// console.log(newData.map(d => [+d.age, +d.readmission_risk]));
const r = regression.linear(newData.map(d => [d.age, d.readmission_risk]));
const m = r.equation[0],
b = r.equation[1];
const [x1, x2] = vis.chart.x().domain();
const points = [
[
x1, m * x1 + b
],
[
x2, m * x2 + b
]
];
const xScale = vis.chart.x();
const yScale = vis.chart.y();
const margins = vis.chart.margins();
console.log(xScale(20));
var line = vis.chart.g().selectAll('line.regression').data([points]);
// console.log(vis.chart.x().domain());
function do_points(line) {
line
.attr('x1', d => xScale(d[0][0]) + margins.left)
.attr('y1', d => yScale(d[0][1]) + margins.top)
.attr('x2', d => xScale(d[1][0]) + margins.left)
.attr('y2', d => yScale(d[1][1]) + margins.top);
}
line = line.enter().append('line')
.attr('class', 'regression')
.call(do_points)
.merge(line);
line.transition().duration(vis.chart.transitionDuration()).call(do_points);
})
vis.renderVis();
}
renderVis() {
let vis = this;
const ageDimension = vis.cf.dimension(d => d.age);
const ageGroup = ageDimension.group();
vis.chart.dimension(ageDimension).group(ageGroup);
vis.chart.render();
console.log("rendering");
}
我确定问题出在updateVis
方法的回调函数中的xScale
。它正在 returning NaN
。但我试图在 initVis
中调用 xScale
,比例函数似乎工作正常并且 return [0,1]
。我为此苦苦挣扎了很长时间。任何帮助将不胜感激!
更新:
这是我收到的错误消息的快照:
感谢您提供可重现的示例。在没有 运行 的情况下,仅仅盯着它调试 D3 和 dc.js 代码真的很难。
这里的问题是散点图期望组键是一个双元素数字数组,而不仅仅是一个数字。您可以看到 key_function()
,在您开始的回归示例中,returns 一个返回此类键的函数。
相应地更改尺寸:
const ageDimension = vis.cf.dimension(d => [d.age, d.readmission_risk] );
导致图表出现。
我还必须添加示例中的 CSS 才能显示回归线;我创建了 dashboard.css
:
line.regression {
stroke: red;
stroke-width: 5;
opacity: 0.5;
}
并将其添加到 dashboard.js
:
import './dashboard.css';
结果:
顺便说一句,您计算回归线的方式在过滤数据时不会更新。如果您希望它这样做,这应该可行:
const r = regression.linear(vis.chart.group().all().filter(kv => kv.value).map(kv => [kv.key[0], kv.key[1]]));
这使用图表组中的键,但仅使用“在”中过滤的键(值 > 0)。
我对 DC/D3 图书馆还很陌生。我试图通过一个单独的纯 JS 文件将 DC 与 ReactJS 结合起来,该文件是一个可重用的 D3 组件。我在这里关注 example。这是我正在使用的虚拟数据: json snippet.
这是我的 App.js:
state = {
data: null,
};
componentDidMount() {
console.log("componentDidMount");
d3.json("dummy_data.json").then(data => {
this.setState({data: data});
console.log("Data is updated!");
})
this.createVisualization();
}
componentDidUpdate() {
console.log("componentDidUpdate");
this.updateVisualization();
}
createVisualization = () => {
console.log("createVisualization");
this.visualization = new Dashboard({
parentElement: d3.select(this.node)
});
}
updateVisualization = () => {
this.visualization.updateVis(this.state.data);
console.log("updateVisualization finished");
}
render() {
return (
<div style={{width: '100vw'}} id="app"
ref={node => this.node = node}>
<h1>Hello World!!!</h1>
</div>
)
}
这是我用于 generate/render 图表的 JS 文件 (dashboard.js):
export default class Dashboard {
constructor(_config) {
// setting up based on input config
this.parentElement = _config.parentElement;
this.initVis();
}
initVis() {
let vis = this;
vis.chartContainer = vis
.parentElement
.append("div")
.attr("id", "chart-container")
.style("width", "100%");
vis.chart = new dc.ScatterPlot("#chart-container");
vis
.chart
.width(768)
.height(480)
.margins({top: 0, right: 10, bottom: 20, left: 50})
.x(d3.scaleLinear())
.elasticX(true)
.elasticY(true)
.brushOn(false) // turn off brush-based range filter
.symbolSize(8) // set dot radius
.clipPadding(10);
const f = vis.chart.x();
console.log(f.domain());
console.log("Finish initVis")
}
updateVis(newData) {
let vis = this;
vis.cf = crossfilter(newData);
console.log(newData);
vis.chart
.on('pretransition', () => {
// console.log(vis)
// const xext = d3.extent(vis.chart.group().all(), d => d.key);
// console.log(newData.map(d => [+d.age, +d.readmission_risk]));
const r = regression.linear(newData.map(d => [d.age, d.readmission_risk]));
const m = r.equation[0],
b = r.equation[1];
const [x1, x2] = vis.chart.x().domain();
const points = [
[
x1, m * x1 + b
],
[
x2, m * x2 + b
]
];
const xScale = vis.chart.x();
const yScale = vis.chart.y();
const margins = vis.chart.margins();
console.log(xScale(20));
var line = vis.chart.g().selectAll('line.regression').data([points]);
// console.log(vis.chart.x().domain());
function do_points(line) {
line
.attr('x1', d => xScale(d[0][0]) + margins.left)
.attr('y1', d => yScale(d[0][1]) + margins.top)
.attr('x2', d => xScale(d[1][0]) + margins.left)
.attr('y2', d => yScale(d[1][1]) + margins.top);
}
line = line.enter().append('line')
.attr('class', 'regression')
.call(do_points)
.merge(line);
line.transition().duration(vis.chart.transitionDuration()).call(do_points);
})
vis.renderVis();
}
renderVis() {
let vis = this;
const ageDimension = vis.cf.dimension(d => d.age);
const ageGroup = ageDimension.group();
vis.chart.dimension(ageDimension).group(ageGroup);
vis.chart.render();
console.log("rendering");
}
我确定问题出在updateVis
方法的回调函数中的xScale
。它正在 returning NaN
。但我试图在 initVis
中调用 xScale
,比例函数似乎工作正常并且 return [0,1]
。我为此苦苦挣扎了很长时间。任何帮助将不胜感激!
更新:
这是我收到的错误消息的快照:
感谢您提供可重现的示例。在没有 运行 的情况下,仅仅盯着它调试 D3 和 dc.js 代码真的很难。
这里的问题是散点图期望组键是一个双元素数字数组,而不仅仅是一个数字。您可以看到 key_function()
,在您开始的回归示例中,returns 一个返回此类键的函数。
相应地更改尺寸:
const ageDimension = vis.cf.dimension(d => [d.age, d.readmission_risk] );
导致图表出现。
我还必须添加示例中的 CSS 才能显示回归线;我创建了 dashboard.css
:
line.regression {
stroke: red;
stroke-width: 5;
opacity: 0.5;
}
并将其添加到 dashboard.js
:
import './dashboard.css';
结果:
顺便说一句,您计算回归线的方式在过滤数据时不会更新。如果您希望它这样做,这应该可行:
const r = regression.linear(vis.chart.group().all().filter(kv => kv.value).map(kv => [kv.key[0], kv.key[1]]));
这使用图表组中的键,但仅使用“在”中过滤的键(值 > 0)。