简体   繁体   中英

D3.js Scatterplot with symbols

I am trying to plot 60 points: 30 upward-pointing equilateral triangles and 30 crosses. Each symbol's X and Y coordinates is a random value between 0 and 100 inclusively which should be independently computed.

The size of symbol will be a value between 5 and 50 mapped to the domain of X values to the range of [5,50]. All objects with size greater than the average size of all scatterplot objects should be colored blue and all other objects should be colored green. The plot must have visible X and Y axes that scale according to the generated objects. The ticks on these axes should adjust automatically based on the randomly generated scatterplot objects.

I have updated my code but could not figure out why my symbols are not showing properly.

function getRandomInt(min, max)         {
        return Math.floor(Math.random() * (max - min + 1)) + min;       }
    var data_tri = [], data_crs =[]

    for (var i=0; i<30; i++)
        {
            data_tri.push([getRandomInt(0,100),getRandomInt(0,100)]);
            data_crs.push([getRandomInt(0,100),getRandomInt(0,100)]);
        }


    var margin = {top: 20, right: 15, bottom: 60, left: 60}
      , width = 500 - margin.left - margin.right
      , height = 500 - margin.top - margin.bottom;



    var xScale = d3.scale.linear()
              .domain([0, d3.max(data_tri, function(d) { return d[0]; })])
              .range([ 0, width]);

    var yScale = d3.scale.linear()
              .domain([0, d3.max(data_crs, function(d) { return d[0]; })])
              .range([ height, 0 ]);

    var sizeMax = d3.max([d3.max(data_crs, function(d) { return d[0];}), d3.max(data_tri, function(d) { return d[0];})])

    var sizeScale = d3.scale.linear()
              .domain([0, sizeMax])
              .range([ 5, 50 ]);

    var colorScale = d3.mean([d3.mean(data_crs, function(d) { return d[0];}), d3.mean(data_tri, function(d) { return d[0];})])

    function symbolcolor(x)
    {
        if (x > colorScale){
            return "blue";
        }
        else {
            return "green";
        }
    }

    var chart = d3.select('body')
    .append('svg:svg')
    .attr('width', width + margin.right + margin.left)
    .attr('height', height + margin.top + margin.bottom)
    .attr('class', 'chart')
    .attr('id', 'svg_chart')


    var main = chart.append('g')
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
    .attr('width', width)
    .attr('height', height)
    .attr('class', 'main')   

    var xAxis1 = d3.svg.axis()
    .scale(xScale)
    .orient('bottom');

    main.append('g')
    .attr('transform', 'translate(0,' + height + ')')
    .attr('class', 'main axis date')
    .call(xAxis1);

    var yAxis1 = d3.svg.axis()
    .scale(yScale)
    .orient('left');

    main.append('g')
    .attr('transform', 'translate(0,0)')
    .attr('class', 'main axis date')
    .call(yAxis1);


    var g = main.append("svg:g");

    g.selectAll("path")
            .data(data_tri)
            .enter()
            .append("path")
            .attr("d", d3.svg.symbol('cross').size(function(d){ return sizeScale(d[0]);}))
            .style("fill", function(d){ return symbolcolor(d[0]) ;})
            .attr("transform", function(d) { return "translate("+xScale(d[0])+","+yScale(d[1])+")"; });

    g.selectAll("null")
            .data(data_crs)
            .enter()
            .append("path")
            .attr("d", d3.svg.symbol().type('triangle-up').size(function(d){ return sizeScale(d[0]);}))
            .style("fill", function(d){ return symbolcolor(d[0]) ;})
            .attr("transform", function(d) { return "translate("+xScale(d[0])+","+yScale(d[1])+")"; });

The problem you're having with the path errors is due to the lines like this:

svg.selectAll("path")
  .data(data_tri)
  .enter().append("path")
  .attr("class", "point")
  .attr("d", d3.svg.symbol().type("triangle-up").size(function(d){ return scale(d); }))

You're calculating the size using a function that takes the argument d , which I presume is supposed to be the data from each item in data_tri or data_crs , but d is undefined. I think you wanted to do this:

.attr("d", function(d){
    // d is now each datum
})

However, if you look at each d item, it is an array, so this code:

.size(function(d){ return scale(d); })

will throw an error because the input to scale(x) should not be an array. I can't see where in your datasets you have specified the value that should be scaled, so I can't suggest a fix for that. I'm going to omit that bit completely, and just set the type of shape for each set of points:

svg.selectAll("path")
  .data(data_tri)
  .enter().append("path")
  .attr("class", "point")
  .attr("d", d3.svg.symbol().type("triangle-up")() )
  .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

svg.selectAll("path")
  .data(data_crs)
  .enter().append("path")
  .attr("class", "point")
  .attr("d", d3.svg.symbol().type("cross")() )
  .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

The next problem is that your data items don't have dx and dy , they are two-item arrays, so your transform function is returning translate(undefined, undefined) . Assuming that your arrays are in the form [x, y] , the transform function should be

  .attr("transform", function(d) { return "translate(" + d[0] + "," + d[1] + ")"; });

The last two statements are thus:

svg.selectAll("path")
  .data(data_tri)
  .enter().append("path")
  .attr("class", "point")
  .attr("d", d3.svg.symbol().type("triangle-up")() )
  .attr("transform", function(d) { return "translate(" + d[0] + "," + d[1] + ")"; });

svg.selectAll("path")
  .data(data_crs)
  .enter().append("path")
  .attr("class", "point")
  .attr("d", d3.svg.symbol().type("cross")() )
  .attr("transform", function(d) { return "translate(" + d[0] + "," + d[1] + ")"; });

You should now find that you are getting data points showing up on your chart, and you can start working out how to scale and colour your chart effectively.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM