D3.js return color () seems random?

So, I'm using D3.js to display information from Facebook, and nodes on the network represent different people in the group. I recently started tackling centralization and wanted some of the nodes to be different in color so they could stand out.

In my JSON file, the nodes are represented like this:

 {"nodes":[{"id":"10066","group":1},{"id":"10072","group":2},{"id":"10075","group":1},{"id":"10077","group":1},{"id":"10093","group":1},{"id":"10114","group":2}],

      

The "group 1" nodes should be blue and the "group 2" nodes should be orange. For most charts this is fine, but for some charts the colors are switched. Is there a way to keep the colors consistent with the group?

Here is the code to create the nodes:

//sets up the nodes
           var node = svg.append("g")
               .attr("class", "nodes")
               .selectAll("circle")
               .data(graph.nodes)
               .enter().append("circle")
                   .attr("r", 10)
                   .attr("fill", function (d) { return color(d.group); })
                   .call(d3.drag()
                       .on("start", dragstarted)
                       .on("drag", dragged)
                       .on("end", dragended));

      

Oh and the color scheme:

var color = d3.scaleOrdinal(d3.schemeCategory10);

      

This is what ALL networks should look like:

This is what ALL networks should look like

But some of them end like this:

NOT what it should look like

If you need all the code or some examples, please follow the link: https://github.com/AnimNations/Biomed-Research-Undergrad

+3


source to share


1 answer


The problem is that you haven't defined the domain of your color scale.

Your ordinal color scale, like any ordinal color scale, will work without specifying a domain (this is clear since your code is not broken). As described in the API , if you didn't set the domain ...

the domain will be implicitly decommissioned by assigning each unique value passed to the scale a new value from the range

However, as you can see, the scale assigns the colors in the first order, first. And why do you sometimes see inverted colors.

Let us show that.

Here's a simple demo. The first 3 laps from group "a", and the last 3 - from group "b":

var svg = d3.select("svg");
var colors = d3.scaleOrdinal(d3.schemeCategory10)
var data = [{
  group: "a"
}, {
  group: "a"
}, {
  group: "a"
}, {
  group: "b"
}, {
  group: "b"
}, {
  group: "b"
}, ]
svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .attr("cy", 50)
  .attr("cx", function(d, i) {
    return 10 + i * 30
  })
  .attr("r", 10)
  .attr("fill", function(d) {
    return colors(d.group)
  });
      

<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
      

Run codeHide result


As you can see, we have "a" circles in blue and "b" circles in orange.



But what happens if the first circle is from group "b"?

var svg = d3.select("svg");
var colors = d3.scaleOrdinal(d3.schemeCategory10)
var data = [{
  group: "b"
}, {
  group: "a"
}, {
  group: "a"
}, {
  group: "b"
}, {
  group: "b"
}, {
  group: "b"
}, ]
svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .attr("cy", 50)
  .attr("cx", function(d, i) {
    return 10 + i * 30
  })
  .attr("r", 10)
  .attr("fill", function(d) {
    return colors(d.group)
  });
      

<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
      

Run codeHide result


As you can see, blue is now assigned to "b" and orange to "a". The colors are reversed.

Solution : specify the domain:

var colors = d3.scaleOrdinal(d3.schemeCategory10)
    .domain(["a", "b"])

      

Now the order of elements in the data no longer matters: "a" will be blue and "b" will be orange, for any dataset.

var svg = d3.select("svg");
var colors = d3.scaleOrdinal(d3.schemeCategory10)
	.domain(["a", "b"])
var data = [{
  group: "b"
}, {
  group: "a"
}, {
  group: "a"
}, {
  group: "b"
}, {
  group: "b"
}, {
  group: "b"
}, ]
svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .attr("cy", 50)
  .attr("cx", function(d, i) {
    return 10 + i * 30
  })
  .attr("r", 10)
  .attr("fill", function(d) {
    return colors(d.group)
  });
      

<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
      

Run codeHide result


+3


source







All Articles