I have unable draw for the line graph in the d3.js,i wrote some code but enable show the graph,how to draw a line for the given data.I have a problem for the how to parse the data for the given data and draw a lines ffor the given data of code.
var data=[{"key":[2000,1,1,12],"value":1000},{"key":[2000,2,1,12],"value":38965},
[{"key":[2000,7,1,24],"value":289},{"key":[2000,8,1,24],"value":389}
]
var parseDate = d3.time.format("%Y.%m.%d.%H").parse;
var map=data.map(function (d){
return {
key:parseDate((d.key[0])+"."+(d.key[1]+1)+"."+(d.key[2])+"."+(d.key[3]+1)),value:+d.value
}
});
console.log(map);
var margin = {top: 15, right: 20, bottom: 70, left: 85},
width = 440,height = 450;
var x = d3.time.scale().range([0, width]);
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 line = d3.svg.line()
.x(function(d) { return x(d.key); })
.y(function(d) { return y(d.value); })
.interpolate("cardinal")
var svg = d3.select("body").select("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
x.domain(d3.extent(d3.map(function (d){return d.key;})));
y.domain(d3.extent(d3.map(function (d){return d.key;})));
svg.append("g")
.attr("class", "x axis x-axis")
.attr("transform", "translate(0," + height + ")").attr("fill","steelblue")
.call(xAxis);
svg.append("g").attr("class", "y axis y-axis").attr("fill","steelblue").call(yAxis)
svg.append("path").datum(map).attr("class", "line").attr("d", line);
There seem to be a number of problems with the above code including an extra [ in the data, which should be:
var data=[
{"key":[2000,1,1,12],"value":1000},
{"key":[2000,2,1,12],"value":38965},
{"key":[2000,7,1,24],"value":289},
{"key":[2000,8,1,24],"value":389}
]
Other than that, the way you parse the data seems fine, but there are some issues with the way you set up the chart.
I've created a new line chart using your data here: http://jsfiddle.net/henbox/9etp0xap/, based on this example: http://bl.ocks.org/mbostock/3883245
You'll probably find it easier to modify that jsfiddle rather than to debug the specific issues.
Related
I'm new to D3.js and am trying to build a very-wide line chart that pans horizontally to show more data from a .csv file. I haven't been able to find many good resources for the latest version of D3.
What I'm trying to achieve:
chart fills the screen with overflow hidden
drag/mousewheel reveals more data from the right
axis labels stay put (but x-axis changes to reflect new data)
no zooming
The code I have right now renders the chart, and it can be clicked and dragged, but the whole thing just moves off the screen... Here's the code:
var margin = {top: 50, right: 50, bottom: 50, left: 50},
width = window.innerWidth - margin.left - margin.right,
height = window.innerHeight - margin.top - margin.bottom;
var x = d3.scaleLinear().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var line = d3.line()
.x(function(d) { return x(d.mile); })
.y(function(d) { return y(d.elevation); })
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.call(d3.zoom().on("zoom", function () {
svg.attr("transform", d3.event.transform)
}))
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
function draw(data) {
data.forEach(function(d) {
d.mile = +d.mile;
d.elevation = +d.elevation;
});
x.domain(d3.extent(data, function(d) { return d.mile }) )
y.domain([0, d3.max(data, function(d) {
return Math.max(d.elevation) }) ]);
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", line)
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
svg.append("g")
.call(d3.axisLeft(y));
}
d3.json("data.json", function(error, data) {
if (error) throw error;
draw(data)
});
And here's a sample of what the data looks like:
mile,elevation
1505.9,1800
1506.4,1360
1507.0,1340
1507.9,1750
1509.7,2365
Thanks in advance for any resources anyone can offer me to help solve this!
I've been looking around a while for an answer to this, and I haven't been able to figure it out.
I'm ultimately creating a TopoJSON file from grid based data (GRIB files).
I can pretty easily interpolate the data down to a finer resolution grid so the plot points appear smoother when zoomed out, but when zoomed in, it's inevitable to see the blocky grid points.
I've also looked into simplification, which does help a bit but its not quite smoothing.
I'm using D3 to render the data.
Is this something that can be done on the front end or should/can it be done in the raw TopoJSON data?
I essentially don't want you to be able to tell that it's a grid, even if you zoom in 10,000%.
Here's an example of what I'm after:
Is this something that can be done on the front end or should/can it be done in the raw TopoJSON data?
This is something that should be done on the front end. If you were to smooth the data before you wrote it to the JSON file, the file would be needlessly big.
If you're using D3.js, and you're working with lines, the built-in interpolate() function is the way to go.
Here is a working example of D3's line.interpolate() using "cardinal" smoothing:
http://codepen.io/gracefulcode/pen/doPmOK
Here's the code:
var margin = {
top: 30,
right: 20,
bottom: 30,
left: 50
},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%d-%b-%y").parse;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y).orient("left").ticks(5);
// Define the line
var valueline = d3.svg.line()
.interpolate("cardinal")
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.close);
});
// Adds the svg canvas
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 + ")");
// Get the data
d3.json('https://api.myjson.com/bins/175jl', function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
// Scale the range of the data
// Starting with a basic graph 14
x.domain(d3.extent(data, function(d) {
return d.date;
}));
y.domain([0, d3.max(data, function(d) {
return d.close;
})]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
Maybe d3 line.interpolate() is what you're looking for?
More info:
http://www.d3noob.org/2013/01/smoothing-out-lines-in-d3js.html
I am trying to create a line graph using D3. The data for the graph is stored in an XML file like this:
XML Code:
<record>
<date_value>1376092800000</date_value>
</record>
JavaScript Code:
var record=xmlDoc.getElementsByTagName("record");
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%d-%b-%y").parse;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
// Adds the svg canvas
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 + ")");
// Get the data
d3.xml("values.xml", "application/xml", function(data) {
for(var d = 0; d < record.length; d++){
d.date = parseDate(record[d].getElementsByTagName("date_value")[0].childNodes[0].nodeValue);
d.close += 1;
};
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.close; })]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
I'm having trouble with the part where I get the data. The x value is the date value and the y value should be increased by one each time. With the current code I have no errors, but only the y axis is showing with no data. I would appreciate any suggestions. Thanks!
I am trying to draw a simple line chart in D3. I am able to draw the data line with a linear scale on the Y-axis (ignore the fact that there are no ticks):
Here is the code and a relevant JSFiddle for this:
var margin = { top: 10, right: 245, bottom: 30, left: 100 },
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// Set the X and Y scale (e.g., linear vs. log) and the domains
var x = d3.scale.linear().domain([-95,-74]).range([0, width]);
// ******* CHANGE linear() to log() *************************** //
var y = d3.scale.linear().domain([0.000010,1]).range([height, 0]);
// Set the locations of the axis (e.g., bottom and left)
var xAxis = d3.svg.axis().scale(x).orient("bottom");
var yAxis = d3.svg.axis().scale(y).orient("left").ticks(0, ".1");;
// Set up some lines and related colors
var color = d3.scale.category10();
var line = d3.svg.line().x(function (d) { return x(d.power); }).y(function (d) { return y(d.ber); });
// Set the graph to be drawn in the respective div (grapharea), and set dimensions
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 + ")");
// Append the X and Y axis to the actual SVG graph
svg.append("g").attr("class", "y axis").call(yAxis);
svg.append("g").attr("class", "x axis").attr("transform", "translate(0," + height + ")").call(xAxis);
// Parse the JSON data response
var jsonString = '[{"power":-91.0,"ber":0.0},{"power":-92.0,"ber":0.0},{"power":-93.0,"ber":1E-07},{"power":-94.0,"ber":6.5E-06},{"power":-95.0,"ber":0.000147}]';
var jsonData = JSON.parse(jsonString);
jsonData.forEach(function (d) {
d.ber = d.ber;
d.power = d.power;
});
// Set the data properly
x.domain(d3.extent(jsonData, function(d) { return d.power; }));
y.domain(d3.extent(jsonData, function(d) { return d.ber; }));
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("BER");
svg.append("path")
.datum(jsonData)
.attr("class", "line")
.attr("d", line);
If all I change is linear() to log() on the variable y, then I get a resulting log scale graph but my data line no longer shows up (relevant JSFiddle):
Does anyone know what I am doing wrong for the data line to not show up on the log scale graph?
You have zeros in your data. The log of zero is not defined. You'll need to use a different type of scale.
I'd like to plot a multi line graph with d3.js.
I have following data, which I get from a database and convert to JSON.
{"items":["itemID01","itemID12","itemID14","itemID15","itemID16"],
"alpha":{
"xvalue":["itemID03","itemID12","itemID14","itemID16"],
"yvalue":[0,0,0,0]},
"beta":{
"xvalue":["itemID03","itemID12","itemID16"],
"yvalue":[0,2,0]},
"gamma":{
"xvalue":["itemID03","itemID12","itemID14","itemID16"],
"yvalue":[9,10,8,9]},
"delta":{
"xvalue":["itemID12","itemID14","itemID16"],
"yvalue":[2,0,2]},
"epsilon":{
"xvalue":["itemID12"],
"yvalue":[3]}}
I got it to work with one line. When I adjusted it to multiple lines, it doesn't show any lines at all. The code is based on this tutorial by d3noob http://www.d3noob.org/2013/01/adding-more-than-one-line-to-graph-in.html
This is my javascript code:
var margin = {top: 20, right: 80, bottom: 30, left: 50},
width = 500 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangePoints([0, width]);
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 + ")");
// get the JSON data
d3.json("getdata.php", function(error, data) {
//console.log(data);
x.domain(data.items);
y.domain([0, d3.max(d3.values(data.gamma.yvalue))]);
// hardcoded for now, use d3.max(data, function(d) { return Math.max(d.alpha.yvalue, d.beta.yvalue, ...); })
// get the array keys
var keys = [];
for (var key in data){
if (data.hasOwnProperty(key) && key !== 'items') {
keys.push(key);
}
}
//console.log(keys);
var valueline = [];
var i = 0;
keys.forEach(function(k) {
valueline[i] = d3.svg.line()
//.defined(function(d) { return (d.xvalue !== null); })
.x(function(d) { return x(d.xvalue); })
.y(function(d) { return y(d.yvalue); });
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline[i](data[k]));
//console.log(data[k]);
i++;
});
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(-10,0)")
.call(yAxis);
});
I set up a jsfiddle with the code http://jsfiddle.net/5PcPU/
I tried different variations of having svg.append("path") in and out of the foreach loop and just one valueline element or an array. But nothing worked so far
My guess is that the error is close to those lines
.x(function(d) { return x(d.xvalue); })
.y(function(d) { return y(d.yvalue); });
since if I try to do this, I don't get any output
.x(function(d) {
console.log('test');
console.log(d.xvalue);
return x(d.xvalue); })
I could make it work by rearranging the json data. If I use an array of x AND y values instead of one array for the x values and another one for the y values, it plots like I expect it to.
So the data looks like this:
{"items":["itemID01","itemID12","itemID14","itemID15","itemID16"],
"alpha":[{"x":"itemID03","y":0},
{"x":"itemID12","y":0},
{"x":"itemID14","y":0},
{"x":"itemID16","y":0}],
"beta":[{"x":"itemID03","y":0},
{"x":"itemID12","y":2},
{"x":"itemID16","y":0}],
"gamma":[{"x":"itemID03","y":9},
{"x":"itemID12","y":10},
{"x":"itemID14","y":8},
{"x":"itemID16","y":9}],
"delta":[{"x":"itemID12","y":2},
{"x":"itemID14","y":0},
{"x":"itemID16","y":2}],
"epsilon":[{"x":"itemID12","y":3}]}