I'm trying to make a scatter plot with two sets of data from two tsv files. However, each one shares the x-axis with single scale. There are two y-axis each with their own scale. The graph I have right now will help visually.
Problem is, the 2nd data set (in orange) only plots partially as seen as a smudge at about 15,000 on the a-axis. it should really be a much larger line. Also, when I run this, sometimes the 2nd data set renders and the first does now. Not sure why this is happening..
Here are the two (likely) relevant blocks of code:
//1st data set
d3.tsv("datatest4.tsv", function(error, tsv1) {
tsv1.forEach(function(d) {
d.altit = +d.altit;
d.tmp = +d.tmp;
});
x.domain(d3.extent(tsv1, function(d) { return d.altit; })).nice();
y.domain(d3.extent(tsv1, function(d) { return d.tmp; })).nice();
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("Altitude (m)");
svg.append("g")
.attr("class", "y axis axis1")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end");
svg.selectAll(".dot")
.data(tsv1)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 1)
.attr("cx", function(d) { return x(d.altit); })
.attr("cy", function(d) { return y(d.tmp); })
.style("fill","steelblue");
});
and
//2nd data set
d3.tsv("datatest2.tsv", function(error, tsv2) {
tsv2.forEach(function(dd) {
dd.alti = +dd.alti;
dd.pressure = +dd.pressure;
});
x2.domain(d3.extent(tsv2, function(dd) { return dd.alti; })).nice();
y2.domain(d3.extent(tsv2, function(dd) { return dd.pressure; })).nice();
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis2)
.attr("x", width)
.attr("y", -6)
.text("Altitude (m)");
svg.append("g")
.attr("class", "y axis axis2")
.call(yAxis2)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end");
svg.selectAll(".dot")
.data(tsv2)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 1)
.attr("cx", function(dd) { return x2(dd.alti); })
.attr("cy", function(dd) { return y2(dd.pressure); })
.style("fill","orange");
});
The problem is that you're using the same selector, svg.selectAll(".dot"), for each dataset .data(tsv1) and .data(tsv2).
D3 thinks that the 2nd set is supposed to replace the first. You can fix it by assigning a unique class to each type of dot.
svg.selectAll(".blue.dot")// Select specifically blue dots
.data(tsv1)
.enter().append("circle")
.attr("class", "blue dot")// Assign two classes
...
svg.selectAll(".orange.dot")
.data(tsv2)
.enter().append("circle")
.attr("class", "orange dot")
...
Related
I want to append x-axis text label and rotate the x axis labels.
Both works individually but I cant figure out how to use them both together.Can someone please help.
g.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text") // either this
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".1em")
.attr("transform", "rotate(-65)")
.append("text")// or this
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.style("font-weight", "bold")
.style("fill", "black")
.text(tooltipTxt);
I have this code and I can't seem to create labels for the axes. I've tried copying what other scripts do but my knowledge of D3 is pretty lacking.
In particulare I was trying to merge this code with what I have to disasterous results:
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("Temperature (ºF)");
And what I have:
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("transform", "translate(" + width + ",0)")
.attr("y", -5)
.style("text-anchor", "end")
.text("Frequency");
Here is the bl.ocks.org link
And here is the gist
Your label is here in the DOM at the position you specified. You just need to style it to make it visible:
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("fill", "black") // <= Here
.attr("transform", "translate(" + width + ",0)")
.attr("y", -5)
.style("text-anchor", "end")
.text("Frequency");
Or simply use CSS:
.label {
fill: black;
}
I what to use a couple of the techanJS examples in my application but am struggling use my own data.
Here is the example code for the close chart which I want to use.
I have a play! framework application which passes in a List[CloseList] array, this is then converted to a JSON object using:
var closesJSON = #{Html(new Gson().toJson(closes))};
I am then assuming that I will be able to replace d3.csv() with d3.json() but cannot find a working example and my hacking hasn't got me anywhere so far.
d3.csv("data.csv", function(error, data) {
var accessor = close.accessor();
data = data.slice(0, 200).map(function(d) {
return {
date: parseDate(d.Date),
open: +d.Open,
high: +d.High,
low: +d.Low,
close: +d.Close,
volume: +d.Volume
};
}).sort(function(a, b) { return d3.ascending(accessor.d(a), accessor.d(b)); });
x.domain(data.map(accessor.d));
y.domain(techan.scale.plot.ohlc(data, accessor).domain());
svg.append("g")
.datum(data)
.attr("class", "close")
.call(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 ($)");
});
Working code here, this renders:
d3.json("/api/closedata/#equity.getId", function(error, data) {
var accessor = close.accessor();
data = data.map(function(d,i) {
console.log(d.high);
return {
date : parseDate(d.closeDate),
open : d.openPrice,
high : d.high,
low : d.low,
close : d.closePrice,
volume : d.volume
}
}).sort(function(a, b) { return d3.ascending(accessor.d(a), accessor.d(b)); });
x.domain(data.map(accessor.d));
y.domain(techan.scale.plot.ohlc(data, accessor).domain());
svg.append("g")
.datum(data)
.attr("class", "close")
.call(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 ($)");
});
I you can stock your data in a json file, you have just to use the function
d3.json("file.json",callback);
after, you have to change the name of the attributes in the code (the attirbutes on his csv are probably differents to your attributes in json)
callback, is usually a function but i don't think you have any other change to do in your code.
Verify your json (use a website like http://jsonprettyprint.com/), test the code on your computer (http://bl.ocks.org/andredumas/af8674d57980790137a0) with the default csv to see if it's work. It it's work, change to use json (like i told you).
I have created one drop down(Account_type) in that drop down the value coming from database.
ie:value1,value 2,value3...
on the basis of selecting value i want to update my chart .But in my current scenario it will be creating a another chart instead of updating same..Again Again it will creating separate chart
My code here
var svg = d3.select("#"+this.htmlObject).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 + ")");data.forEach(function(d) {
d.frequency = +d.frequency;
});
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", -75)
.attr("dy", ".71em")
.attr("dx","-18em")
.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); });
Could you please tell me How i can achieved this.
Remove previous svg element and create new svg element for other value.
I'm confused about how to save a D3 selection for later use. In the code below, I have a "global" variable for my axes, to which I save them when they are first created. Later, I'm able to use this variable for certain things (here, setting some text) but not others (here, updating the scale), which only work if I explicitly (re)select the axes.
Is there perhaps something about JavaScript variable scoping or lifetime that I don't understand? Any assistance is appreciated!
The relevant code, much condensed from the full context:
// Top level of page
var gxaxis, gyaxis;
var updatePlot = function (view, first) {
d3.csv("data.csv", function (error, data) {
data.forEach(function (d) {
...
});
var x, y;
x = d3.scale.linear().range(...);
y = d3.scale.linear().range(...);
x.domain(d3.extent(data, function (d) {...})).nice();
y.domain(d3.extent(data, function (d) {...})).nice();
var xAxis = d3.svg.axis().scale(x).orient("bottom");
var yAxis = d3.svg.axis().scale(y).orient("left");
// The variable 'first' is true on page load, so this code the if clause will be executed before any executions of the else clause
if (first) {
gxaxis = svg.append("g").attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end");
gyaxis = svg.append("g").attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end");
} else {
// Why is it necessary to explicitly select; why can't I use my gxaxis variable (as I do below for the text)?
svg.select(".x.axis")
.transition().duration(0).ease("in")
.call(xAxis);
// Using gyaxis.transition()... has NO EFFECT
svg.select(".y.axis")
.transition().duration(0).ease("in")
.call(yAxis);
}
var xLabel = ...;
var yLabel = ...;
// This use of gxaxis works.
gxaxis.text(xLabel);
gyaxis.text(yLabel);
});
};
// Set up handlers for switching among views
d3.selectAll(".view-select").on("click", function () {
d3.event.preventDefault();
updatePlot(this.id, false);
});
updatePlot('a', true);
This code:
gxaxis = svg.append("g").attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end");
Creates this DOM:
<svg>
<...>
<g class="x axis">
<g class="tick">
<line ...>
<text ...>
</g>
</g>
</...>
</svg>
And saves the text to the selection, because it was appended last.
If you want the axis, save the axis to the selection before you edit the text.
gxaxis = svg.append("g").attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
gxaxis.selectAll("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end");