简体   繁体   中英

Bar Chart with Counts in dc.js

I am trying to create a bar chart that will display the record counts by identifier and am unable to get it to display properly.

Hoping somebody can look at this and discover where my issue lies.

I am hooking up to a data source that returns an array of objects that appear like this:

[{
    "pollCycleCount": 1,
    "identifier": "21",
    "value": "Value",
    "timestamp": "2015-03-12T18:47:28-05:00",
    "collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573",
    "readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)",
    "name": "name",
    "description": "description"
},
...]

The identifier field will be what I am wanting to count the number of.

Here is the code I have so far:

var dateFormat = d3.time.format.iso;

d3.json("http://url-to-web-service-that-returns-out-data")
.header("Content-Type", "application/json")
.post(JSON.stringify({"apiKey": "private_key", "collection":"D4B5D33B-9151-46BB-AF2A-71FDFEB5E573"}), function(error, data)
{
    if(error)
    {
        console.log(error);
        return;
    }

    console.log(data);

    var xAxisUnits = [""];

    data.forEach(function (d)
    {
        d.timestamp = dateFormat.parse(d.timestamp);
        d.decodedValue = +d.decodedValue;

        if(xAxisUnits.indexOf(d.identifier) == -1 && typeof d.identifier != "undefined")
        {
            xAxisUnits.push(d.identifier);
        }
    });

    console.log(xAxisUnits);

    var ndx = crossfilter(data);

    var idCountDim = ndx.dimension(function(d) { return d.identifier; });
    var idCountGroupCount = idCountDim.group().reduceCount(function(d) { return d.identifier; });

    var barChart = dc.barChart("#barChart");

    barChart.width(480)
        .height(150)
        .margins({top: 10, right: 10, bottom: 20, left: 40})
        .dimension(idCountDim)
        .group(idCountGroupCount)
        .transitionDuration(500)
        .centerBar(true)
        .x(d3.scale.ordinal().domain(xAxisUnits))
        .xUnits(d3.scale.ordinal)
        .elasticY(true)
        .xAxis().tickFormat();

    dc.renderAll();
});

The HTML file body looks like this:

<body>
<script src="./js/crossfilter.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="./js/dc.min.js"></script>
<script src="http://d3js.org/queue.v1.min.js"></script>
<script src="./js/graph.js"></script><!-- Javascript referenced above. -->

<div id="barChart"></div>
</body>

Update here is a sample of the data returned that should show 3 bars that are one tall each.

[{
"pollCycleCount": 1,
"identifier": "21",
"value": "Value",
"timestamp": "2015-03-12T18:47:28-05:00",
"collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573",
"readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)",
"name": "name",
"description": "description"
},
{
"pollCycleCount": 1,
"identifier": "11",
"value": "Value2",
"timestamp": "2015-03-12T18:47:28-05:00",
"collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573",
"readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)",
"name": "name2",
"description": "description"
},
{
"pollCycleCount": 1,
"identifier": "31",
"value": "Value3",
"timestamp": "2015-03-12T18:47:28-05:00",
"collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573",
"readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)",
"name": "name3",
"description": "description"
}]

There's only one thing wrong as far as I can tell, to actually get a chart displayed, although it may not be exactly as you desire.

First up, here's a snippet that works:

 var dateFormat = d3.time.format.iso; var data = [{ "pollCycleCount": 1, "identifier": "21", //"value": "Value", "value": "100", "timestamp": "2015-03-12T18:47:28-05:00", "collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573", "readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)", "name": "name", "description": "description" }, { "pollCycleCount": 1, "identifier": "21", //"value": "Value2", "value": "120", "timestamp": "2015-03-12T18:47:28-05:00", "collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573", "readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)", "name": "name2", "description": "description" }, { "pollCycleCount": 1, "identifier": "11", //"value": "Value2", "value": "100", "timestamp": "2015-03-12T18:47:28-05:00", "collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573", "readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)", "name": "name2", "description": "description" }, { "pollCycleCount": 1, "identifier": "11", //"value": "Value2", "value": "100", "timestamp": "2015-03-12T18:47:28-05:00", "collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573", "readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)", "name": "name2", "description": "description" }, { "pollCycleCount": 1, "identifier": "11", //"value": "Value2", "value": "100", "timestamp": "2015-03-12T18:47:28-05:00", "collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573", "readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)", "name": "name2", "description": "description" }, { "pollCycleCount": 1, "identifier": "31", //"value": "Value3", "value": "100", "timestamp": "2015-03-12T18:47:28-05:00", "collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573", "readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)", "name": "name3", "description": "description" }]; /* d3.json("http://url-to-web-service-that-returns-out-data") .header("Content-Type", "application/json") .post(JSON.stringify({"apiKey": "private_key", "collection":"D4B5D33B-9151-46BB-AF2A-71FDFEB5E573"}), function(error, data) { if(error) { console.log(error); return; } */ console.log(data); var xAxisUnits = [""]; data.forEach(function (d) { d.timestamp = dateFormat.parse(d.timestamp); d.decodedValue = +d.value; if(xAxisUnits.indexOf(d.identifier) == -1 && typeof d.identifier != "undefined") { xAxisUnits.push(d.identifier); } }); console.log(xAxisUnits); var ndx = crossfilter(data); var idCountDim = ndx.dimension(function(d) { return d.identifier; }); var idCountGroupCount = idCountDim.group().reduceCount(function(d) { return d.identifier; }); var barChart = dc.barChart("#barChart"); barChart.width(480) .height(150) .margins({top: 10, right: 10, bottom: 20, left: 40}) .dimension(idCountDim) .group(idCountGroupCount) .transitionDuration(500) .centerBar(true) .x(d3.scale.ordinal().domain(xAxisUnits)) .xUnits(dc.units.ordinal) .elasticY(true) .xAxis().tickFormat(); dc.renderAll(); /* }); */ 
 <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/dc/1.7.0/dc.css" /> <script src="http://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.11/crossfilter.min.js"></script> <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> <script src="http://cdnjs.cloudflare.com/ajax/libs/dc/1.7.0/dc.min.js" charset="utf-8"></script> <script src="http://d3js.org/queue.v1.min.js"></script> <div id="barChart"></div> 

The change is:

Here's another snippet with a further change:

 var dateFormat = d3.time.format.iso; var data = [{ "pollCycleCount": 1, "identifier": "21", //"value": "Value", "value": "100", "timestamp": "2015-03-12T18:47:28-05:00", "collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573", "readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)", "name": "name", "description": "description" }, { "pollCycleCount": 1, "identifier": "21", //"value": "Value2", "value": "120", "timestamp": "2015-03-12T18:47:28-05:00", "collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573", "readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)", "name": "name2", "description": "description" }, { "pollCycleCount": 1, "identifier": "11", //"value": "Value2", "value": "100", "timestamp": "2015-03-12T18:47:28-05:00", "collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573", "readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)", "name": "name2", "description": "description" }, { "pollCycleCount": 1, "identifier": "11", //"value": "Value2", "value": "100", "timestamp": "2015-03-12T18:47:28-05:00", "collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573", "readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)", "name": "name2", "description": "description" }, { "pollCycleCount": 1, "identifier": "11", //"value": "Value2", "value": "100", "timestamp": "2015-03-12T18:47:28-05:00", "collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573", "readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)", "name": "name2", "description": "description" }, { "pollCycleCount": 1, "identifier": "31", //"value": "Value3", "value": "100", "timestamp": "2015-03-12T18:47:28-05:00", "collection": "D4B5D33B-9151-46BB-AF2A-71FDFEB5E573", "readableTimestamp": "Thu Mar 12 2015 23:47:28 GMT+0000 (UTC)", "name": "name3", "description": "description" }]; /* d3.json("http://url-to-web-service-that-returns-out-data") .header("Content-Type", "application/json") .post(JSON.stringify({"apiKey": "private_key", "collection":"D4B5D33B-9151-46BB-AF2A-71FDFEB5E573"}), function(error, data) { if(error) { console.log(error); return; } */ console.log(data); data.forEach(function (d) { d.timestamp = dateFormat.parse(d.timestamp); d.decodedValue = +d.value; }); var ndx = crossfilter(data); var idCountDim = ndx.dimension(function(d) { return d.identifier; }); var idCountGroupCount = idCountDim.group().reduceCount(function(d) { return d.identifier; }); var barChart = dc.barChart("#barChart"); barChart.width(480) .height(150) .margins({top: 10, right: 10, bottom: 20, left: 40}) .dimension(idCountDim) .group(idCountGroupCount) .transitionDuration(500) .centerBar(true) .x(d3.scale.ordinal().domain(d3.set(data.map(function(d) { return d.identifier; })).values())) .xUnits(dc.units.ordinal) .elasticY(true) .xAxis().tickFormat(); dc.renderAll(); /* }); */ 
 <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/dc/1.7.0/dc.css" /> <script src="http://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.11/crossfilter.min.js"></script> <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> <script src="http://cdnjs.cloudflare.com/ajax/libs/dc/1.7.0/dc.min.js" charset="utf-8"></script> <script src="http://d3js.org/queue.v1.min.js"></script> <div id="barChart"></div> 

The change here is:

  • The way you're calculating your xAxisUnits (and therefore your domain) didn't seem right, so I've swapped it out for:

     d3.set(data.map(function(d) { return d.identifier; })).values() 

    That will create an array containing all the unique identifier values.

The reason I didn't think it looked right is because you've got an extra empty value in there (due to initialising the array with "" , which creates an empty string as the first element in the array) and because they weren't sorted. Creating a set from the identifier values takes care of this for you.

This is not necessarily correct for what you need, but it's what makes sense to me for a visualisation.

Note: The value properties in your data are strings, and you're trying to coerce them to integers in your code, this may just be a peculiarity of the sample data you've provided, and in any case, doesn't make any difference in this example.

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