Simon GIS
Simon GIS

Reputation: 1055

Stacked Bar Chart: By Type and Quantity

With Dc.Js and crossfilter, I want to create a Stacked bar chart.

Basicaly, I have two variables:

type : 2018, Never Covered, Other Periods

district : Thu Duc, etc....

In my StackedBarChart, I want to see for each district the quantity of .

Ive tried using this code:

var paymentsRecord = [{
    date: "2011-11-14T16:17:54Z",
    quantity: 2,
    total: 190,
    tip: 100,
    type: "tab"
  },
  {
    date: "2011-11-14T16:20:19Z",
    quantity: 2,
    total: 190,
    tip: 100,
    type: "tab"
  },
  {
    date: "2011-11-14T16:28:54Z",
    quantity: 1,
    total: 300,
    tip: 200,
    type: "visa"
  },
  {
    date: "2011-11-14T16:30:43Z",
    quantity: 2,
    total: 90,
    tip: 0,
    type: "tab"
  },
  {
    date: "2011-11-14T16:48:46Z",
    quantity: 2,
    total: 90,
    tip: 0,
    type: "tab"
  },
  {
    date: "2011-11-14T16:53:41Z",
    quantity: 3,
    total: 90,
    tip: 0,
    type: "tab"
  },
  {
    date: "2011-11-14T16:54:06Z",
    quantity: 1,
    total: 100,
    tip: 0,
    type: "cash"
  },
  {
    date: "2011-11-14T16:58:03Z",
    quantity: 2,
    total: 90,
    tip: 0,
    type: "tab"
  },
  {
    date: "2011-11-14T17:07:21Z",
    quantity: 2,
    total: 90,
    tip: 0,
    type: "tab"
  },
  {
    date: "2011-11-14T17:22:59Z",
    quantity: 2,
    total: 90,
    tip: 0,
    type: "tab"
  },
  {
    date: "2011-11-14T17:25:45Z",
    quantity: 2,
    total: 200,
    tip: 0,
    type: "cash"
  },
  {
    date: "2011-11-14T17:29:52Z",
    quantity: 1,
    total: 200,
    tip: 100,
    type: "visa"
  }
];

var facts = crossfilter(paymentsRecord);
var dimensionByType = facts.dimension(function(d) {
  return d.type;
});
var groupByType = dimensionByType.group().reduce(reduceAdd, reduceRemove, reduceInitial);


function reduceAdd(p, v) {
  p[v.quantity] = (p[v.quantity] || 0) + v.total;
  return p;
}

function reduceRemove(p, v) {
  p[v.quantity] = (p[v.quantity] || 0) - v.total;
  return p;
}

function reduceInitial() {
  return {};
}

var barChart = dc.barChart("#stackedBarChart")
  .width(1024)
  .height(200)
  .dimension(dimensionByType)
  .group(groupByType, "Quantity: 1", function(d) {
    return d.value[1] || 0;
  })
  .stack(groupByType, "Quantity: 2", function(d) {
    return d.value[2];
  })
  .stack(groupByType, "Quantity: 3", function(d) {
    return d.value[3];
  })
  .x(d3.scale.ordinal().domain(['tab', 'visa', 'cash']))
  .xUnits(dc.units.ordinal)
  .legend(dc.legend().x(500).y(1).itemHeight(15).gap(5));
barChart.yAxis().ticks(5);
barChart.xAxis().ticks(4);


dc.renderAll();
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.1/d3.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/dc/2.1.9/dc.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/dc/2.1.9/dc.min.css" />
<h1>StackedBart Chart:By Type and Quantity</h1>
<div id="stackedBarChart"></div>

To adapt for my needs into this one:

var universe = [{
    "KMIST_TEMP_ID": "KTMPVN12119",
    "ID POP": "",
    "type": 2018,
    "pop": "No",
    "name": "Nha Thuoc An Binh",
    "Country": "",
    "Province": "Ho Chi Minh Province",
    "City": "Ho Chi Minh",
    "district": "Thu Duc",
    "ward": "Linh Trung",
    "name_full": "Ho Chi Minh ,Nha Thuoc An Binh ,Thu Duc, Linh Trung",
    "latitude": 10.8539167,
    "longitude": 106.7716921,
    "geo": "106.7716921,10.8539167",
    "amenity": "pharmacy",
    "date_entered": "2015-10-30T00:00:00",
    "date_issued": "2015-10-30T00:00:00"
  },

  {
    "KMIST_TEMP_ID": "KTMPVN12119",
    "ID POP": "",
    "type": 2018,
    "pop": "No",
    "name": "Nha Thuoc An Binh",
    "Country": "",
    "Province": "Ho Chi Minh Province",
    "City": "Ho Chi Minh",
    "district": "first",
    "ward": "Linh Trung",
    "name_full": "Ho Chi Minh ,Nha Thuoc An Binh ,Thu Duc, Linh Trung",
    "latitude": 10.8539167,
    "longitude": 106.7716921,
    "geo": "106.7716921,10.8539167",
    "amenity": "pharmacy",
    "date_entered": "2015-10-30T00:00:00",
    "date_issued": "2015-10-30T00:00:00"
  },

  {
    "KMIST_TEMP_ID": "KTMPVN12119",
    "ID POP": "",
    "type": "Never Covered",
    "pop": "No",
    "name": "Nha Thuoc An Binh",
    "Country": "",
    "Province": "Ho Chi Minh Province",
    "City": "Ho Chi Minh",
    "district": "new",
    "ward": "Linh Trung",
    "name_full": "Ho Chi Minh ,Nha Thuoc An Binh ,Thu Duc, Linh Trung",
    "latitude": 10.8539167,
    "longitude": 106.7716921,
    "geo": "106.7716921,10.8539167",
    "amenity": "pharmacy",
    "date_entered": "2015-10-30T00:00:00",
    "date_issued": "2015-10-30T00:00:00"
  },

  {
    "KMIST_TEMP_ID": "KTMPVN12119",
    "ID POP": "",
    "type": "Other Periods",
    "pop": "No",
    "name": "Nha Thuoc An Binh",
    "Country": "",
    "Province": "Ho Chi Minh Province",
    "City": "Ho Chi Minh",
    "district": "Thu Duc",
    "ward": "Linh Trung",
    "name_full": "Ho Chi Minh ,Nha Thuoc An Binh ,Thu Duc, Linh Trung",
    "latitude": 10.8539167,
    "longitude": 106.7716921,
    "geo": "106.7716921,10.8539167",
    "amenity": "pharmacy",
    "date_entered": "2015-10-30T00:00:00",
    "date_issued": "2015-10-30T00:00:00"
  }
];



var xdata = crossfilter(universe);
var dimensionByType = xdata.dimension(function(d) {
  return d.district;
});
var groupByType = dimensionByType.group().reduce(reduceAdd, reduceRemove, reduceInitial);


function reduceAdd(p, v) {
  p[v.type] = (p[v.type] || 0) + v.total;
  return p;
}

function reduceRemove(p, v) {
  p[v.type] = (p[v.type] || 0) - v.total;
  return p;
}

function reduceInitial() {
  return {};
}

var barChart = dc.barChart("#stackedBarChart")
  .width(1024)
  .height(200)
  .dimension(dimensionByType)
  .group(groupByType, "Type: 1", function(d) {
    return d.value[1] || 0;
  })
  .stack(groupByType, "Type: 2", function(d) {
    return d.value[2];
  })
  .stack(groupByType, "Type: 3", function(d) {
    return d.value[3];
  })
  .elasticX(true)
  .xUnits(dc.units.ordinal)
  .legend(dc.legend().x(500).y(1).itemHeight(15).gap(5));
barChart.yAxis().ticks(5);
barChart.xAxis().ticks(4);


dc.renderAll();
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.1/d3.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/dc/2.1.9/dc.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/dc/2.1.9/dc.min.css" />

<h1>StackedBart Chart:By Type and Quantity</h1>
<div id="stackedBarChart"></div>
<div id="stackedBarChart2"></div>

How I can make this work for my needs?

Upvotes: 1

Views: 61

Answers (1)

barbsan
barbsan

Reputation: 3458

You have to set x scale (even if you use .elasticX(true)) like this:

.x(d3.scale.ordinal())

Note also that in .group and .stack callbacks you have to use same names that in reduceAdd and reduceRemove is used (type property).
Since your dataset lacked total property and anything value-like I've chosen to display latitude in following demo:

var universe = [{
    "KMIST_TEMP_ID": "KTMPVN12119",
    "ID POP": "",
    "type": 2018,
    "pop": "No",
    "name": "Nha Thuoc An Binh",
    "Country": "",
    "Province": "Ho Chi Minh Province",
    "City": "Ho Chi Minh",
    "district": "Thu Duc",
    "ward": "Linh Trung",
    "name_full": "Ho Chi Minh ,Nha Thuoc An Binh ,Thu Duc, Linh Trung",
    "latitude": 10.8539167,
    "longitude": 106.7716921,
    "geo": "106.7716921,10.8539167",
    "amenity": "pharmacy",
    "date_entered": "2015-10-30T00:00:00",
    "date_issued": "2015-10-30T00:00:00"
  },

  {
    "KMIST_TEMP_ID": "KTMPVN12119",
    "ID POP": "",
    "type": 2018,
    "pop": "No",
    "name": "Nha Thuoc An Binh",
    "Country": "",
    "Province": "Ho Chi Minh Province",
    "City": "Ho Chi Minh",
    "district": "first",
    "ward": "Linh Trung",
    "name_full": "Ho Chi Minh ,Nha Thuoc An Binh ,Thu Duc, Linh Trung",
    "latitude": 10.8539167,
    "longitude": 106.7716921,
    "geo": "106.7716921,10.8539167",
    "amenity": "pharmacy",
    "date_entered": "2015-10-30T00:00:00",
    "date_issued": "2015-10-30T00:00:00"
  },

  {
    "KMIST_TEMP_ID": "KTMPVN12119",
    "ID POP": "",
    "type": "Never Covered",
    "pop": "No",
    "name": "Nha Thuoc An Binh",
    "Country": "",
    "Province": "Ho Chi Minh Province",
    "City": "Ho Chi Minh",
    "district": "new",
    "ward": "Linh Trung",
    "name_full": "Ho Chi Minh ,Nha Thuoc An Binh ,Thu Duc, Linh Trung",
    "latitude": 10.8539167,
    "longitude": 106.7716921,
    "geo": "106.7716921,10.8539167",
    "amenity": "pharmacy",
    "date_entered": "2015-10-30T00:00:00",
    "date_issued": "2015-10-30T00:00:00"
  },

  {
    "KMIST_TEMP_ID": "KTMPVN12119",
    "ID POP": "",
    "type": "Other Periods",
    "pop": "No",
    "name": "Nha Thuoc An Binh",
    "Country": "",
    "Province": "Ho Chi Minh Province",
    "City": "Ho Chi Minh",
    "district": "Thu Duc",
    "ward": "Linh Trung",
    "name_full": "Ho Chi Minh ,Nha Thuoc An Binh ,Thu Duc, Linh Trung",
    "latitude": 10.8539167,
    "longitude": 106.7716921,
    "geo": "106.7716921,10.8539167",
    "amenity": "pharmacy",
    "date_entered": "2015-10-30T00:00:00",
    "date_issued": "2015-10-30T00:00:00"
  }
];



var xdata = crossfilter(universe);
var dimensionByType = xdata.dimension(function(d) {
  return d.district;
});
var groupByType = dimensionByType.group().reduce(reduceAdd, reduceRemove, reduceInitial);


function reduceAdd(p, v) {
  p[v.type] = (p[v.type] || 0) + v.latitude;
  return p;
}

function reduceRemove(p, v) {
  p[v.type] = (p[v.type] || 0) - v.latitude;
  return p;
}

function reduceInitial() {
  return {};
}

var barChart = dc.barChart("#stackedBarChart")
  .width(1024)
  .height(200)
  .dimension(dimensionByType)
  .group(groupByType, "Type: Never Covered", function(d) {
    return d.value['Never Covered'] || 0;
  })
  .stack(groupByType, "Type: 2018", function(d) {
    return d.value['2018'] || 0;
  })
  .stack(groupByType, "Type: Other Periods", function(d) {
    return d.value["Other Periods"] || 0;
  })
  .elasticY(true)
  .x(d3.scale.ordinal())
  .elasticX(true)
  .xUnits(dc.units.ordinal)
  .legend(dc.legend().x(500).y(1).itemHeight(15).gap(5));
barChart.yAxis().ticks(5);
barChart.xAxis().ticks(4);


dc.renderAll();
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.1/d3.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/dc/2.1.9/dc.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/dc/2.1.9/dc.min.css" />

<h1>StackedBart Chart:By Type and Quantity</h1>
<div id="stackedBarChart"></div>
<div id="stackedBarChart2"></div>

Upvotes: 2

Related Questions