Why does this D3 code not produce any output in Jupyter Notebook? - javascript
I followed this blog here and here's the code that I'm trying to run on my Jupyter Notebook - essentially a simple scatter plot from the iris dataset.
from IPython.core.display import display, HTML
from string import Template
import pandas as pd
import json, random
HTML('<script src="./d3.min.js"></script>')
filename = 'https://gist.githubusercontent.com/mbostock/3887118/raw/2e68ffbeb23fe4dadd9b0f6bca62e9def6ee9e17/data.tsv'
iris = pd.read_csv(filename,sep="\t")
iris_array_of_dicts = iris.to_dict(orient='records')
css_text = '''
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.dot {
stroke: #000;
}
'''
js_text_template = Template('''
var margin = {top: 20, right: 20, bottom: 30, left: 40},
// **** width = 960 - margin.left - margin.right, ****
// **** height = 500 - margin.top - margin.bottom; ****
width = 720 - margin.left - margin.right,
height = 375 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
// **** var svg = d3.select("body").append("svg") ****
var svg = d3.select("#$graphdiv").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 + ")");
// **** d3.tsv("data.tsv", function(error, data) { ****
// **** if (error) throw error; ****
var data = $python_data ;
data.forEach(function(d) {
d.sepalLength = +d.sepalLength;
d.sepalWidth = +d.sepalWidth;
});
x.domain(d3.extent(data, function(d) { return d.sepalWidth; })).nice();
y.domain(d3.extent(data, function(d) { return d.sepalLength; })).nice();
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("Sepal Width (cm)");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Sepal Length (cm)")
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.sepalWidth); })
.attr("cy", function(d) { return y(d.sepalLength); })
.style("fill", function(d) { return color(d.species); });
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
// **** }); ****
''')
html_template = Template('''
<style> $css_text </style>
<div id="graph-div"></div>
<script> $js_text </script>
''')
js_text = js_text_template.substitute({'python_data': json.dumps(iris_array_of_dicts),
'graphdiv': 'graph-div'})
HTML(html_template.substitute({'css_text': css_text, 'js_text': js_text}))
The code runs without errors but doesn't display any output.
I've also tried to use the display functionality but that still produces no results.
What am I doing wrong? My assumption is that since this is an old blog post, Jupyter has moved past supporting Javascript this way and I have to use cell and line magics now but I'm not sure as I'm new to Javascript.
I have just tried and figured out the problem.
If you look at the console log, the browser do not interpret d3. To solve it add to your code.
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
You will now see your nice plot
Here an exemple of update
In [1]:
from IPython.core.display import display, HTML
from string import Template
import pandas as pd
import json, random
HTML('<script src="./d3.min.js"></script>')
filename = 'https://gist.githubusercontent.com/mbostock/3887118/raw/2e68ffbeb23fe4dadd9b0f6bca62e9def6ee9e17/data.tsv'
iris = pd.read_csv(filename,sep="\t")
iris_array_of_dicts = iris.to_dict(orient='records')
css_text = '''
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.dot {
stroke: #000;
}
'''
js_text_template = Template('''
var margin = {top: 20, right: 20, bottom: 30, left: 40},
// **** width = 960 - margin.left - margin.right, ****
// **** height = 500 - margin.top - margin.bottom; ****
width = 720 - margin.left - margin.right,
height = 375 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
// **** var svg = d3.select("body").append("svg") ****
var svg = d3.select("#$graphdiv").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 + ")");
// **** d3.tsv("data.tsv", function(error, data) { ****
// **** if (error) throw error; ****
var data = $python_data ;
data.forEach(function(d) {
d.sepalLength = +d.sepalLength;
d.sepalWidth = +d.sepalWidth;
});
x.domain(d3.extent(data, function(d) { return d.sepalWidth; })).nice();
y.domain(d3.extent(data, function(d) { return d.sepalLength; })).nice();
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("Sepal Width (cm)");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Sepal Length (cm)")
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.sepalWidth); })
.attr("cy", function(d) { return y(d.sepalLength); })
.style("fill", function(d) { return color(d.species); });
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
// **** }); ****
''')
html_template = Template('''
<style > $css_text </style>
<div id="graph-div"></div>
<script > $js_text </script>
''')
js_text = js_text_template.substitute({'python_data': json.dumps(iris_array_of_dicts),
'graphdiv': 'graph-div'})
my_plot = html_template.substitute({'css_text': css_text, 'js_text': js_text})
d3_download = """ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8" > </script>"""
my_plot = d3_download + my_plot
HTML(my_plot)
Out [1]:
Related
D3.js path goes in different directions in V3 vs V4
I'm attempting to make the same multi-line graph in D3 V3 and V4, but they behave differently for reasons I don't understand. What can I change in my V4 code that will make the paths connect in the correct order (according to the x axis instead of the y axis)? Here's what V3 gives, taken from the jsfiddle I made for it: ...But here's V4: Jsfiddle doesn't support V4 yet, so here's my code: var margin = {top: 20, right: 40, bottom: 100, left: 100}, width = 500 - margin.left - margin.right, height = 400 - margin.top - margin.bottom; var x = d3.scaleLinear().range([0, width]); var y = d3.scaleLinear().range([height, 0]); var xAxis = d3.axisBottom(x); var yAxis = d3.axisLeft(y); var line = d3.line() .x(function(d) { return x(d.depth); }) .y(function(d) { return y(d.carat); }); 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 + ")"); d3.csv("diamonds.csv", function(error, data) { data.forEach(function(d) { d.carat = +d.carat; d.depth = +d.depth; //d.cut = +d.cut; }) data.sort(function(a,b) { return a.x - b.x; }); x.domain(d3.extent(data, function(d) { return d.depth; })).nice(); y.domain(d3.extent(data, function(d) { return d.carat; })).nice(); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .attr("y", 6) .attr("x", 5) .attr("dy", ".35em") .attr("transform", "rotate(45)") .style("text-anchor", "start") var dataNest = d3.nest() .key(function(d) {return d.cut;}) .entries(data); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("class", "label") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("Price"); var color = d3.scaleOrdinal(d3.schemeCategory10); dataNest.forEach(function(d) { svg.append("path") .attr("class", "line") .style("stroke", function() { // Add the colours dynamically return d.color = color(d.key); }) .attr("d", line(d.values)); }); });
If you look at your code using D3 v3.x, you did this after loading the data: data.forEach(function(d) { d.x = +d.depth; d.carat = +d.carat; }) And using that property x for sorting: data.sort(function(a,b) { return a.x - b.x; }); However, in your v4.x version, you did: data.forEach(function(d) { d.depth = +d.depth; d.carat = +d.carat; }) And used an nonexistent x for sorting (the problem with sorting alone was making the lines different from v3.x). Solution: use depth for sorting: data.sort(function(a,b) { return a.depth - b.depth; }); Here is your code using v4.x version: var margin = { top: 20, right: 40, bottom: 100, left: 100 }, width = 500 - margin.left - margin.right, height = 400 - margin.top - margin.bottom; var x = d3.scaleLinear().range([0, width]); var y = d3.scaleLinear().range([height, 0]); var xAxis = d3.axisBottom(x); var yAxis = d3.axisLeft(y); var line = d3.line() .x(function(d) { return x(d.depth); }) .y(function(d) { return y(d.carat); }); 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 data = d3.csvParse(d3.select("pre#data").text()); data.forEach(function(d) { d.carat = +d.carat; d.depth = +d.depth; //d.cut = +d.cut; }) data.sort(function(a, b) { return a.depth - b.depth; }); x.domain(d3.extent(data, function(d) { return d.depth; })).nice(); y.domain(d3.extent(data, function(d) { return d.carat; })).nice(); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .attr("y", 6) .attr("x", 5) .attr("dy", ".35em") .attr("transform", "rotate(45)") .style("text-anchor", "start") var dataNest = d3.nest() .key(function(d) { return d.cut; }) .entries(data); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("class", "label") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("Price"); var color = d3.scaleOrdinal(d3.schemeCategory10); dataNest.forEach(function(d) { svg.append("path") .attr("class", "line") .style("stroke", function() { // Add the colours dynamically return d.color = color(d.key); }) .attr("d", line(d.values)); }); pre { display:none; } path { fill: none; stroke: #000; } .line { fill: none; // stroke: green; // stroke-width: 3.5px; } <script src="https://d3js.org/d3.v4.min.js"></script> <pre id="data"> carat,cut,color,clarity,depth,table,price,x,y,z 0.41,Ideal,G,VS1,60.8,56,899,4.79,4.82,2.92 0.3,Ideal,F,VS1,62.1,55,612,4.31,4.35,2.69 1.25,Ideal,H,SI1,62.2,57,6661,6.86,6.9,4.28 0.41,Ideal,G,VS2,61.4,55,1061,4.8,4.75,2.93 0.53,Premium,E,VVS2,62.4,56,2331,5.19,5.17,3.23 1.14,Very Good,G,VS2,63.2,56,6435,6.67,6.63,4.2 0.51,Premium,G,SI1,62,59,1053,5.12,5.1,3.17 1.51,Good,H,VVS2,63.1,59,11826,7.26,7.28,4.59 1.31,Ideal,J,SI1,62.5,56,6337,6.95,7.04,4.37 0.33,Very Good,I,VVS1,61.7,61,608,4.43,4.45,2.74 0.42,Ideal,F,VS1,62.3,55,1103,4.79,4.77,2.98 1.01,Good,E,VS2,60.8,63,6250,6.44,6.46,3.92 1,Premium,F,SI1,62.7,59,5292,6.4,6.36,4 0.51,Ideal,G,VVS1,61.9,53,1919,5.14,5.2,3.2 0.34,Ideal,H,SI1,61.5,55,647,4.53,4.55,2.79 0.23,Premium,F,VVS2,61.3,59,445,3.94,3.99,2.43 0.3,Ideal,F,VS2,62.9,57,776,4.29,4.27,2.69 1.14,Premium,F,SI1,60.4,58,6320,6.82,6.79,4.11 0.33,Ideal,J,VVS1,62.1,54,509,4.45,4.47,2.77 0.41,Premium,H,SI1,60.9,60,683,4.79,4.83,2.93 2.01,Premium,J,SI2,62.8,58,12407,8.09,8,5.05 2.01,Very Good,I,SI1,60.3,59,15126,8.14,8.21,4.93 0.4,Very Good,D,VS2,62.8,58,993,4.66,4.71,2.94 1.09,Premium,D,SI1,61.6,58,5799,6.61,6.57,4.06 0.3,Ideal,F,VS1,61.5,55,612,4.31,4.34,2.66 0.77,Very Good,H,SI2,63.6,58,2129,5.77,5.81,3.68 0.38,Very Good,F,VS1,62.7,57,883,4.71,4.64,2.93 0.54,Premium,E,VS1,60.3,58,1939,5.26,5.32,3.19 0.93,Premium,F,SI1,58.8,60,4010,6.49,6.37,3.78 0.32,Ideal,H,VS1,61.1,56,561,4.44,4.46,2.72 0.78,Premium,F,SI2,62.8,56,2200,5.9,5.86,3.69 0.4,Ideal,E,VS1,61.2,55,1005,4.79,4.76,2.92 0.41,Ideal,D,VS2,62.4,55,1076,4.79,4.76,2.98 0.73,Very Good,E,SI1,61.6,59,2760,5.77,5.78,3.56 2.52,Very Good,G,SI2,63.2,58,17689,8.65,8.61,5.45 1.06,Ideal,D,VVS2,62,56,12053,6.53,6.57,4.06 0.8,Very Good,D,IF,63.3,57,6834,5.85,5.87,3.71 1.5,Premium,H,VS2,62.2,58,10291,7.27,7.36,4.55 2.17,Good,H,SI2,58.9,62,16036,8.48,8.52,5.01 1.58,Ideal,G,SI1,62.2,55,11927,7.44,7.5,4.65 2.03,Premium,H,VS2,62.1,56,18139,8.2,8.12,5.07 0.58,Very Good,D,SI2,62.9,56,1438,5.31,5.35,3.35 0.72,Very Good,D,VS2,62.1,59,3016,5.7,5.73,3.55 0.38,Ideal,D,VVS2,61.5,57,1200,4.63,4.67,2.86 0.5,Premium,E,VS2,61.3,60,1624,5.07,5.11,3.12 0.31,Ideal,F,VS2,61.1,56,640,4.35,4.39,2.67 1.41,Premium,D,SI2,61.1,56,6988,7.19,7.15,4.38 0.7,Good,I,VS1,63.2,55,2274,5.58,5.63,3.54 1.22,Ideal,F,SI2,62,57,4852,6.88,6.83,4.25 1.58,Ideal,H,VS2,61.4,56,12334,7.5,7.56,4.62 1.2,Ideal,G,VS1,62,55,9625,6.81,6.87,4.24 1.03,Premium,H,I1,61.1,60,3172,6.46,6.51,3.96 0.77,Very Good,H,VS1,62.8,58,2961,5.75,5.78,3.62 1.04,Ideal,I,VS2,61.5,57,5105,6.49,6.52,4 1,Good,H,SI1,63.7,60,4788,6.33,6.3,4.02 0.82,Very Good,G,IF,61.9,57,4844,5.96,6,3.7 0.71,Ideal,D,VS1,60.9,57,3518,5.74,5.76,3.5 1.21,Ideal,I,SI2,64.6,56,4879,6.67,6.62,4.29 0.4,Very Good,E,SI1,61.7,60,687,4.68,4.72,2.9 1.11,Premium,H,SI1,61.1,60,5433,6.68,6.62,4.06 1.5,Ideal,F,VS2,60.4,57,14071,7.41,7.43,4.48 1.48,Very Good,H,SI1,62.5,59,8815,7.16,7.23,4.5 0.28,Ideal,F,VVS2,61.5,57,787,4.19,4.24,2.59 0.64,Very Good,E,VS2,63.4,54,2114,5.52,5.49,3.49 1.68,Ideal,I,VS2,62.1,57,10800,7.6,7.54,4.7 0.93,Premium,G,SI2,61.7,60,3802,6.25,6.2,3.84 0.34,Very Good,E,SI1,62.9,56,596,4.45,4.48,2.81 1.57,Premium,G,VS1,59.9,56,14180,7.6,7.55,4.54 1.16,Premium,H,SI2,61.8,58,4872,6.81,6.75,4.19 0.3,Ideal,E,VVS2,61.4,57,1013,4.34,4.32,2.66 1.06,Very Good,F,SI1,63.4,58,5520,6.51,6.42,4.1 1.14,Ideal,H,SI1,61.6,56,7079,6.72,6.74,4.14 1,Premium,J,SI1,58.7,58,3920,6.55,6.51,3.83 2.01,Very Good,F,SI2,63.3,59,11925,7.98,7.89,5.02 1.37,Premium,G,VS1,58.3,60,10412,7.35,7.3,4.27 0.91,Premium,E,SI2,61.6,60,3846,6.14,6.1,3.77 1,Premium,G,VS2,63,58,6048,6.4,6.33,4.01 0.4,Good,G,SI1,63.4,58,655,4.66,4.71,2.97 1.39,Very Good,G,SI2,61.5,62,6628,7.09,7.16,4.38 0.31,Ideal,G,IF,62.7,57,924,4.31,4.34,2.71 1.5,Premium,H,VS2,62.4,59,11092,7.29,7.32,4.56 0.99,Very Good,F,SI1,62.5,58,5112,6.36,6.38,3.98 1.5,Very Good,I,VVS2,64,54,9618,7.19,7.27,4.63 1.04,Very Good,E,VVS2,62.4,58,8748,6.46,6.4,4.01 1.01,Premium,H,SI1,61.8,59,5204,6.38,6.33,3.93 0.71,Fair,D,SI1,55.5,62,2086,6,5.97,3.32 0.26,Ideal,G,VS1,62.1,55,478,4.09,4.12,2.55 0.92,Premium,E,SI1,61.7,57,4637,6.32,6.2,3.86 0.32,Ideal,E,VS2,61.8,54,768,4.43,4.4,2.73 0.54,Ideal,H,IF,61.5,54,1981,5.27,5.3,3.25 0.4,Ideal,G,IF,61.2,56,1199,4.74,4.77,2.91 1.28,Very Good,G,VVS2,59.5,56,11478,7.12,7.16,4.25 0.42,Premium,G,VS2,60.6,59,1087,4.85,4.78,2.92 1.04,Premium,H,VS2,60.4,59,5777,6.66,6.51,3.98 0.91,Premium,G,SI1,61.8,60,4045,6.18,6.21,3.83 0.33,Very Good,H,VS2,58.8,62,486,4.49,4.53,2.65 0.31,Ideal,E,VS1,61.3,54,664,4.37,4.4,2.69 0.61,Very Good,D,VS1,62.4,57,2096,5.44,5.46,3.4 0.3,Ideal,H,VVS2,61.6,55,605,4.3,4.34,2.66 1.57,Premium,J,VS1,61.3,59,8595,7.44,7.47,4.57 0.72,Very Good,J,VS1,62.3,57,2136,5.73,5.77,3.58 1.11,Premium,F,SI2,62.2,57,5284,6.67,6.61,4.13 0.4,Premium,D,SI2,61.7,58,855,4.74,4.69,2.91 0.7,Good,F,VVS1,63.3,56,3310,5.64,5.7,3.59 1,Premium,D,SI2,59.4,60,4626,6.56,6.48,3.87 0.61,Ideal,E,VVS2,62,54,3011,5.43,5.47,3.38 1,Premium,F,VS2,62.8,59,6328,6.35,6.32,3.98 1.05,Ideal,F,SI2,60.9,56,4591,6.56,6.64,4.02 1.01,Premium,I,SI1,61.6,58,3944,6.45,6.51,3.99 0.51,Ideal,F,VS2,63.2,57,1687,5.08,5.05,3.2 1.2,Premium,H,SI2,62.4,61,5040,6.81,6.78,4.24 1.52,Ideal,J,VS1,62.3,58,8608,7.32,7.35,4.57 0.51,Premium,F,VVS2,61.9,56,2310,5.17,5.13,3.19 0.5,Very Good,H,IF,61.4,61,1923,5.14,5.03,3.12 1.01,Premium,G,SI1,63,60,4118,6.34,6.3,3.98 0.8,Very Good,F,VS1,62.6,57,3720,5.9,5.98,3.72 2.01,Very Good,I,SI1,62.8,60,14811,7.99,8.04,5.03 1,Premium,E,SI1,61.6,59,5600,6.41,6.38,3.94 1,Good,J,VS1,58.1,64,3920,6.63,6.51,3.82 0.52,Premium,F,VS2,61.4,62,1605,5.19,5.16,3.18 1.3,Very Good,I,VS2,61.8,56,7087,6.98,7.04,4.33 2,Very Good,I,SI1,62.9,59.2,15081,7.95,8.08,5.05 0.31,Very Good,I,VS2,61.6,56,468,4.36,4.39,2.69 1.63,Very Good,I,SI1,62,54,9090,7.6,7.67,4.73 0.3,Premium,H,VVS2,62.1,52,776,4.31,4.29,2.67 1.1,Premium,G,VS2,62.8,58,6387,6.6,6.58,4.14 0.23,Very Good,F,VVS2,61,59,465,3.93,3.97,2.41 1.23,Premium,I,SI2,62.1,59,4773,6.83,6.79,4.23 1.02,Good,G,VS2,63.6,57,5816,6.38,6.41,4.07 0.71,Premium,F,VS1,59.2,58,2839,5.87,5.82,3.46 1.69,Ideal,H,I1,62,56,6757,7.66,7.61,4.73 1.6,Ideal,G,VS2,61.9,56,15000,7.53,7.47,4.64 0.32,Ideal,H,IF,61.9,54.2,783,4.38,4.42,2.72 0.73,Very Good,G,SI2,62.2,58,2057,5.71,5.77,3.57 0.32,Ideal,D,VS2,62.7,54,758,4.36,4.38,2.74 0.7,Ideal,E,VS2,61.1,59,3201,5.67,5.73,3.48 0.3,Ideal,H,VS1,62.1,54,526,4.32,4.35,2.69 0.9,Good,I,VS2,63.8,55,3303,6.07,6.16,3.9 0.52,Premium,H,SI2,60.9,61,975,5.15,5.1,3.12 0.97,Premium,F,SI1,62.7,59,4561,6.28,6.31,3.95 0.32,Very Good,H,SI1,62.6,55,461,4.37,4.38,2.74 0.54,Ideal,F,SI1,61.2,56,1307,5.23,5.29,3.22 1.21,Good,F,VS2,63.7,58,7911,6.67,6.71,4.26 1.51,Very Good,I,SI1,63.1,56,7891,7.28,7.33,4.61 1.01,Premium,F,VS2,58.9,58,6271,6.59,6.51,3.86 1.57,Very Good,J,VS2,62.6,59,7832,7.39,7.43,4.64 0.73,Premium,I,VS1,60.3,58,2371,5.83,5.87,3.53 1.2,Ideal,I,SI1,62.5,57,5107,6.77,6.71,4.21 3.04,Premium,I,SI2,59.3,60,18559,9.51,9.46,5.62 0.31,Very Good,G,VVS1,63.1,56,1046,4.35,4.33,2.74 0.5,Premium,E,I1,60.7,61,840,5.14,5.05,3.09 0.38,Ideal,I,VS1,62.4,54.4,703,4.62,4.66,2.9 1.12,Premium,G,VS2,60.7,53,6774,6.81,6.7,4.1 1.33,Premium,F,SI2,60.7,62,5288,7.12,7.07,4.31 1.11,Ideal,J,VS1,61.7,57,4854,6.67,6.72,4.13 0.71,Ideal,G,SI1,62.4,56,2386,5.74,5.71,3.57 1.03,Ideal,G,VS1,62.1,57,6558,6.44,6.47,4.01 0.32,Very Good,G,VVS1,61.4,55,772,4.41,4.45,2.72 1.55,Premium,D,VS2,61.5,58,16137,7.51,7.48,4.61 0.72,Premium,F,VS2,60.8,58,2530,5.78,5.74,3.5 0.31,Good,F,VS2,63.4,56,625,4.29,4.32,2.73 0.42,Ideal,G,IF,62,57,1310,4.82,4.8,2.98 2.1,Premium,H,SI2,60.4,59,16479,8.28,8.33,5.02 0.66,Ideal,H,VS2,61.4,56,2178,5.62,5.65,3.46 0.48,Premium,F,SI1,60.6,62,1110,5.06,5,3.05 0.91,Very Good,D,SI1,63,59,4429,6.11,6.15,3.86 0.5,Ideal,E,SI2,62.5,57,1154,5.04,5.07,3.16 0.57,Ideal,I,VS1,62.2,55,1448,5.28,5.33,3.3 1.09,Premium,F,SI1,60.9,59,5384,6.64,6.59,4.03 1,Premium,H,SI1,62.3,60,4788,6.38,6.34,3.96 0.4,Very Good,E,VS2,63,58,791,4.7,4.73,2.97 1.2,Ideal,I,SI1,60.1,56,5578,6.9,6.84,4.13 0.71,Premium,I,VS2,59.3,59,2300,5.89,5.81,3.47 0.34,Ideal,D,VS2,62,55,1033,4.48,4.45,2.77 1.25,Good,J,SI1,63.6,57,5110,6.86,6.81,4.35 0.41,Ideal,D,SI1,61.7,54,1015,4.79,4.78,2.95 0.51,Fair,D,SI2,66.5,58,1109,4.95,4.89,3.27 0.56,Ideal,E,SI1,62.7,57,1698,5.27,5.23,3.29 1.04,Ideal,G,VS1,61.5,57,7457,6.5,6.54,4.01 0.3,Ideal,I,SI1,61.9,57,422,4.29,4.31,2.66 0.5,Premium,F,VS2,61.7,60,1323,5.06,5.02,3.11 0.28,Very Good,G,VVS2,62.3,56,522,4.16,4.19,2.6 0.37,Very Good,E,VS1,62,56,925,4.59,4.63,2.86 0.8,Premium,F,SI2,58.5,62,2371,6.08,6.05,3.55 0.81,Very Good,F,SI2,62.7,58,2942,5.92,5.95,3.72 0.51,Ideal,E,VVS2,62.8,56,2211,5.13,5.15,3.23 0.98,Ideal,G,SI1,62.3,56,4665,6.37,6.34,3.96 1.51,Good,H,VS2,63.6,61,8904,7.08,7.03,4.49 0.5,Premium,D,SI1,60.3,58,1433,5.12,5.1,3.08 0.43,Ideal,F,VVS2,62.2,55,1250,4.85,4.83,3.01 0.7,Ideal,F,SI1,61.1,57,2516,5.75,5.71,3.5 0.3,Premium,E,SI1,61.8,60,675,4.28,4.23,2.63 0.7,Very Good,F,VS2,62.9,56,2400,5.66,5.73,3.58 0.92,Very Good,D,VS1,61.9,58,7544,6.19,6.24,3.85 2.57,Premium,J,SI1,63,58,18485,8.77,8.65,5.49 2.25,Ideal,I,SI2,60.7,56,11104,8.54,8.5,5.17 0.51,Ideal,G,VVS2,61.5,57,1875,5.13,5.18,3.17 1.05,Ideal,H,SI2,61.9,56,4504,6.49,6.56,4.04 0.3,Ideal,E,VS1,62.5,56,694,4.27,4.31,2.68 1.01,Premium,J,VS2,62.4,60,3296,6.45,6.35,3.99 </pre>
D3 - To add Data Labels to a simple bar chart
I know this is easy and I saw some examples in this forum as well as other websites as well, but I simple can't figure it out. I'm new in using D3 library to generate the charts. I'm trying to learn by creating bar chart. My question is how to add the Data Labels into the chart? Below is the codes I have. then I have my JS: var chartwidth = 800; var chartheight = 600; var data = [ {"Start_Dt":"Jan 15","UnitName":"Unit 1","ProgramName":"ProgramName 1","AttendCnt":159,"NewcomerCnt":10} , {"Start_Dt":"Jan 22","UnitName":"Unit 2","ProgramName":"ProgramName 2","AttendCnt":178,"NewcomerCnt":5} , {"Start_Dt":"Feb 14","UnitName":"Unit 2","ProgramName":"ProgramName 3","AttendCnt":240,"NewcomerCnt":46} , {"Start_Dt":"Feb 19","UnitName":"Unit 1","ProgramName":"ProgramName 4","AttendCnt":201,"NewcomerCnt":10} , {"Start_Dt":"Feb 26","UnitName":"Unit 2","ProgramName":"ProgramName 5","AttendCnt":177,"NewcomerCnt":7} , {"Start_Dt":"Mar 12","UnitName":"Unit N","ProgramName":"ProgramName N","AttendCnt":184,"NewcomerCnt":3} ]; var margin = {top: 20, right: 20, bottom: 300, left: 40}, width = chartwidth - margin.left - margin.right, height = chartheight - margin.top - margin.bottom; var formatPercent = d3.format(".0%"); var formatTime = d3.time.format("%e %B"); var x = d3.scale.ordinal() .rangeRoundBands([0, width], .1); var x2 = d3.scale.ordinal() .rangeBands([0, width], 0); var y = d3.scale.linear() .range([height, 0]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left"); 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 + ")"); data.forEach(function(d) { d.AttendCnt = +d.AttendCnt; }); x.domain(data.map(function(d) { return d.Start_Dt + " " + d.ProgramName; })); y.domain([0, d3.max(data, function(d) { return d.AttendCnt; })]); //Create X Axis svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", ".15em") .attr("transform", "rotate(-65)" ) .append("text") .attr("y", 25) .attr("x",x.rangeBand()/2 ) .style("text-anchor", "middle") .style("font-size", "20px") .style("color", "black") .text(function(d,i) { return "xxx"; }); //Create Y Axis svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 0) .attr("dy", ".71em") .style("text-anchor", "end") .text("Attendance"); svg.selectAll(".bar") .data(data) .enter().append("rect") .attr("class", "bar") .attr("x", function(d) { return x(d.Start_Dt + " " + d.ProgramName); }) .attr("width", x.rangeBand()) .attr("y", function(d) { return y(d.AttendCnt); }) .attr("height", function(d) { return height - y(d.AttendCnt); }); Before After How to modify the codes to get the result I wanted? Tks
i haven't tested the code but it could be something like this : svg.selectAll(".barText") .data(data) .enter().append("text") .attr("class", "barText") .attr("x", function(d) { return x(d.Start_Dt + " " + d.ProgramName); }) .attr("y", function(d) { return height - y(d.AttendCnt); }) .text(function(d) { return d.AttendCnt; }) ; Hope it helps
D3 chart not showing up
Problem Having trouble getting my chart in D3 to show up. Getting an Uncaught SyntaxError: Unexpected end of input with my scripts.js index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="assets/css/style.css"> </head> <body> <script src="assets/js/scripts.js"></script> <script src="http://d3js.org/d3.v3.min.js"></script> </body> </html> scripts.js $(function() { var margin = {top: 20, right: 20, bottom: 30, left: 40}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var x0 = d3.scale.ordinal() .rangeRoundBands([0, width], .1); var x1 = d3.scale.ordinal(); var y = d3.scale.linear() .range([height, 0]); var color = d3.scale.ordinal() .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]); var xAxis = d3.svg.axis() .scale(x0) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left") .tickFormat(d3.format(".2s")); 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 + ")"); d3.csv("assets/data/data.csv", function(error, data) { var ageNames = d3.keys(data[0]).filter(function(key) { return key !== "State"; }); data.forEach(function(d) { d.ages = ageNames.map(function(name) { return {name: name, value: +d[name]}; }); }); x0.domain(data.map(function(d) { return d.State; })); x1.domain(ageNames).rangeRoundBands([0, x0.rangeBand()]); y.domain([0, d3.max(data, function(d) { return d3.max(d.ages, function(d) { return d.value; }); })]); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("Population"); var state = svg.selectAll(".state") .data(data) .enter().append("g") .attr("class", "g") .attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; }); state.selectAll("rect") .data(function(d) { return d.ages; }) .enter().append("rect") .attr("width", x1.rangeBand()) .attr("x", function(d) { return x1(d.name); }) .attr("y", function(d) { return y(d.value); }) .attr("height", function(d) { return height - y(d.value); }) .style("fill", function(d) { return color(d.name); }); var legend = svg.selectAll(".legend") .data(ageNames.slice().reverse()) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; }); legend.append("rect") .attr("x", width - 18) .attr("width", 18) .attr("height", 18) .style("fill", color); legend.append("text") .attr("x", width - 24) .attr("y", 9) .attr("dy", ".35em") .style("text-anchor", "end") .text(function(d) { return d; }); }); style.css body { font: 10px sans-serif; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .bar { fill: blue; } .x.axis path { display: none; }
I found that I got the same error when pasting your code directly into JSFiddle. It went away when I properly closed the main function. For reference, here's your code in live snippet form with the extra closing braces: var csvData = [ {"State":0, "Age":31, "Names":["Austin"]}, {"State":0, "Age":31, "Names":["Austin"]}, {"State":0, "Age":31, "Names":["Austin"]}, ]; $(function() { $("#placeholder").remove(); var margin = {top: 20, right: 20, bottom: 30, left: 40}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var x0 = d3.scale.ordinal() .rangeRoundBands([0, width], .1); var x1 = d3.scale.ordinal(); var y = d3.scale.linear() .range([height, 0]); var color = d3.scale.ordinal() .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]); var xAxis = d3.svg.axis() .scale(x0) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left") .tickFormat(d3.format(".2s")); 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 data = csvData; var ageNames = d3.keys(data[0]).filter(function(key) { return key !== "State"; }); data.forEach(function(d) { d.ages = ageNames.map(function(name) { return {name: name, value: +d[name]}; }); }); x0.domain(data.map(function(d) { return d.State; })); x1.domain(ageNames).rangeRoundBands([0, x0.rangeBand()]); y.domain([0, d3.max(data, function(d) { return d3.max(d.ages, function(d) { return d.value; }); })]); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("Population"); var state = svg.selectAll(".state") .data(data) .enter().append("g") .attr("class", "g") .attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; }); state.selectAll("rect") .data(function(d) { return d.ages; }) .enter().append("rect") .attr("width", x1.rangeBand()) .attr("x", function(d) { return x1(d.name); }) .attr("y", function(d) { return y(d.value); }) .attr("height", function(d) { return height - y(d.value); }) .style("fill", function(d) { return color(d.name); }); var legend = svg.selectAll(".legend") .data(ageNames.slice().reverse()) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; }); legend.append("rect") .attr("x", width - 18) .attr("width", 18) .attr("height", 18) .style("fill", color); legend.append("text") .attr("x", width - 24) .attr("y", 9) .attr("dy", ".35em") .style("text-anchor", "end") .text(function(d) { return d; }); }); body { font: 10px sans-serif; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .bar { fill: blue; } .x.axis path { display: none; } <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
On the d3.csv("csv...") call - try adding another }); to the end of it. I tried your code out on JSFiddle, and that seemed to resolve the syntax error. EDIT: My bad. Left in a hurry. Here's the fiddle: http://jsfiddle.net/strsjpxa/ I later noticed it made more sense to close the function at the end.
Hyperlink chart bars using D3
I am using the D3 toolkit to create a stacked bar graph of some data. I want link the bars to a separate page with more detail about the underlying data for that bar. I can't figure out how to turn the bars into hyperlinks. The code below is based on a demo that I have been tinkering with. When I inspect the code in Google Chrome it looks correct but the bars aren't clickable. Tremendous thanks in advance for ideas and suggestions on this! Source, attempting to add link to Google to each bar: <!DOCTYPE html> <meta charset="utf-8"> <style> body { font: 10px sans-serif; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .bar { fill: steelblue; } .x.axis path { display: none; } </style> <body> <script src="d3.min.js"></script> <script> var margin = {top: 20, right: 20, bottom: 30, left: 40}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var x = d3.scale.ordinal() .rangeRoundBands([0, width], .1); var y = d3.scale.linear() .rangeRound([height, 0]); var color = d3.scale.ordinal() .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left") .tickFormat(d3.format(".2s")); 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 + ")"); d3.csv("./data.csv", function(error, data) { color.domain(d3.keys(data[0]).filter(function(key) { return key !== "State"; })); data.forEach(function(d) { var y0 = 0; d.ages = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; }); d.total = d.ages[d.ages.length - 1].y1; }); data.sort(function(a, b) { return b.total - a.total; }); x.domain(data.map(function(d) { return d.State; })); y.domain([0, d3.max(data, function(d) { return d.total; })]); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("Population"); var state = svg.selectAll(".state") .data(data) .enter().append("g") .attr("class", "g") .attr("xlink:href", function(d) { return "http://www.google.com"; }) .attr("transform", function(d) { return "translate(" + x(d.State) + ",0)"; }); state.selectAll("rect") .data(function(d) { return d.ages; }) .enter().append("rect") .attr("width", x.rangeBand()) .attr("y", function(d) { return y(d.y1); }) .attr("height", function(d) { return y(d.y0) - y(d.y1); }) .style("fill", function(d) { return color(d.name); }); state.append("a") .attr("xlink:href", "http://www.google.com") ; var legend = svg.selectAll(".legend") .data(color.domain().slice().reverse()) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; }); legend.append("rect") .attr("x", width - 18) .attr("width", 18) .attr("height", 18) .style("fill", color); legend.append("text") .attr("x", width - 24) .attr("y", 9) .attr("dy", ".35em") .style("text-anchor", "end") .text(function(d) { return d; }); }); </script>
I'm not sure that you can add "a" html mark in SVG. But you can add an event on each bar segment: state.on('click',function(d){ ... some great code ... })
Add text on top of bar in d3js chart -- no <text> elements added
I am creating a bar chart with d3.js from data stored in tsv file. I want to insert a text in each bar. How I can do? I have tried even this solution, but doesn't work. Here is the code of my function: var margin = {top: 20, right: 20, bottom: 30, left: 40}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var formatPercent = d3.format(".0%"); var x = d3.scale.ordinal() .rangeRoundBands([0, width], .1, 1); var y = d3.scale.linear() .range([height, 0]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left"); 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 + ")"); function visualize(file){ d3.tsv(file, function(error, data) { data.forEach(function(d) { d.weight = +d.weight; }); x.domain(data.map(function(d) { return d.concept; })); y.domain([0, d3.max(data, function(d) { return d.weight; })]); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("weight"); svg.selectAll(".bar") .data(data) .enter().append("rect").style("fill", function (d){return d.color;}) .attr("class", "bar") .attr("x", function(d) { return x(d.concept); }) .attr("width", x.rangeBand()) .attr("y", function(d) { return y(d.weight); }) .attr("height", function(d) { return height - y(d.weight); }); svg.selectAll("text") .data(data) .enter() .append("text") .text(function(d) { return d.concept; }) .attr("text-anchor", "middle") .attr("x", x) .attr("y",y) .attr("font-family", "sans-serif") .attr("font-size", "11px") .attr("fill", "white"); }); } All my code with the files tsv are here: full code
AmeliaBR is right as usual, and I am only putting this answer because while I was working on it, I saw myself changing the code so that it really makes use of the Enter, Update, Exit selection paradigm. I have made quite a few changes in that regard. Here is the code, FWIW: var margin = {top: 20, right: 20, bottom: 30, left: 40}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var formatPercent = d3.format(".0%"); var x = d3.scale.ordinal() .rangeRoundBands([0, width], .1, 1); var y = d3.scale.linear() .range([height, 0]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left"); 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 + ")"); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("weight"); var g = svg.append("g"); function update(file){ d3.tsv(file, function(error, data) { data.forEach(function(d) { d.weight = +d.weight; }); x.domain(data.map(function(d) { return d.concept; })); y.domain([0, d3.max(data, function(d) { return d.weight; })]); var bar = g.selectAll(".bar") .data(data); bar.enter() .append("rect") .attr("class","bar"); bar .style("fill", function (d){return d.color;}) .attr("class", "bar") .attr("x", function(d) { return x(d.concept); }) .attr("width", x.rangeBand()) .attr("y", function(d) { return y(d.weight); }) .attr("height", function(d) { return height - y(d.weight); }); bar.exit().remove(); var text = g.selectAll(".text") .data(data); text.enter() .append("text") .attr("class","text"); text .attr("text-anchor", "right") .attr("x", function(d) { return x(d.concept); }) .attr("y", function(d) { return y(d.weight) + 22;}) .attr("font-family", "sans-serif") .attr("font-size", "11px") .attr("fill", "white") .text(function(d) { return d.concept; }); text.exit().remove(); }); } And you call it like by doing update("data16.tsv") and then update("data15.tsv").
When you draw an axis, it creates separate <text> elements for each label inside the axis group inside the SVG. So if you then try to select all the <text> elements in the SVG, you're going to select all your axis labels. If you have more axis labels than data for text elements, your enter() selection will be empty and nothing will happen. To be sure you're only selecting the correct <text> elements, give your text labels a class to distinguish them from the axis labels. And then use that class to narrow-down your selector: svg.selectAll("text.bar-label") .data(data) .enter() .append("text") .attr("class", "bar-label")