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
aar0n
Advocate II
Advocate II

d3 Line graph dual y-axis

The following code compiles, but doesn't render a graph. Not sure why exactly it isnt working in power bi....

 

i am using an input of "Date", "Value1", "Value2".
i am trying to plot date on x-axis, value1 on left y-axis, and value2 on right y-axis.

 

// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 40, bottom: 30, left: 50},
    width = pbi.width - margin.left - margin.right,
    height = pbi.height - margin.top - margin.bottom;

var parseDate = d3.time.format("%d-%b-%y").parse;

// Set the ranges
var x = d3.time.scale().range([0, width]);
var y0 = d3.scale.linear().range([height, 0]);
var y1 = d3.scale.linear().range([height, 0]);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var xAxis = d3.svg.axis().scale(x)
    .orient("bottom").ticks(5);

var yAxisLeft = d3.svg.axis().scale(y0)
    .orient("left").ticks(5);

var yAxisRight = d3.svg.axis().scale(y1)
    .orient("right").ticks(5); 

//////////////////////////////////////////////////////

var valueline = d3.svg.line()
    .x(function(d) { return x(d.date); })
    .y(function(d) { return y0(d.Value1); });
    
var valueline2 = d3.svg.line()
    .x(function(d) { return x(d.date); })
    .y(function(d) { return y1(d.Value2); });

///////////////////////////////////////////////////////////////////

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


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  
  // ALTER: Replaced the d3.tsv function with the pbi variant: pbi.dsv
pbi.dsv(type, function(values) {
    data.forEach(function(d) {
        d.date = parseDate(d.date);
        d.Value1 = +d.Value1;
        d.Value2 = +d.Value2;
    });

  // Scale the range of the data
    x.domain(d3.extent(data, function(d) { return d.date; }));
    y0.domain([0, d3.max(data, function(d) {
		return Math.max(d.Value1); })]); 
    y1.domain([0, d3.max(data, function(d) { 
		return Math.max(d.Value2); })]);

    svg.append("path")        // Add the valueline path.
        .attr("d", valueline(data));

    svg.append("path")        // Add the valueline2 path.
        .style("stroke", "red")
        .attr("d", valueline2(data));

    svg.append("g")            // Add the X Axis
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);

    svg.append("g")
        .attr("class", "y axis")
        .style("fill", "steelblue")
        .call(yAxisLeft);	

    svg.append("g")				
        .attr("class", "y axis")	
        .attr("transform", "translate(" + width + " ,0)")	
        .style("fill", "red")		
        .call(yAxisRight);

});
 


it is similar to:

http://bl.ocks.org/d3noob/e34791a32a54e015f57d

 

16 REPLIES 16
sriksrin
Frequent Visitor

Hi,

 

 I am trying to create the dual y axis line chart from the d3 code : http://bl.ocks.org/d3noob/e34791a32a54e015f57d

 

Changed the D3 code as per the D3JSVisuals instruction.  I notice that the path is not getting constructed. The lines always start from one point and not join from the previous point. 

 

I have put in the modified code as per custom visual instruction and the screenshot. Require help in resolving the same.

 

Code:

 

 

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

var parseDate = d3.time.format("%d-%b-%y").parse;

var x = d3.time.scale().range([0, width]);
var y0 = d3.scale.linear().range([height, 0]);
var y1 = d3.scale.linear().range([height, 0]);

var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);

var yAxisLeft = d3.svg.axis().scale(y0)
.orient("left").ticks(5);

var yAxisRight = d3.svg.axis().scale(y1)
.orient("right").ticks(5);

/*var valueline = d3.svg.line()
.x(function(d) { return d.date; })
.y(function(d) { return d.close; })
.interpolate("linear");
*/
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y0(d.close); })
.interpolate("cardinal");

var valueline2 = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y1(d.open); });

var svgCont = 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 + ")");

// Get the data
pbi.dsv(function(data) {

data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
d.open = +d.open;
});

// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y0.domain([0, d3.max(data, function(d) {
return Math.max(d.close); })]); 
y1.domain([0, d3.max(data, function(d) { 
return Math.max(d.open); })]);

svgCont.append("path") // Add the valueline path.
.attr("class","line")
.attr("d", valueline(data));

/*svg.append("path") // Add the valueline2 path.
.style("stroke", "red")
.attr("d", valueline2(data));*/

svgCont.append("g") // Add the X Axis
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);

svgCont.append("g")
.attr("class", "y axis")
.style("fill", "steelblue")
.call(yAxisLeft);

svgCont.append("g") 
.attr("class", "y axis") 
.attr("transform", "translate(" + width + " ,0)") 
.style("fill", "red") 
.call(yAxisRight);

});
v-viig
Community Champion
Community Champion

We'd recommend to add a try-catch to catch an exception.

 

Otherwise, please share source code.

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

can you please elaborate "try-catch"?

 

also, i thought i did above.. is there anything else that might be needed? 

v-viig
Community Champion
Community Champion

We'd recommend to take a look at try-catch syntax here.

 

To debug this issue we should have a full source code along with pbiviz.json, tsconfig.json, etc.

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

since the data is confidential, i am unable to post the powerbi file, etc. if there is any other example of a dual y-axis line graph, using d3, i would be happy to use it instead of the code above.. 

v-viig
Community Champion
Community Champion

What verison of d3 do you use? Can you share pbiviz.json, package.json and tsconfig.json?

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

Hi, I am also facing the same problem. I am using the custom visual D3JSVisuals and embedding the D3 code into it. 

 

I get to see that the lines always start from the same point and not from the previous point. Can't figure where mistake is going on. 

 

Request your help in the same.

 

D3 Version : V3

Custom Visual: D3JSVisual

D3 Code: http://bl.ocks.org/d3noob/e34791a32a54e015f57d

PBI Code :

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

var parseDate = d3.time.format("%d-%b-%y").parse;

var x = d3.time.scale().range([0, width]);
var y0 = d3.scale.linear().range([height, 0]);
var y1 = d3.scale.linear().range([height, 0]);

var xAxis = d3.svg.axis().scale(x)
    .orient("bottom").ticks(5);

var yAxisLeft = d3.svg.axis().scale(y0)
    .orient("left").ticks(5);

var yAxisRight = d3.svg.axis().scale(y1)
    .orient("right").ticks(5); 

/*var valueline = d3.svg.line()
    .x(function(d) { return d.date; })
    .y(function(d) { return d.close; })
	.interpolate("linear");
*/
var valueline = d3.svg.line()
    .x(function(d) { return x(d.date); })
    .y(function(d) { return y0(d.close); })
	.interpolate("cardinal");
    
var valueline2 = d3.svg.line()
    .x(function(d) { return x(d.date); })
    .y(function(d) { return y1(d.open); });
  
var svgCont = 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 + ")");

// Get the data
pbi.dsv(function(data) {
   
 data.forEach(function(d) {
        d.date = parseDate(d.date);
        d.close = +d.close;
        d.open = +d.open;
    });

    // Scale the range of the data
    x.domain(d3.extent(data, function(d) { return d.date; }));
    y0.domain([0, d3.max(data, function(d) {
		return Math.max(d.close); })]); 
    y1.domain([0, d3.max(data, function(d) { 
		return Math.max(d.open); })]);

    svgCont.append("path")        // Add the valueline path.
        .attr("class","line")
        .attr("d", valueline(data));

    /*svg.append("path")        // Add the valueline2 path.
        .style("stroke", "red")
        .attr("d", valueline2(data));*/

    svgCont.append("g")            // Add the X Axis
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);

    svgCont.append("g")
        .attr("class", "y axis")
        .style("fill", "steelblue")
        .call(yAxisLeft);	

    svgCont.append("g")				
        .attr("class", "y axis")	
        .attr("transform", "translate(" + width + " ,0)")	
        .style("fill", "red")		
        .call(yAxisRight);
  
});
v-viig
Community Champion
Community Champion

@jppp Can you help with this issue? It seems devs use D3.JS visual.

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

I managed to get the code working and basically the trick is in how the data is presented to and used by D3js.
In this case the date column: I have kept it as a string, e.g. '26-Mar-18' and add a derived column, convert as a date type and use that for the 'sort-by' column.

After that the line d3.time.format("%d-%b-%y").parse; will correctly parse the column to dates that can be used by the d3js axis.

 

If you need some more explanation; I got a PBIX file that I can share if needed.

 

-JP

 

Anonymous
Not applicable

Can you reshare PBIX file ? cause the link you posted is no longer available. 

sriksrin
Frequent Visitor

Hi JP,

 

 While i am trying what you have said, it would really be very helpful to share the pbix file.

 

Thanks

Srikanth

v-viig
Community Champion
Community Champion

PBIX has been attached by Jan Pieter. See link above.

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

tcd1nc
Frequent Visitor

i would really appreciate if you could share the file! 

 

Thanks for the help!!

 

You should be able to download it here.

 

If you have questions, feel free.

sriksrin
Frequent Visitor

Thanks jppp for sharing the pbix file. I am still puzzled as the new duplicate column didnot change any data after been applied to sort. Can u share some more details on the fix.  

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.

Top Solution Authors