Using the ordinal scale

In some cases, we might need to map our data to some ordinal values, for example, ["a", "b", "c"] or ["#1f77b4", "#ff7f0e", "#2ca02c"]. So, how can we perform this kind of mapping using D3 scales? This recipe is dedicated to address this kind of question.

Getting Ready

Open your local copy of the following file in your web browser:

https://github.com/NickQiZhu/d3-cookbook/blob/master/src/chapter4/ordinal-scale.html

How to do it...

This kind of ordinal mapping is quite common in data visualization. For example, you might want to map certain data points through categorization into some textual value or perhaps into RGB color code, which in turn can be used in CSS styling. D3 offers a specialized scale implementation to handle this kind of mapping. We will explore its usage here. Here is the code of the ordinal.scale.html file:

<div id="alphabet" class="clear">
    <span>Ordinal Scale with Alphabet</span>
    <span>Mapping [1..10] to ["a".."j"]</span>
</div>
<div id="category10" class="clear">
    <span>Ordinal Color Scale Category 10</span>
    <span>Mapping [1..10] to category 10 colors</span>
</div>
<div id="category20" class="clear">
    <span>Ordinal Color Scale Category 20</span>
    <span>Mapping [1..10] to category 20 colors</span>
</div>
<div id="category20b" class="clear">
    <span>Ordinal Color Scale Category 20b</span>
    <span>Mapping [1..10] to category 20b colors</span>
</div>
<div id="category20c" class="clear">
    <span>Ordinal Color Scale Category 20c</span>
    <span>Mapping [1..10] to category 20c colors</span>
</div>

<script type="text/javascript">
    var max = 10, data = [];

    for (var i = 0; i < max; ++i) data.push(i); // <-A
    
    var alphabet = d3.scale.ordinal() // <-B
        .domain(data)
        .range(["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]);
        
    function render(data, scale, selector) { // <-C
        d3.select(selector).selectAll("div.cell")
                  .data(data)
              .enter().append("div").classed("cell", true);

        d3.select(selector).selectAll("div.cell")
                  .data(data)
              .exit().remove();

        d3.select(selector).selectAll("div.cell")
                  .data(data)
              .style("display", "inline-block")
              .style("background-color", function(d){  // <-D
                return scale(d).indexOf("#")>=0?scale(d):"white";
              })
                .text(function (d) { // <-E
                    return scale(d);
                });
    }

    render(data, alphabet, "#alphabet"); // <-F
    render(data, d3.scale.category10(), "#category10");
    render(data, d3.scale.category20(), "#category20");
    render(data, d3.scale.category20b(), "#category20b");
    render(data, d3.scale.category20c(), "#category20c"); // <-G
</script>

The preceding code outputs the following in your browser:

How to do it...

Ordinal scale

How it works...

In the above code example, a simple data array containing integers from 0 to 9 is defined on line A:

for (var i = 0; i < max; ++i) data.push(i); // <-A    
var alphabet = d3.scale.ordinal() // <-B
    .domain(data)
.range(["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]);

Then an ordinal scale was created using the d3.scale.ordinal function on line B. The domain of this scale was set to our integer array data while range is set to a list of alphabets from a to j.

With this scale defined, we can perform the mapping by simply invoking the scale function, for example, alphabet(0) will return a, alphabet(4) will return e, and so on.

On line C, the render function was defined to generate a number of div elements on the page to represent the 10 elements in a data array. Each div has its background-color set to scale function's output or white if the output is not an RGB color string:

.style("background-color", function(d){  // <-D
    return scale(d).indexOf("#")>=0 ? scale(d) : "white";
})

On line E, we also set the text of each cell to display scale function's output:

.text(function (d) { // <-E
    return scale(d);
});

Now, with all the structures in place, from line F to G, the render function was repetitively called with different ordinal scales to produce different visual outputs. On line F, calling render with the alphabet ordinal scale produces the following output:

How it works...

Alphabetic ordinal scale

While on line G, calling the render function with the built-in d3.scale.category20c ordinal color scale produces the following output:

How it works...

Color ordinal scale

Because assigning different colors to different elements in visualization is a common task, for example, assigning different colors in Pie and Bubble charts, D3 provides a number of different built-in ordinal color scales as we have seen in this recipe.

It is quite easy to build your own simple custom ordinal color scale. Just create an ordinal scale with the range set to the colors you want to use, for example:

d3.scale.ordinal()
.range(["#1f77b4", "#ff7f0e", "#2ca02c"]);
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset