D3: Drawing a histogram + heatmap - javascript

d3 noob here.
I'd like to draw something like this:
(http://bl.ocks.org/mbostock/3883195)
But with a heat aspect, sort of like this:
Code (from above link):
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.area {
fill: steelblue;
}
</style>
<body>
<center>
<div>
<script src="http://d3js.org/d3.v3.js"></script>
<script>
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("%d-%b-%y").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 area = d3.svg.area()
.x(function(d) { return x(d.date); })
.y0(height)
.y1(function(d) { return y(d.close); });
var svg = d3.select("div").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) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.close; })]);
svg.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
// .attr("style", "stroke: #001")
.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 ($)");
});
</script>
</div>
</center>
</body>
Perhaps changing the area variable in someway? I could add another column to the data, say, color. But how would I apply the color to the "vertical line" of each day?
Thoughts? Thanks in advance!

Related

Multiple graphs on one page, scale error in D3.js

I'm newbie in D3.js. I would like to make many graphs on one page as here http://bl.ocks.org/d3noob/5987480 based on this example https://bl.ocks.org/mbostock/1166403
But I ran into a problem. The scale in the first chart is incorrect. And I just don't understand, why... How to fix this?
<!DOCTYPE html>
<meta charset="utf-8">
<style>
svg {
font: 12px Arial;
}
path.line {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
path.area {
fill: #e7e7e7;
}
.axis {
shape-rendering: crispEdges;
}
.x.axis line {
stroke: #fff;
}
.x.axis .minor {
stroke-opacity: .5;
}
.x.axis path {
display: none;
}
.y.axis line,
.y.axis path {
fill: none;
stroke: #000;
}
</style>
<body>
<div id="area1"></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 10, right: 20, bottom: 20, left: 40},
width = 300 - margin.left - margin.right,
height = 150 - margin.top - margin.bottom;
var parse = d3.time.format("%Y").parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.ticks(8)
.tickSize(-height);
var yAxis = d3.svg.axis()
.scale(y)
.ticks(4)
.orient("left");
var area = d3.svg.area()
.interpolate("monotone")
.x(function(d) { return x(d.date); })
.y0(height)
.y1(function(d) { return y(d.price); });
var line = d3.svg.line()
.interpolate("monotone")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.price); });
var svg1 = d3.select("#area1").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 + ")");
svg1.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
d3.csv("1-1.9.csv", function(error, data) {
data.forEach(function(d) {
d.date = parse(d.date);
d.close = +d.price;
});
// 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.price; })]);
area.y0(y(0));
svg1
.datum(data);
svg1.append("path")
.attr("class", "area")
.attr("clip-path", "url(#clip)")
.attr("d", area);
svg1.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg1.append("g")
.attr("class", "y axis")
.call(yAxis);
svg1.append("path")
.attr("class", "line")
.attr("clip-path", "url(#clip)")
.attr("d", line);
svg1.append("text")
.attr("x", width - 6)
.attr("y", height - 6)
.style("text-anchor", "end")
.text(data[0].symbol);
});
var svg2 = d3.select("#area1").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 + ")");
svg2.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
d3.csv("2-2.9.csv", function(error, data) {
data.forEach(function(d) {
d.date = parse(d.date);
d.close = +d.price;
});
// 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.price; })]);
area.y0(y(0));
svg2
.datum(data);
svg2.append("path")
.attr("class", "area")
.attr("clip-path", "url(#clip)")
.attr("d", area);
svg2.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg2.append("g")
.attr("class", "y axis")
.call(yAxis);
svg2.append("path")
.attr("class", "line")
.attr("clip-path", "url(#clip)")
.attr("d", line);
svg2.append("text")
.attr("x", width - 6)
.attr("y", height - 6)
.style("text-anchor", "end")
.text(data[0].symbol);
});
</script>
1-1.9.csv:
symbol,date,price
1-1.9,2003,339
1-1.9,2004,560
1-1.9,2005,792
1-1.9,2006,2579
1-1.9,2007,960
1-1.9,2008,3295
1-1.9,2009,3807
1-1.9,2010,2634
1-1.9,2011,2576
1-1.9,2012,2748
1-1.9,2013,4292
1-1.9,2014,4295
1-1.9,2015,4045
2-2.9.csv:
symbol,date,price
2-2.9,2003,1768
2-2.9,2004,1732
2-2.9,2005,1714
2-2.9,2006,2622
2-2.9,2007,2281
2-2.9,2008,3801
2-2.9,2009,3712
2-2.9,2010,3407
2-2.9,2011,3349
2-2.9,2012,3237
2-2.9,2013,5180
2-2.9,2014,3496
2-2.9,2015,3076
Your scale's domain is set to find the maximum value in the property price, not the property close. price is a string, close is an integer.
Your data array has objects such as:
{ symbol: "1-1.9", date: Date 2006-01-01T08:00:00.000Z, price: "2579", close: 2579 }
{ symbol: "1-1.9", date: Date 2007-01-01T08:00:00.000Z, price: "960", close: 960 }
Comparing price will compare strings. In javascript, strings are compared in a manner similar to alphabetical order, so the string with the highest first digit will be last (the maximum, see this answer or this one for more info on comparing strings). In your case, that is 960, as you can see if you include this line after you set the domain:
console.log(y.domain()); // [0,960]
Instead, simply change your scale's domain to:
y.domain([0, d3.max(data, function(d) { return d.close; })]);

How can i add another line to make this a multi line chart?

I have trying to add another graph line to show another set of data. I am struggling to add another line of data. the technologies i am using are, D3.js, HTML and CSS.
Could someone help me with adding another line of data into this graph please?
CSS -
<style>
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
and this is my D3.js to create the graph.
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
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("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 = 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);
</script>
Well, that would be really simple, since you already done the job. The working example is here and what I did was simply copying your pieces of code according to the new data arrData2
Given a new data:
var arrData2 = [
["2012-10-02",250],
["2012-10-09", 200],
["2012-10-12", 100]
];
You just have to adjust your data, as you did before:
var data2 = arrData2.map(function(d) {
return {
date: parseDate(d[0]),
close: d[1]
};
});
And add a new line according to data2:
svg.append("path")
.datum(data2)
.attr("class", "line")
.attr("d", line);

how to set color and grid in areaplot using d3.js?

I have the following code:
<!DOCTYPE html>
<html>
<head>
<title>areaplot</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style>
svg { border: 1px solid #dedede; }
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.area { fill: skyblue; }
</style>
</head>
<body>
<svg id="area" />
<script>
d3.csv("performance.csv", function (error, data) {
data.forEach(function (d) {
d.stocks = +d.stocks;
});
var margin = {top: 20, right: 20, bottom: 40, left: 50},
width = 575 - margin.left - margin.right,
height = 350 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([d3.min(data, function (d) {
return d.percentage;
}), d3.min(data, function (d) {
return d.percentage;
})])
.range([0, width]);
var y = d3.scale.linear()
.domain([0, d3.max(data, function (d) {
return d.stocks;
})])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var area = d3.svg.area()
.x(function (d) {
return x(d.percentage);
})
.y0(height)
.y1(function (d) {
return y(d.stocks);
});
var svg = d3.select("svg#area")
.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("path")
.datum(data)
.attr("class", "area")
.attr("d", area);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
</script>
</body>
</html>
I have to set the grid and the colors to look the same as in this picture:
My CSV file contains the following data:
stocks,percentage
400,100
300,75
200,70
100,50
75,20
How do I add the grid and set the colors using d3.
You can achieve this using linear gradient.
var gradient = d3.select("svg").append("defs")
.append("linearGradient")
.attr("id", "gradient")
.attr("spreadMethod", "pad");
//start color white
gradient.append("stop")
.attr("offset", "0%")
.attr("stop-color", "white")
.attr("stop-opacity", 1);
//end color steel blue
gradient.append("stop")
.attr("offset", "90%")
.attr("stop-color", "steelblue")
.attr("stop-opacity", 1);
On the area path:
svg.append("path")
.datum(data)
.style("fill", "url(#gradient)")//set the fill to the gradient id created above.
.attr("d", area);
Working code here

Insert minutes and hour on d3.js timeseries plot

I'm using this snippet to understand how d3.js works.
I changed this line of code -> var parseDate = d3.time.format('%H-%M-%e-%b-%y').parse;
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 1000 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var parseDate = d3.time.format('%H-%M-%e-%b-%y').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("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.tsv("data/plottingData/first.tsv", function(error, data) {
if (error) throw error;
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
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)
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
});
</script>
because the file is formatted in this way:
11-30-1-May-12 582.13
10-30-1-Apr-12 382.13
9-30-1-Mar-12 482.13
...
but I'm continuing to view only day-month into x-Axis.
what's wrong?
thanks in advance.
You are parsing the date in correct format, but on X-axis you did not provide the format, on which you want to show date. So just use "xAxis.tickFormat(parseDate)" in your code. Example is here:
d3.svg.axis()
.scale(x)
.orient("bottom").tickFormat(d3.time.format('%H-%M-%e-%b-%y'));

d3 dynamic data in bar graph

i am using the d3 for making the bar graph . From example i see that they use the tsv file for the data . In my case i have the dynamic data . Here is the code and i want to use the var data1 to make the graph
<!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>
<div id="bar"></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>
var $window = $(window);
var wWidth = $window.width();
var wHeight = $window.height();
var margin = {top: 10, right: 0, bottom: 30, left: 40},
width = 300 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
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")
.tickFormat(formatPercent);
//var data = [[1,1],[2,3],[3,2],[4,5],[5,4]];
var svg = d3.select("#bar").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 data1 = [
{letter:"A",frequency:"58.13"},
{letter:"B",frequency:"53.98"},
{letter:"C",frequency:"67.00"},
{letter:"D",frequency:"89.70"},
{letter:"E",frequency:"99.00"}
];
d3.tsv("data.tsv", type, function(error, data) {
x.domain(data.map(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>
data.tsv
letter frequency
A .08167
B .01492
C .02780
D .04253
E .12702
F .02288
G .02022
H .06094
I .06973
J .00153
Change the variable name,
data1 To data
And remove these line
1. d3.tsv("data.tsv", type, function(error, data) {
2. });
See DEMO Here

Categories

Resources