使用d3在d3中绘制成组线。组

2022-03-08 00:00:00 grouping d3.js javascript

我正在使用一个整齐的长数据结构,它有三列:Date、ID、Num_Orders。

date          ID          num_orders
"2018-08-22"  1           3
"2018-08-23"  7           1
"2018-08-23"  10          1
"2018-08-23"  17          1
"2018-08-23"  19          1
.
.
.

我想使用D3.js为每个ID绘制一条线,将date和num_order分别作为x轴和y轴。我使用this作为我正在做的事情的模型,但是在该代码中,作者使用的是nest()函数,该函数在D3的V6中不再使用;现在使用的方法是group()。所以我现在的代码是:

const margin = { top: 10, right: 30, bottom: 30, left: 60 };
const width = 1000 - margin.left - margin.right;
const height = 600 - margin.top - margin.bottom;

const svg = d3.select('#my_dataviz')
    .append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
    .append('g')
        .attr('transform',
                `translate(${margin.left}, ${margin.top})`);
                
d3.json("./data.json")
    .then( function(data) {        
        const grouped_data = d3.group(data, d => d.ID);

        parseDate = d3.timeParse('%Y-%m-%d')
        const xScale = d3.scaleTime()
                        .domain(d3.extent(data, d => parseDate(d.date)))
                        .range([0, width]);
        svg.append('g')
            .attr('transform', `translate(0, ${height})`)
            .call(d3.axisBottom(xScale));
        
        const yScale = d3.scaleLinear()
                        .domain([0, d3.max(data, d => d.num_orders)])
                        .range([height, 0]);
        svg.append('g')
            .call(d3.axisLeft(yScale));

        const myColor = d3.scaleOrdinal()
                            .domain(grouped_data.keys())
                            .range(d3.schemeSet3);
        
        svg.selectAll('.line')
            .data(grouped_data)
            .enter()
            .append('path')
                .attr('fill', 'none')
                .attr('stroke', d => myColor(d.keys))
                .attr('stroke-width', 1.5)
                .attr('d', function(d){
                                return d3.line()
                                    .x(d => xScale(d.date))
                                    .y(d => yScale(d.num_orders))
                                    (d.values);
                });
    } )

到目前为止,我可以显示带有勾号的轴,但是没有显示任何线条,这让我认为问题出在最后的svg.selectAll('.line')语句中。我是D3的新手,所以对这个问题的任何指导都是非常感谢的。(如果您对我的代码有任何总体建议,我也欢迎。)


解决方案

d3.line()仅接受数组,而d.Values()是迭代器。 通过将其转换为数组,问题就解决了。

请注意,我删除了代码片段上的parseDate,因为我将数据生成为日期。 您很可能需要保留parseDate

const margin = { top: 10, right: 30, bottom: 30, left: 60 };
const width = 1000 - margin.left - margin.right;
const height = 600 - margin.top - margin.bottom;

var x = d3.timeDays(new Date(2020, 06, 01), new Date(2020, 10, 30));
var y = Array.from({length: x.length}, Math.random).map(n => Math.floor(n * 10) + 5);
var data = x.map((v, i) => {
  return {
    "date": v,
    "id": Math.floor(Math.random() * (10 + 1)),
    "num_orders": y[i]
  };
});

const svg = d3.select('#my_dataviz')
    .append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
    .append('g')
        .attr('transform',
                `translate(${margin.left}, ${margin.top})`);


const grouped_data = d3.group(data, d => d.id);

parseDate = d3.timeParse('%Y-%m-%d');

const xScale = d3.scaleTime()
                .domain(d3.extent(data, d => d.date))
                .range([0, width]);
svg.append('g')
    .attr('transform', `translate(0, ${height})`)
    .call(d3.axisBottom(xScale));

const yScale = d3.scaleLinear()
                .domain([0, d3.max(data, d => d.num_orders)])
                .range([height, 0]);
svg.append('g')
    .call(d3.axisLeft(yScale));

const myColor = d3.scaleOrdinal()
                    .domain(grouped_data.keys())
                    .range(d3.schemeSet3);

const line = d3.line()
              .x(d => { return xScale(d.date); })
              .y(d => yScale(d.num_orders));

svg.selectAll('.line')
    .data(grouped_data)
    .enter()
    .append('path')
        .attr('fill', 'none')
        .attr('stroke', d => myColor(d[0]))
        .attr('stroke-width', 1.5)
        .attr('d', (d) => line(Array.from(d.values())[1]));
   
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.5.0/d3.min.js"></script>
<div id="my_dataviz"></div>

相关文章