Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Earn the coveted Fabric Analytics Engineer certification. 100% off your exam for a limited time only!

Reply
alpayne
Frequent Visitor

Network (force-directed) visual using power BI d3 custom visual

Hi All, 

I'm having trouble getting a force-directed visual to display in Power BI, I think its related to how the data is referenced. I can get it working outside of Power Bi but just can't get it working in Power BI. Here it what it looks like (just using dummy data, which has the form of four colums name, group, source and target. I loaded the data into Power BI from a csv file).

 

Simple force-directed chartSimple force-directed chart

The dummy data I used was,

 

namegroupsourcetarget
A101
B204
C305
D412
E516
F623
G772
H834
I938
J1049

 

and here is the code that I wrote outside of Power BI

 

var margin = {top: 10, right: 30, bottom: 30, left: 40},
  width = 400 - margin.left - margin.right,
  height = 400 - margin.top - margin.bottom;

// append the svg object to the body of the page
var svg = d3.select("body")
.append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
.append("g")
  .attr("transform",
        "translate(" + margin.left + "," + margin.top + ")");

var force = d3.layout.force()
  .gravity(0.1)
  .distance(100)
  .charge(-700)
  .size([width,height]);

var color = function(group) {
  if (group==1) {return "#aaa"}
  else if (group==2) {return "#fbc280"}
  else {return "#405275"}};

var links = [];
var nodes = [];


// d3.json("Network.json", function(error, data) {
//   if (error) throw error;
d3.csv("Network.csv")
  .row(function(d) {return {name:d.name, group:Number(d.group),source:Number(d.source), target:Number(d.target)};})
  .get(function(error,data) {
  for(var i = 0;i < 10; i++){
    links.push({"source":data[i].source,
                "target":data[i].target
                })
    nodes.push({"name":data[i].name,
                 "group":data[i].group
                })
  };
  var dat = {"nodes":nodes, "links":links}
  console.log(dat);
  console.log(dat.nodes);
  console.log(dat.links);
  force
    .nodes(dat.nodes)
    .links(dat.links)
    .start();

  var link = svg.selectAll(".link")
    .data(dat.links)
    .enter()
    .append("line")
      .attr("class","link");
  var node = svg.selectAll(".node")
      .data(dat.nodes)
      .enter()
      .append("g")
        .attr("class", "node")
        .call(force.drag);
  node
    .append('circle')
      .attr('r', 13)
      .attr('fill', function (d) {
        return color(d.group);});
  node
    .append("text")
        .attr("dx", -18)
        .attr("dy", 8)
        .style("font-family", "overwatch")
        .style("font-size", "18px")
        .text(function (d) {
          return d.name});

  force.on("tick", function () {
      link
        .attr("x1", function (d) {
            return d.source.x;})
        .attr("y1", function (d) {
            return d.source.y;})
        .attr("x2", function (d) {
            return d.target.x;})
        .attr("y2", function (d) {
            return d.target.y;});
      node
        .attr("transform", function (d) {
          return "translate(" + d.x + "," + d.y + ")";});
  });
// //console.log(links);
// //console.log(nodes);
});

And here is the code I'm trying to get running in Power BI (adapted from the above code).

 

var margin = {top: 10, right: 30, bottom: 30, left: 40},
  width = pbi.width - margin.left - margin.right,
  height = pbi.height - margin.top - margin.bottom;

// append the svg object to chart
var svg = d3.select("#chart")
.append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
.append("g")
  .attr("transform",
        "translate(" + margin.left + "," + margin.top + ")");

var force = d3.layout.force()
  .gravity(0.1)
  .distance(100)
  .charge(-700)
  .size([width,height]);

var color = function(group) {
  if (group==1) {return "#aaa"}
  else if (group==2) {return "#fbc280"}
  else {return "#405275"}};

var links = [];
var nodes = [];



pbi.dsv(function(data) {
  for(var i = 0;i < 10; i++){
  links.push({"source":data[i].source,
              "target":data[i].target
             })
  nodes.push({"name":data[i].name,
              "group":data[i].group
             })
  };
  var dat = {"nodes":nodes, "links":links}

  force
    .nodes(dat.nodes)
    .links(dat.links)
    .start();

  var link = svg.selectAll(".link")
    .data(dat.links)
    .enter()
    .append("line")
      .attr("class","link");
  var node = svg.selectAll(".node")
      .data(dat.nodes)
      .enter()
      .append("g")
        .attr("class", "node")
        .call(force.drag);
  node
    .append('circle')
      .attr('r', 13)
      .attr('fill', function (d) {
        return color(d.group);});
  node
    .append("text")
        .attr("dx", -18)
        .attr("dy", 8)
        .style("font-family", "allan")
        .style("font-size", "18px")
        .text(function (d) {
          return d.name});

  force.on("tick", function () {
      link
        .attr("x1", function (d) {
            return d.source.x;})
        .attr("y1", function (d) {
            return d.source.y;})
        .attr("x2", function (d) {
            return d.target.x;})
        .attr("y2", function (d) {
            return d.target.y;});
      node
        .attr("transform", function (d) {
          return "translate(" + d.x + "," + d.y + ")";});
  });
});

If anyone can provide some help than I would be very greatful. 

 

 

10 REPLIES 10
wallace13
Advocate II
Advocate II

I contacted the developer and was able to get the answer on how to do this.  More info was needed in the declaration pbi.dsv line.

 

 

var margin = {top: 10, right: 30, bottom: 30, left: 40},
  width = pbi.width - margin.left - margin.right,
  height = pbi.height - margin.top - margin.bottom;

// append the svg object to chart
var svg = d3.select("#chart")
.append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
.append("g")
  .attr("transform",
        "translate(" + margin.left + "," + margin.top + ")");

var force = d3.layout.force()
  .gravity(0.1)
  .distance(100)
  .charge(-700)
  .size([width,height]);

var color = function(group) {
  if (group==1) {return "#aaa"}
  else if (group==2) {return "#fbc280"}
  else {return "#405275"}};

var links = [];
var nodes = [];



pbi.dsv(function(d) {return {name:d.name, group:Number(d.group),source:Number(d.source), target:Number(d.target)};}, function(data) {
  for(var i = 0;i < 10; i++){
  links.push({"source":data[i].source,
              "target":data[i].target
             })
  nodes.push({"name":data[i].name,
              "group":data[i].group
             })
  };
  var dat = {"nodes":nodes, "links":links}

  force
    .nodes(dat.nodes)
    .links(dat.links)
    .start();

  var link = svg.selectAll(".link")
    .data(dat.links)
    .enter()
    .append("line")
      .attr("class","link");
  var node = svg.selectAll(".node")
      .data(dat.nodes)
      .enter()
      .append("g")
        .attr("class", "node")
        .call(force.drag);
  node
    .append('circle')
      .attr('r', 13)
      .attr('fill', function (d) {
        return color(d.group);});
  node
    .append("text")
        .attr("dx", -18)
        .attr("dy", 8)
        .style("font-family", "allan")
        .style("font-size", "18px")
        .text(function (d) {
          return d.name});

  force.on("tick", function () {
      link
        .attr("x1", function (d) {
            return d.source.x;})
        .attr("y1", function (d) {
            return d.source.y;})
        .attr("x2", function (d) {
            return d.target.x;})
        .attr("y2", function (d) {
            return d.target.y;});
      node
        .attr("transform", function (d) {
          return "translate(" + d.x + "," + d.y + ")";});
  });
});

 

 

 

To get the links to show you will also need to add some CSS to that tab:

 

.link {
  stroke-width: 1px;
  stroke: #ccc;
}
wallace13
Advocate II
Advocate II

Hi,

 

Were you able to get this resolved?  I'm having the exact same issue where the D3 force chart won't render despite it working fine outside of the tool.

 

Thanks!

v-evelk
Employee
Employee

Hi,

 

Have you already checked how ForceGraph is implemented?

Please note that source code for this visual is public, feelfreetofork and modify it for your needs.

 

Evgenii Elkin,
Software Engineer
Microsoft Power BI Custom Visuals
pbicvsupport@microsoft.com

 

Thank you for you reply. I had already looked at the Force Graph Power BI Visual, but it didn't suit my needs. I feel changing the source code of this visual would be whole heap more complicated than just trying to get my simple script to run in the Power Bi D3 visual. My thinking was, if I can implement the very simply example I outlined then once it was working I could adpated it to display a much more complicated scenario. The issue I'm having I think is to do with how I get Power BI to recognise the input data. 

Sorry I should have also said. I'm only using Power BI Desktop, hence adapting the code will not be possible. 

Force graph uses standard d3 features for rendering.

You can use the repo to analyze how to build it.

 

Regarding inputs, you should look at the documentation.

There are several pages that can help you in this:

https://microsoft.github.io/PowerBI-visuals/docs/concepts/capabilities/

https://microsoft.github.io/PowerBI-visuals/docs/concepts/dataviewmappings/

https://microsoft.github.io/PowerBI-visuals/docs/concepts/objects-and-properties/

 

There is no so big difference where are you use your visual, the conception is the same.

 

Evgenii Elkin,
Software Engineer
Microsoft Power BI Custom Visuals
pbicvsupport@microsoft.com

Once again thank you for replying and I'm sorry if I'm being painful, but I currently can't use the developer option as I only have Power BI Desktop. I'm in the proccess of getting my company to pay for a subscription to Power BI Pro Service, which would then allow me to use developer functionailty. So unti that happens I'm left with the Power BI D3 visual which I imported from the store front. I have gone through some tutorials on how to implement this visual and as I said I think that the error, although the code doesn't throw any errors, lies with how I have defined my data with the pbi.dsv object. The code works fine outside of Power BI and it appears to me to just be a simple matter seems of tweeking the code I have to enable it to run, but I'm just not sure how to achieve this (I have been trying for a long time on this and was hoping for some fresh ideas).

 

Maybe I will just have to wait until we pay for the Power BI Pro (Service) and then modify the Force Graph Visual to meet my needs. It might just not be possible to use the Power BI D3 visual to display my code.  

Sorry I also should have said, I have gotten my simple data set to work in the Force Graph Visual, but as said I won't be able to use this visual without modifiying the source code to incorpoate the additional capabilites I require and that can't happen until I can use the developer option.  

Could you please send your visual to pbicvsupport@microsoft.com ?

I can analyze it and figure out what is wrong.

 

Evgenii Elkin,
Software Engineer
Microsoft Power BI Custom Visuals
pbicvsupport@microsoft.com

Thank you so much for looking at this for me and spending some time on this, I really appeciate it.

 

The code I'm trying to get to work in the d3 Visual I imported from the Microsoft Store (https://appsource.microsoft.com/en-us/product/power-bi-visuals/WA104381354?tab=Overview) is shown in my orignal question. Also included in my orignal question is the dataset I'm using. I simply stored the dataset as a csv file and then sourced it from Power BI. You can just copy paste the source code and dataset from my original post but I will also send it to the email address you provided.  

 

Futhermore, I'm also in the process of now looking at the source code for the Force Graph Visual (as you suggested) as I have basically given up on using the d3 Visual. The overview of the d3 Visual reads like it should be just a simple matter of copying and pasting your d3.js source code into the d3 Visual editor and then changing a few lines and it should all work. I have gotten this to work for simple visuals but something that is a little bit more complicated doesn't seem to work. Or probably more to the point, I don't understand how to get it to work.  

 

Once again your help is greatly appreciated. 

 

 

Helpful resources

Announcements
April AMA free

Microsoft Fabric AMA Livestream

Join us Tuesday, April 09, 9:00 – 10:00 AM PST for a live, expert-led Q&A session on all things Microsoft Fabric!

March Fabric Community Update

Fabric Community Update - March 2024

Find out what's new and trending in the Fabric Community.