Fail to load tsv for d3.js bar chart - javascript

I'm using d3.js for charting, I'm getting this error while I want to load custom data from local system.
Failed to load file:///C:/Users/foo/Desktop/d3/barChart/data.tsv:
Cross origin requests are only supported for protocol schemes: http,
data, chrome, chrome-extension, https.
Inside d3 folder there is the index.html and the data.tsv.
I have installed WAMP Server and it's active.
Update
index.html
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.bar {
fill: steelblue;
}
.bar:hover {
fill: brown;
}
.axis--x path {
display: none;
}
</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 30, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
y = d3.scaleLinear().rangeRound([height, 0]);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.tsv("data.tsv", function(d) {
d.frequency = +d.frequency;
return d;
}, function(error, data) {
if (error) throw error;
x.domain(data.map(function(d) { return d.letter; }));
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).ticks(10, "%"))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Frequency");
g.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.letter); })
.attr("y", function(d) { return y(d.frequency); })
.attr("width", x.bandwidth())
.attr("height", function(d) { return height - y(d.frequency); });
});
</script>
data.tsv
letter frequency
A .08167
B .01492
C .02782
D .04253

Related

how to connect d3.js and solr json response?

<!DOCTYPE html>
<meta charset="utf-8">
<head>
<style>
.axis {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<!--/* adding d3.js lib*/-->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="https://d3js.org/d3-dsv.v1.min.js"></script>
<script src="https://d3js.org/d3-fetch.v1.min.js"></script>
<script>
var margin = { top: 20, right: 20, bottom: 70, left: 40 },
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.num);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10);
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 + ")");
/* my data on json server
d3.json("https://api.myjson.com/bins/xya14", function (error, data)
{
alert(data);
data.forEach(function (d) {
d.num = d.num;
d.value = +d.value;
alert(d.value);
});
x.domain(data.map(function (d) { return d.num; }));
y.domain([0, d3.max(data, function (d) { return d.value; })]);
*/
/* data on solr server*/
d3.json("http://192.168.2.4:8983/solr/vkash_collection/select?q=*:*&omitHeader=true", function (error, data)
{
alert(data);
data.forEach(function (d) {
d.num = d.num;
d.value = +d.value;
alert(d.value);
});
x.domain(data.map(function (d) { return d.num; }));
y.domain([0, d3.max(data, function (d) { return d.value; })]);
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", "-.55em")
.attr("transform", "rotate(-90)");
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("Value ($)");
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.style("fill", "steelblue")
.attr("x", function (d) { return x(d.num); })
.attr("width", x.rangeBand())
.attr("y", function (d) { return y(d.value); })
.attr("height", function (d) { return height - y(d.value); });
});
</script>
</body>
I load one json file in solr which is have only two fields num and value.i take this url and use d3.json("solr url",function (data))..but I get nothing on the browser. how to connect d3.js ??
my js code snippet is here:
my solr url response is here:

How to animate a d3 js v4 bar chart from bottom(x axis) to up?

Currently, this d3 js bar chart animates from top to bottom. Most likely its because of the way d3js renders its chart which starts from the top. This might be a common issue and might be easy for those who are familiar with the nuisance of d3js, how can I make this animate from bottom to top?
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.bar {
fill: steelblue;
}
.bar:hover {
fill: brown;
}
.axis--x path {
display: none;
}
</style>
<svg width="1260" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 30, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleBand().rangeRound([0, width]).padding(0.4),
y = d3.scaleLinear().rangeRound([height, 0]);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("MRT_MonthlyAve_2014.csv", function(d) {
d.MonthlyAverage = +d.MonthlyAverage;
return d;
}, function(error, data) {
if (error) throw error;
x.domain(data.map(function(d) { return d.Station; }));
y.domain([0, d3.max(data, function(d) { return d.MonthlyAverage; })]);
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).ticks(12, "s"))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Frequency");
g.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.Station); })
.attr("y", function(d) { return y(d.MonthlyAverage); })
.transition().duration(1000)
.ease(d3.easeExp)
.attr("width", x.bandwidth())
.attr("height", function(d) { return height - y(d.MonthlyAverage); });
});
</script>
MRT_MonthlyAve_2014.csv
Station,MonthlyAverage
North Avenue,2227081
Quezon Avenue,1018121
GMA,606110
Cubao,1410788
Santolan,260737
Ortigas,561910
Shaw Boulevard,1339020
Boni,631115
Guadalupe,1002740
Buendia,421302
Ayala,1145004
Magallanes,933713
Taft Avenue,2427220
Just set the initial y position to height:
.attr("y", height)
Here is your code with that change only (I'm reducing the height of the SVG, so you can see it working in the small snippet view):
var csv = `Station,MonthlyAverage
North Avenue,2227081
Quezon Avenue,1018121
GMA,606110
Cubao,1410788
Santolan,260737
Ortigas,561910
Shaw Boulevard,1339020
Boni,631115
Guadalupe,1002740
Buendia,421302
Ayala,1145004
Magallanes,933713
Taft Avenue,2427220`;
var svg = d3.select("svg"),
margin = {
top: 20,
right: 20,
bottom: 30,
left: 40
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleBand().rangeRound([0, width]).padding(0.4),
y = d3.scaleLinear().rangeRound([height, 0]);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var data = d3.csvParse(csv, function(d) {
d.MonthlyAverage = +d.MonthlyAverage;
return d;
})
x.domain(data.map(function(d) {
return d.Station;
}));
y.domain([0, d3.max(data, function(d) {
return d.MonthlyAverage;
})]);
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).ticks(12, "s"))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Frequency");
g.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.Station);
})
.attr("y", height)
.transition().duration(1000)
.ease(d3.easeExp)
.attr("y", function(d) {
return y(d.MonthlyAverage);
})
.attr("width", x.bandwidth())
.attr("height", function(d) {
return height - y(d.MonthlyAverage);
});
.bar {
fill: steelblue;
}
.bar:hover {
fill: brown;
}
.axis--x path {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="1260" height="200"></svg>

Cannot read property 'getHours' of undefined

I am trying to build a simple bar chart with some financial data in json format.
I am having this strange error popup when I try to use my parsed time. When I console log it shows the data to be parsed ok - it doesn't return null or anything.
d3.v3.min.js:1 Uncaught TypeError: Cannot read property 'getHours' of undefined
at H (d3.v3.min.js:1)
at SVGTextElement.t (d3.v3.min.js:1)
at SVGTextElement.arguments.length.each.function.n.textContent (d3.v3.min.js:3)
at d3.v3.min.js:3
at Y (d3.v3.min.js:1)
at Array.Co.each (d3.v3.min.js:3)
at Array.Co.text (d3.v3.min.js:3)
at SVGGElement.<anonymous> (d3.v3.min.js:5)
at d3.v3.min.js:3
at Y (d3.v3.min.js:1)
Its hard to troubleshoot this as I cannot understand which part of my code is responsible for causing this problem because it points toward d3.v3.min.js. I assume that the problem is in d3.extent as I used it to replace d3.max for the x-axis.
This is the code that gives the error:
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<style>
.axis {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 70, left: 40},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%H:%M:%S.%L").parse;
var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.time.format("%H:%M:%S.%L"));
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10);
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.json("https://gist.githubusercontent.com/kvyb/cba0e652b7fd9349604cf45ced75fbf9/raw/3f824e76c38479a1a327abbb5c85a5962fec6f21/schudata.json", function(error, data) {
data["bboList"].forEach(function(d) {
d.timeStr = parseDate(d.timeStr);
d.value = +d.ask;
console.log(d.timeStr)
});
x.domain(d3.extent(data, function(d) { return d.timeStr; }));
y.domain([0, d3.max(data, function(d) { return d.value; })]);
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", "-.55em")
.attr("transform", "rotate(-90)" );
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("Value ($)");
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.style("fill", "steelblue")
.attr("x", function(d) { return x(d.timeStr); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
});
</script>
</body>
P.S.
There is another issue which is outside the bounds of this question, but needs to be included.
In order to get the bars to render also replaced
var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);
with
var x = d3.time.scale().range([0, width]);
and changing the width for the bars to a fixed value.
I assume that the problem is in d3.extent...
Yes, you are correct, and the explanation is simple: d3.extent accepts an array as the first argument. However, your data is not an array, but an object with two properties (each one having one array).
Thus, you should select one of them to set your domains (and your bar's data as well):
x.domain(d3.extent(data["bboList"], function(d) {
return d.timeStr;
}));
y.domain([0, d3.max(data["bboList"], function(d) {
return d.value;
})]);
Here is your working code:
var margin = {top: 20, right: 20, bottom: 70, left: 40},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%H:%M:%S.%L").parse;
var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.time.format("%H:%M:%S.%L"));
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10);
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.json("https://gist.githubusercontent.com/kvyb/cba0e652b7fd9349604cf45ced75fbf9/raw/3f824e76c38479a1a327abbb5c85a5962fec6f21/schudata.json", function(error, data) {
data["bboList"].forEach(function(d) {
d.timeStr = parseDate(d.timeStr);
d.value = +d.ask;
});
x.domain(d3.extent(data["bboList"], function(d) { return d.timeStr; }));
y.domain([0, d3.max(data["bboList"], function(d) { return d.value; })]);
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", "-.55em")
.attr("transform", "rotate(-90)" );
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("Value ($)");
svg.selectAll("bar")
.data(data["bboList"])
.enter().append("rect")
.style("fill", "steelblue")
.attr("x", function(d) { return x(d.timeStr); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
});
path, line {
fill: none;
stroke: black;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
PS: Have in mind that I'm only answering your question ("Cannot read property 'getHours' of undefined"). You still have some problems drawing those bars.

Can't decrease number of ticks in axisBottom

I'm trying to create some bar chart with the U.S. GDP growth. In the x axis, all the YYYY-MM-DD values are shown even though I explicitly set .call(d3.axisBottom(x).ticks(10); What should I do? I tried it with d3.timeYear.every(25) too.
Here's my code:
var url = "https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json";
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 30, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
y = d3.scaleLinear().rangeRound([height, 0]);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json(url, function(error, data) {
if (error) throw error;
x.domain(data.data.map(function(d) { return d[0]; }));
y.domain([0, d3.max(data.data, function(d) { return d[1]; })]);
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(d3.timeYear.every(25)));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).ticks(10))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("font-size", "30px")
.attr("font-color", "black")
.attr("dy", "7.71em")
.attr("text-anchor", "end")
.text("Frequency");
g.selectAll(".bar")
.data(data.data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d[0]); })
.attr("y", function(d) { return y(d[1]); })
.attr("width", x.bandwidth())
.attr("height", function(d) { return height - y(d[1]); });
});
You have two problems here. First, you are using a band scale, and d3.timeYear.every(25) will have no effect. But, on top on that, you're using that d3.timeYear.every(25) inside a ticks function, and that won't work.
According to the API:
This method has no effect if the scale does not implement scale.ticks, as with band and point scales. (emphasis mine)
Thus, a possible solution is filtering the band scale's domain inside a tickValues function.
In this example, I'm filtering one tick out of every 20. Also, I'm splitting the string to show only the year:
d3.axisBottom(x).tickValues(x.domain().filter(function(d, i) {
return !(i % 20);
})).tickFormat(function(d) {
return d.split("-")[0]
});
Here is your code with that change:
var url = "https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json";
var svg = d3.select("svg"),
margin = {
top: 20,
right: 10,
bottom: 30,
left: 50
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleBand().range([0, width]).padding(0.1),
y = d3.scaleLinear().rangeRound([height, 0]);
d3.json(url, function(error, data) {
if (error) throw error;
x.domain(data.data.map(function(d) {
return d[0];
}));
y.domain([0, d3.max(data.data, function(d) {
return d[1];
})]);
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickValues(x.domain().filter(function(d, i) {
return !(i % 20);
})).tickFormat(function(d) {
return d.split("-")[0]
}))
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).ticks(10))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("font-size", "30px")
.attr("font-color", "black")
.attr("dy", "7.71em")
.attr("text-anchor", "end")
.text("Frequency");
g.selectAll(".bar")
.data(data.data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d[0]);
})
.attr("y", function(d) {
return y(d[1]);
})
.attr("width", x.bandwidth())
.attr("height", function(d) {
return height - y(d[1]);
});
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="600" height="400"></svg>

JavaScript , D3 bar graph error

This is the script/html i am not sure what the problem here is the error I keep arriving at is. I messed around with the y and heigh variables but i am unable to get to a solution. Changed the parameters, changed values but of no avail. Please assist.
Error: Invalid value for attribute y="NaN"
Error: Invalid value for attribute height="NaN"
This is the ERRORS
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.bar {
fill: steelblue;
}
.bar:hover {
fill: brown;
}
.axis {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
</style>
<body>
<script src="//d3js.org/d3.v3.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()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(1)
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(1.0);
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("Unemployment.csv", type, function(error, data) {
if (error) throw error;
x.domain([0, d3.max(data, function(d) { return d.letter; })]);
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
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("Frequency");
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.letter); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.frequency); })
.attr("height", function(d) { return height - y(d.frequency); });
});
function type(d) {
d.frequency = +d.frequency;
return d;
}
</script>
Ward,Unemployment
1,4.5
2,4.3
3,4.0
4,5.7
5,7.9
6,5.2
7,11.0
8,14.2
If you log your data after the d3.csv("Unemployment.csv", type, function(error, data) { call you would see that it will contain an array of object with the keys Ward and Unemployment.
However, in several cases such as:
x.domain([0, d3.max(data, function(d) { return d.letter; })]);
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
And
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.letter); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.frequency); })
.attr("height", function(d) { return height - y(d.frequency); });
your code expects the letter and frequency keys to be present.
Changing these to ward and unemployment would solve this issue

Categories