I have a big problem.
I use d3 to visualize my (poll)data. (So Questions and answers) It works fine except one problem.
Sometimes it doesn't visualize the data like they are. For example one time d3 get all right data about d3.json. But the graph is not right. It should load 300 answers in the first bars but it just show 50. I tested it and the json works.
I tried to filter the graph and I got the same problem.
This is my d3 code.
<div>
<script src="http://d3js.org/d3.v3.js"></script>
<script>
var margin = {
top: 20,
right: 30,
bottom: 30,
left: 430
},
width = 1400 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var xScale = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var yScale = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(yScale)
.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)
.attr("class", "chart");
var chart = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json("getdata.php", function(error, data) {
xScale.domain(data.map(function(d) {
return d.text;
}));
yScale.domain([0, d3.max(data, function(d) {
return d.count;
})]);
chart.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return xScale(d.text);
})
.attr("y", function(d) {
return yScale(d.count);
})
.attr("height", function(d) {
return height - yScale(d.count);
})
.attr("width", xScale.rangeBand())
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
chart.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("Antworten");
});
function type(d) {
d.count = +d.text;
return d;
}
</script>
</div>
I guess the problem starts here. But I don't know why. The problem doesn't appear at every question. Only at a few or when I try to use my filter.
Maybe it happens when two values have a big difference?
Update:
It is like: D3 doesn't want to lose the smallest bar. So other bars must based on that smallest. And then the values are not correct for the bigger bars. Maybe the Y scale depends on the smallest bar.
Related
I´m using d3.js library but i´m having so problems with linear graphics. It looks like on each page refresh, the graphics is replicated, and after some running time i got lots of duplicated graphics. I´m also using static data (i entered some random data for the graphic to work). Can someone help me? Why is this happening? Any solutions?
chart3-controller.js
module.exports = function Chart3Ctrl($scope) {
d3 = require('d3')
$scope.chart = function() {
var arrData = [
["2012-10-02", 200],
["2012-10-09", 300],
["2012-10-12", 150]
];
var margin = {
top: 20,
right: 20,
bottom: 30,
left: 50
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y-%m-%d").parse;
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.date);
})
.y(function(d) {
return y(d.close);
});
var svg = d3.select("#chart3").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 = arrData.map(function(d) {
return {
date: parseDate(d[0]),
close: d[1]
};
});
console.log(data);
x.domain(d3.extent(data, function(d) {
return d.date;
}));
y.domain(d3.extent(data, function(d) {
return d.close;
}));
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("Price ($)");
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
}
}
chart3.pug
.widget-container.fluid-height.stf-cpu(ng-controller='Chart3Ctrl')
.heading
i.fa
span(translate) Chart 3
.widget-content.padded
div#chart3(style='width:100%; height:100%;')
{{ chart() }}
Please any help welcome! :)
Thanx
Have you tried to remove the chart at the top of the function?
so;
d3.selectAll('#chart3 svg').remove();
this would remove any instance of the chart before re drawing, a better approach might be to wrap inside an if statement to check if the svg exists first and then drawing it if it doesn't, using jquery this could be ;
if(!$('#chart3 svg').length > 0) {
run code here...
}
I looking any chart library which has configuration for custom y-axis values. I want to customize the y-axis like ( 0 to 3). I seen D3 and other chart libraries, the Y-axis automatically generates the values. I my design there is only one filed and on one for compare on the x-axis.
Which chart library is most suited for this condition to make this happen. If any example already on google, please share...
If you are looking for a D3 solution then you can refer my fiddle below:
http://jsfiddle.net/cyril123/7ftuumv4/2/
code:
var margin = {
top: 20,
right: 20,
bottom: 30,
left: 40
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
//specify data here
data = [{letter: "1", value: 1.3}]
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");
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 + ")");
//as you have a fixed x axis value and single data
x.domain([data[0].letter]);
//as you have a fixed range for y axis
y.domain([0, 3]);
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("Value");
//make the bar chart
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.value); })
.attr("height", function(d) { return height - y(d.value); });
I am creating a bar chart using d3. To do so I looked at this code and changed it a little bit.
However what it does is centering the bars, and I would like the bars to start immediate at the bar y axis.
It looks like the issue comes from these 2 pieces of code:
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .0);
and the last line of this one:
svg.selectAll(".bar")
.data(graphObj)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.step); })
where the x(d.step) is responsible for the distance, the x is set at the var x = ...
Somehow I need to change this, but cant figure it out.
The distance is a bit different since I changed this:
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
to this:
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .0);
but it doesn't help much.
Can you help out here?
This is my code:
$('#chartDiv').html('');
var margin = {top: 10, right: 10, bottom: 35, left: 50},
width = 600 - margin.left - margin.right,
height = 250 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([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")
.ticks(10, "");
var svg = d3.select("#chartDiv").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 + ")");
graphObj.forEach(function(d) {
d.step = +d.step;
d.temp = +d.temp;
});
x.domain(graphObj.map(function(d) { return d.step; }));
y.domain([0, d3.max(graphObj, function(d) { return d.temp; })]);
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", "-40px")
.style("text-anchor", "end")
.text("Temperature");
svg.selectAll(".bar")
.data(graphObj)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { console.log(d.step, x.rangeBand(), x(d.step)); return x(d.step); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.temp); })
.attr("height", function(d) { return height - y(d.temp); });
if ($('#chartDiv').css('left').replace('px','') < 0) {
$('#chartDiv').animate({
left: 10
}, 1000);
}
you need to add the i variable to the .attr("x", function(d) { return x(d.step); }), like so: .attr("x", function(d, i) { return x.rangeRoundBands() * i; }), so it will go through the bars and place them one after the other (this might need some tweaking, can't do it properly without a jsfiddle) but should at least get you on the path of fixing it without issues
I am trying to plot a bar chart by taking two columns from my database and converting it to JSON using json_encode in PHP (probc.php file)
I referred to this example here to construct a bar chart - BAR CHART EXAMPLE
After doing so, I changed the attributes letters and frequency to the column names I wanted to use (fphour for x-axis and fpprob for y-axis), and also changed d3.tsv to d3.json and included the relevant file (probc.php). But I do not get any results on running my file. Just a blank vanilla page. Please help!
Here's the code
<script src="http://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");
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("probc.php", type, function(error, data) {
x.domain(data.map(function(d) { return d.fphour; }));
y.domain([0, d3.max(data, function(d) { return d.fpprob; })]);
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.fphour); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.fpprob); })
.attr("height", function(d) { return height - y(d.fpprob); });
});
function type(d) {
d.fpprob = +d.fpprob;
return d;
}
</script>
Type should not be here .
d3.json("probc.php", ***type***, function(error, data) {
Remove type
d3.json("probc.php", function(error, data) {
I have a variable called final csv which looks like and is stored in a CSV format. The lines are separated by a \n. I'm using the statement D3.csv.parse. Can anyone tell me why nothing appears on the page at all? :-
String, Float
value, 1
value2, 2
function generateGraph(finalcsv)
{
var finaldata = finalcsv;
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")
.tickFormat(formatPercent);
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 + ")");
console.log(finaldata);
d3.csv.parse(finaldata, function(error, data) {
data.forEach(function(d) {
d.Float = +d.Float;
});
x.domain(data.map(function(d) { return d.String; }));
y.domain([0, d3.max(data, function(d) { return d.Float; })]);
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("Integer");
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.String); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.Float); })
.attr("height", function(d) { return height - y(d.Float); });
});
}
I quickly built an example which seems to work (or at least it shows something): http://jsfiddle.net/frXRW/2/
The first difference with the code you provided is that I didn't use the d3.csv.parse() function , I don't know if your problem comes from there but I suggest you take a look at the documentation if your problem comes from there: https://github.com/mbostock/d3/wiki/CSV
The second thing I changed, and that I suspect is the source of your problem, is that you forgot to put the #body identifier between "", so it is considered as an object. Thus I just changed the following line:
var svg = d3.select(#body).append("svg")
to
var svg = d3.select("#body").append("svg")
If this was your problem, then I would recommend you to use the chrome javascript console as it gave the following error pointing exactly to the line above:
Uncaught SyntaxError: Unexpected identifier