微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 dc.js 生成的图表比例返回 NaN

如何解决使用 dc.js 生成的图表比例返回 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>
        )
    }

这是我用来生成/渲染图表的 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");
    }

我已经确定问题是 xScale 方法中回调函数中的 updateVis。它正在返回 NaN。但是我尝试在 xScale调用 initVis 缩放函数似乎工作正常并返回 [0,1]。为此,我已经挣扎了很长时间。任何帮助将不胜感激!

更新: 这是我收到的错误消息的快照:

enter image description here

解决方法

感谢您提供可重现的示例。 D3 和​​ dc.js 代码只是盯着它而不运行它真的很难调试。

这里的问题是散点图期望组键是一个由两个元素组成的数字数组,而不仅仅是一个数字。您可以看到,在您开始的回归示例中,std::optional::emplace 返回一个返回此类键的函数。

相应地更改您的维度:

key_function()

导致图表出现。

我还必须添加示例中的 CSS 才能显示回归线;我创建了 const ageDimension = vis.cf.dimension(d => [d.age,d.readmission_risk] );

dashboard.css

并将其添加到 line.regression { stroke: red; stroke-width: 5; opacity: 0.5; }

dashboard.js

结果:

scatterplot with regression line

顺便说一句,您计算回归线的方式,在过滤数据时不会更新。如果您希望这样做,这应该可以工作:

import './dashboard.css';

这使用图表组中的键,但仅使用“输入”(值 > 0)过滤的键。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。