I am trying to create a d3 chart with logarithmic scale(1,10,100..). I used their functions and call but not much help.
var x = d3.scale.log()
.domain([1,10])
.range([0, width]);
var y = d3.scale.log()
.domain([1,10])
.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 line = d3.svg.line()
.x(function(d) { return x(d[xAxxis]); })
.y(function(d) { return y(d[yAxxis]); });
var svg = d3.select("#"+this.divid).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 + ")");
x.domain(d3.extent(totalArray, function(d) { return d[xAxxis]; })).nice();
y.domain(d3.extent(totalArray, function(d) { return d[yAxxis]; })).nice();
Is there any way i can create the axis with 1e+0,10e+0,100e+0 rather than 1e+0,2e+0,3e+0
You can control which labels the axis renders using either the tick() or tickValues() method, depending on how you want to go about it. See the d3's API documentation for more details. Also, note that a log scale's tick() method takes no arguments, so you'll likely have to use tickValues() though the other method might come in handy for formatting.
Related
I'm trying to make a scatterplot that appears below an interactive worldmap with the help of D3. The scatterplot contains data from the country that the user clicked on in the worldmap. The problem is that when the user clicks on another country, the scatterplot of the previous country should disappear. This is not the case unfortunately, the second scatterplot just appears under the first scatterplot. Does anyone know how I can fix this? Any help would be greatly appreciated.
A part of the code I use for the scatterplot:
function ScatterCorruption(dataset, title){
var xValue = function(d) { return d.GDP;}
var yValue = function(d) { return d.Variable;}
// determine parameters
var margin = {top: 20, right: 20, bottom: 200, left: 70},
width = 600 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// formatters for axis and labels
var currencyFormat = d3.format("0.2f");
var decimalFormat = d3.format("0.2f");
// determine x scale
var x = d3.scale.linear()
.range([0, width]);
// determine y scale
var y = d3.scale.linear()
.range([height, 0]);
// determine x-axis
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
// determine y-axis
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
// make svg
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 + ")");
// add the tooltip area to the webpage
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
console.log(dataset)
// load in data
d3.tsv(dataset, function(error, data) {
if (error) throw error;
// convert data
data.forEach(function(d) {
d.GDP = +d.GDP;
d.Variable = +d.Variable;
});
You'll need to call this before rendering a new scatterplot: d3.selectAll("svg > *").remove(); so that your svg is clear again. Alternatively you can also do d3.select("svg").remove(); and then recreate the svg.
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.
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}]}
I have a current zoom function I just learned to use in D3. However when I use it, it only moves my and zooms the axis of the graph not the objects on it.
I'm very knew to D3 and would like some help please.
My source code of the javascript is posted below:
//Setting generic width and height values for our SVG.
var margin = {top: 60, right: 0, bottom: 60, left: 40},
width = 1024 - 70 - margin.left - margin.right,
height = 668 - margin.top - margin.bottom;
//Other variable declarations.
//Creating scales used to scale everything to the size of the SVG.
var xScale = d3.scale.linear()
.domain([0, 1024])
.range([0, width]);
var yScale = d3.scale.linear()
.domain([1, 768])
.range([height, 0]);
//Creates an xAxis variable that can be used in our SVG.
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
//Zoom command ...
var zoom = d3.behavior.zoom()
.x(xScale)
.y(yScale)
.scaleExtent([1, 10])
.on("zoom", zoomed);
// The mark '#' indicates an ID. IF '#' isn't included argument expected is a tag such as "svg" or "p" etc..
var SVG = d3.select("#mainSVG")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
//Create background. The mouse must be over an object on the graph for the zoom to work. The rectangle will cover the entire graph.
var rect = SVG.append("rect")
.attr("width", width)
.attr("height", height);
//This selects 4 circles (non-existent, there requires data-binding) and appends them all below enter.
//The amount of numbers in data is the amount of circles to be appended in the enter() section.
var circle = SVG
.selectAll("circle")
.data([40,100,400,1900])
.enter()
.append("circle")
.attr("cx",function(d){return xScale(d)})
.attr("cy",function(d){return xScale(d)})
.attr("r",20);
//This appends a circles to our SVG.
var circle = SVG
.append("circle")
.attr("cx",function(d){ return xScale(d)})
.attr("cy",300)
.attr("r",20);
//Showing the axis that we created earlier in the script for both X and Y.
var xAxisGroup = SVG.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
var yAxisGroup = SVG.append("g")
.attr("class", "y axis")
.call(yAxis);
function zoomed() {
SVG.select(".x.axis").call(xAxis);
SVG.select(".y.axis").call(yAxis);
}
You also need to redraw all the elements with the changed axes on zoom -- D3 won't do this for you automatically:
function zoomed() {
SVG.select(".x.axis").call(xAxis);
SVG.select(".y.axis").call(yAxis);
SVG.selectAll("circle")
.attr("cx",function(d){return xScale(d)})
.attr("cy",function(d){return xScale(d)});
}
I'm playing again with d3.js the javascript library. I am able to create a chart with 2 numeric axes but now I want to have one numeric axis and one axis with a date. Unfortunately I'm not able to do this.
First of all, thats the code that is not running:
d3.json('builds.json',
function(data){
var format = d3.time.format("%Y-%m-%d");
data.forEach(function(d) {
d.finished_at = format.parse(d.finished_at);
});
var margin = {top: 40, right: 40, bottom: 40, left: 40},
width = 960,
height = 500;
var x = d3.time.scale()
.domain(d3.extent(data, function(d) { return d.finished_at; }))
.range([0, width - margin.right - margin.left]);
var y = d3.scale.linear()
.domain(d3.extent(data, function(d) { return d.result; }))
.range([height - margin.top - margin.bottom, 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)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("cx", function(d) { return x(d.finished_at); })
.attr("cy", function(d) { return y(d.result); })
.attr("r", 6);
svg.append("g") // Render the axis by calling a <g> selection.
.attr("transform", "translate(0," + y.range()[0] + ")") //setzt x-achse an null punkt von y-achse
.call(xAxis);
svg.append("g")
.call(yAxis);
});
The variable finished_at looks like this: "finished_at":"2011-11-20" and I tried to parse it.
But the output is the following:
Can anybody please help me?
The problem likely lies with your data. You will need to confirm that all of the finished_at values in your JSON are in the correct format.
Your code appears to work perfectly well with a small working JSON dataset: http://bl.ocks.org/4162693