D3.js v4 prepare an object for a Pie Chart

Prepare an array object for a pie chart using d3.pie()(data).value().

   var = data_count = [{
        key: "f",
        value: 2
      },
      {
        key: "m",
        value: 1
      }
    ]

    var arcs = d3.pie()
      .value(function(d) {
        return d.value;
      })
      (data_count);

    arcs.forEach(function(element) {
      console.log(element);
    });

This will generate the array object,

arcs = [
{index: 0, value: 2, startAngle: 0, endAngle: 4.1887902047863905, padAngle: 0},
{index: 1, value: 1, startAngle: 4.1887902047863905, endAngle: 6.283185307179586, padAngle: 0}
]

D3.js v4 prepare array for a Pie Chart

Use d3.pie()(data) to prepare an array of numbers for a pie chart.

var data = [1, 1, 2, 3, 5, 8, 13, 21];
    var arcs = d3.pie()(data);

    arcs.forEach(function(element) {
      console.log(element);
    });

This will generate a new array object,

arcs = [
{data: 1, index: 6, value: 1, startAngle: 6.050474740247008, endAngle: 6.166830023713296, padAngle: 0},
{data: 1, index: 7, value: 1, startAngle: 6.166830023713296, endAngle: 6.2831853071795845, padAngle: 0},
{data: 2, index: 5, value: 2, startAngle: 5.817764173314431, endAngle: 6.050474740247008, padAngle: 0},
{data: 3, index: 4, value: 3, startAngle: 5.468698322915565, endAngle: 5.817764173314431, padAngle: 0},
{data: 5, index: 3, value: 5, startAngle: 4.886921905584122, endAngle: 5.468698322915565, padAngle: 0},
{data: 8, index: 2, value: 8, startAngle: 3.9560796378538132, endAngle: 4.886921905584122, padAngle: 0},
{data: 13, index: 1, value: 13, startAngle: 2.443460952792061, endAngle: 3.9560796378538132, padAngle: 0},
{data: 21, index: 0, value: 21, startAngle: 0, endAngle: 2.443460952792061, padAngle: 0}
]

D3.js v4 count values in an object

We want to count the number of each value that occurs in an object. In this array of object we want to know how many ‘f’ value and how many ‘m’ values there are on the key ‘gender’.
Great link and more indepth examples on Phoebe Bright‘s page.
Also a running example on github.

var data = [{
        name: "Sarah",
        gender: "f",
        value: 1
      },
      {
        name: "Bob",
        gender: "m",
        value: 2
      },
      {
        name: "Amy",
        gender: "f",
        value: 3
      },
    ]

var data_count = d3.nest()
      .key(function(d) {
        return d.gender;
      })
      // .key(function(d) { return d.priority; })
      .rollup(function(leaves) {
        return leaves.length;
      })
      .entries(data);

    data_count.forEach(function(element) {
      console.log(element);
    });
data_count=[
{key: "f", value: 2},
{key: "m", value: 1}
]

D3.js v4 sum values in an object

Given the following array of objects, we may want to sum values for a particular category. The category is gender in this case. So we want to be able to find the total value for all the ‘f’ and for the ‘m’ categories.
Great link and more indepth examples on Phoebe Bright‘s page.
Also a running example on github.

var data = [{
        name: "Sarah",
        gender: "f",
        value: 1
      },
      {
        name: "Bob",
        gender: "m",
        value: 2
      },
      {
        name: "Amy",
        gender: "f",
        value: 3
      },
    ]

    var genderVals = d3.nest().key(function(d) {
        return d.gender;
      })
      .rollup(function(leaves) {
        return d3.sum(leaves, function(d) {
          return d.value;
        });
      }).entries(data)
      .map(function(d) {
        return {
          Gender: d.key,
          totalValue: d.value
        };
      });

    genderVals.forEach(function(element) {
      console.log(element);
    });

This will output the new array of objects called genderVals,

genderVals = [
{Gender: "f", totalValue: 4},
{Gender: "m", totalValue: 2}
]

Angular 4 & D3.js

Code is on github on d3graph repo.
View demo on gh-pages.


Having angular-cli installed (how to install angular-cli), then create a project called ‘angular-d3-example’

$ ng new angular-d3-example

Next we’ll add a component for the graph, which we’ll call ‘d3graph’,

$ ng g c d3graph

Add the selector to the app.component.html file.
We need to install the service ‘d3-ng2-service’. The github page for this is here. Install this service with npm using,

$ npm install d3-ng2-service --save

You will need to import the ‘D3Service’ from ‘d3-ng2-service’ by adding to the top of app.module.ts,

import { D3Service } from 'd3-ng2-service';

Also import ‘D3Service’ to the providers array in the same file.
Then module.ts should look like this,

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
import { D3graphComponent } from './d3graph/d3graph.component';

import { D3Service } from 'd3-ng2-service'; // <-- import statement

@NgModule({
  declarations: [
    AppComponent,
    D3graphComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [D3Service], // <-- import provider
  bootstrap: [AppComponent]
})
export class AppModule { }

Services can be greated with angular-cli using,

$ ng g s SERVICENAME

At this stage it is a good idea to check everything is working by running,

$ ng serve

and navigate to http://localhost:4200 where is should say ‘app works!’ and below it ‘d3graph works!’

We’ll create a bar chart using,

data = [
          {name : 'A', yVal : 1},
          {name : 'B', yVal : 4},
          {name : 'C', yVal : 2},
          {name : 'D', yVal : 3}
      ];

The d3graph.componet.ts will look like this,

import { Component, ElementRef, NgZone, OnDestroy, OnInit } from '@angular/core';

import {
  D3Service,
  D3,
  Axis,
  BrushBehavior,
  BrushSelection,
  D3BrushEvent,
  ScaleLinear,
  ScaleOrdinal,
  Selection,
  Transition
} from 'd3-ng2-service';


@Component({
  selector: 'app-d3graph',
  template: '<svg width="200" height="200"></svg>'
})
export class D3graphComponent implements OnInit {
  private d3: D3;
  private parentNativeElement: any;
  private d3Svg: Selection<SVGSVGElement, any, null, undefined>;

  constructor(element: ElementRef, private ngZone: NgZone, d3Service: D3Service) {
    this.d3 = d3Service.getD3();
    this.parentNativeElement = element.nativeElement;
  }

  ngOnInit() {
            let self = this;
            let d3 = this.d3;
            let d3ParentElement: any;
            let svg: any;
            let name: string;
            let yVal: number;
            let colors: any = [];
            let data: {name: string, yVal: number}[] = [];
            let padding: number = 25;
            let width: number = 500;
            let height: number = 150;
            let xScale: any;
            let yScale: any;
            let xColor: any;
            let xAxis: any;
            let yAxis: any;

    if (this.parentNativeElement !== null) {
      svg = d3.select(this.parentNativeElement)
          .append('svg')        // create an <svg> element
          .attr('width', width) // set its dimensions
          .attr('height', height);

      colors = ['red', 'yellow', 'green', 'blue'];

      data = [
          {name : 'A', yVal : 1},
          {name : 'B', yVal : 4},
          {name : 'C', yVal : 2},
          {name : 'D', yVal : 3}
      ];

      xScale = d3.scaleBand()
          .domain(data.map(function(d){ return d.name; }))
          .range([0, 200]);

      yScale = d3.scaleLinear()
          .domain([0,d3.max(data, function(d) {return d.yVal})])
          .range([100, 0]);

      xAxis = d3.axisBottom(xScale) // d3.js v.4
          .ticks(5)
          .scale(xScale);

      yAxis = d3.axisLeft(xScale) // d3.js v.4
          .scale(yScale)
          .ticks(7);

        svg.append("g")
        .attr("class", "axis")
        .attr("transform", "translate(" + (padding) + "," + padding + ")")
        .call(yAxis);

	       svg.append('g')            // create a <g> element
         .attr('class', 'axis')   // specify classes
	       .attr("transform", "translate(" + padding + "," + (height - padding) + ")")
         .call(xAxis);            // let the axis do its thing

      var rects = svg.selectAll('rect')
          .data(data);
          rects.size();

      var newRects = rects.enter();

      newRects.append('rect')
          .attr('x', function(d,i) {
            return xScale(d.name );
          })
          .attr('y', function(d) {
              return yScale(d.yVal);
            })
	        .attr("transform","translate(" + (padding -5  + 25) + "," + (padding - 5) + ")")
          .attr('height', function(d) {
              return height - yScale(d.yVal) - (2*padding) + 5})
          .attr('width', 10)
          .attr('fill', function(d, i) {
            return colors[i];
          });
     }
   }
 }

Should look like this,

Code is on github on d3graph repo.
View demo on gh-pages.