So I'm using d3, v4. Trying to graph multiple lines individually, by date (x) and value (y). The problem is I cannot parse the date after doing it once for the first line. What can I do differently (for the first function in particular) to make it work for both?
Here is the code pen for the entire project (where I've included multiple arrays of data, but am only in the process of graphing the first two. Sorry for the messiness. The lines below can be found starting line 314)
Important pieces:
function type(data) {
data[0].forEach(function(d) {
d.inspected_at = parseTime(d.inspected_at);
console.log(d)
return d;
})
};
// define the line
var line1 = d3.line()
.x(function(d) { return x(d.inspected_at); })
.y(function(d) { return y(d.flow_data);});
var line2 = d3.line()
.x(function(d) { return x(d.inspected_at); })
.y(function(d) { return y(d.flow_data);});
// Add the line path(s)
//line CB-01
svg.append('g')
.attr('clip-path', 'url(#clipper)')
.selectAll('path#line').data([data[0]])
.enter().append("path")
.attr("class", "line")
.attr("id", "downstreamLine")
.attr("d", line1)
.attr("stroke", "blue");
//line CB-02
svg.append('g')
.attr('clip-path', 'url(#clipper)')
.selectAll('path#line').data([data[1]])
.enter().append("path")
.attr("class", "line")
// .attr("id", "downstreamLine")
.attr("d", line2)
.attr("stroke", "green");
Here is what my data looks like:
var data = [{"id":"CB-01","inspected_at":"2018-04-08T12:44:30.000Z","flow_data":"4"},
{"id":"CB-01","inspected_at":"2018-04-08T12:44:30.000Z","flow_data":"5"},
{"id":"CB-01","inspected_at":"2018-04-08T12:54:36.000Z","flow_data":"4"},
{"id":"CB-01","inspected_at":"2018-04-08T12:54:36.000Z","flow_data":"7"},
{"id":"CB-01","inspected_at":"2018-04-08T12:54:36.000Z","flow_data":"2"},
{"id":"CB-01","inspected_at":"2018-04-08T13:04:42.000Z","flow_data":"3"},
{"id":"CB-01","inspected_at":"2018-04-08T13:04:42.000Z","flow_data":"9"}],
[{"id":"CB-02","inspected_at":"2018-04-08T12:44:30.000Z","flow_data":"3"},
{"id":"CB-02","inspected_at":"2018-04-08T12:44:30.000Z","flow_data":"2"},
{"id":"CB-02","inspected_at":"2018-04-08T12:54:36.000Z","flow_data":"3"},
{"id":"CB-02","inspected_at":"2018-04-08T12:54:36.000Z","flow_data":"5"},
{"id":"CB-02","inspected_at":"2018-04-08T12:54:36.000Z","flow_data":"6"},
{"id":"CB-02","inspected_at":"2018-04-08T13:04:42.000Z","flow_data":"8"},
{"id":"CB-02","inspected_at":"2018-04-08T13:04:42.000Z","flow_data":"7"}]
The first array being one line, the second array is the next.
Thanks in advance! Let me know if I can provide any more info.
This should work for any amount of lines, iterate every line array and do the same process for each point in that line array:
function type(data) {
data.forEach(arr => arr.forEach(d => d.inspected_at = parseTime(d.inspected_at)))
};
Related
I searched for this and found a lot of info on how to set scales, but I'm trying to color individual SVGs created in D3 using values from a column that's populated with hex values. In the code below "Color1" is the column populated with different hex color values, e.g., #000000;
Here's what I've tried that makes intuitive sense to me but isn't working, instead the chart populates with the fill as black:
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx',function (d) { return xScale(d.xvalue) })
.attr('cy',function (d) { return yScale(d.yvalue) })
.attr('r','3')
.attr('stroke','black')
.attr('stroke-width',1)
.attr('fill', function (d) {return d.Color1})
I've also tried surrounding the function with "'" but was unsuccessful.
The color property should not include a semicolon:
var data = [
{Color1: "#aaaaaa;"},
{Color1: "#aaaaaa"}
]
var svg = d3.select("body").append("svg");
var circles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx',(d,i)=>i*100+50)
.attr('cy', 100)
.attr('r','10')
.attr('stroke','black')
.attr('stroke-width',1)
.attr('fill', function(d) { return d.Color1; })
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
You could just slice the last character off if you have the semicolon hard coded in your data:
.attr("fill", function(d) { return d.Color1.slice(0,-1); })
There seems to be a bug in my d3 (version 4) code and I can't quite figure out why my line won't draw. My axes are there but my line path won't compute. I thought it was an issue with my data types (right now they're all numbers) But I must be missing something. Can you help me find what it is?
Here is the codepen
Here are some key parts:
var line = d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.ratio); });
g.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", line);
Structuring my data:
var baseValue = +data[0].avg_water_temp;
data.forEach(function(d) {
d.date = d.date;
d.ratio = +(d.avg_water_temp /baseValue);
});
Just an fyi, The y axis is actually a distance from a base Value, not distance from 0. So my ratios (y values) will be percentages.
Like This(without the log scale)
Thanks!! Let me know if there's anything I can clarify.
I'm trying to draw a line graph in D3, with a transition based on a click. I can do it the long way round, describing each line as it goes, but I wanted to simplify the code using a key. I got the idea from D3 tips and tricks
Drawing the lines is fine, but transitioning to the second set of data is proving difficult - all the lines just converge to one. That line would be where the fifth line ought to be.
Here's the relevant bit of code - first defining the scales and he two sets of lines
/ Set the ranges
var x = d3.scale.linear().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the lines
var line1 = d3.svg.line()
.x(function(d) { return x(d.year); })
.y(function(d) { return y(d.data1); });
var line2 = d3.svg.line()
.x(function(d) { return x(d.year); })
.y(function(d) { return y(d.data2); });
Then getting the data, and nesting it, then setting up the key, based on the "symbol" column in the data (the data is all here, it's a bit boring to type out http://www.graphitti.org/admin2/files/experiments/lines_exp_data.tsv)
// Get the data
d3.tsv("lines_exp_data.tsv", function(error, data) {
data.forEach(function(d) {
d.year = +d.year;
d.data1 = +d.data1;
d.data2 = +d.data2;
d.data3 = +d.data3;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.year; }));
y.domain([80, d3.max(data, function(d) { return d.data1, d.data2; })]);
// Nest the entries by symbol
var dataNest = d3.nest()
.key(function(d) {return d.symbol;})
.entries(data);
// Loop through each symbol / key
dataNest.forEach(function(d) {
graph.append("path")
.attr("class", "line")
.attr("id", "lines")
.attr("d", line1(d.values));
});
This all works fine. Then I want to change them based on the click, so I do this
d3.select("#clickone")
.on("click", function() {
dataNest.forEach(function(d) {
graph.selectAll("#lines")
.transition()
.duration(1000)
.attr("d", line2(d.values));
;})
;})
And what happens then is that all the lines collapse to one line. You can see it all here http://www.graphitti.org/admin2/files/experiments/lines_exp_03.html
Is there a way of doing this? I've seen other questions on SO that suggest it can't be done (e.g. d3.js: Is it possible to line transition by key instead of index?) but I wasn't sure, as the circumstances were different. Sorry if this is a repeat
So I have one view that creates paths and I'm trying to have it so that each line that I draw has a random color.
I'm currently doing this-
var color = d3.scale.category20();
//other code that does stuff
this.path = svg.append("path")
.attr("d", line(newData))
.style("stroke", function(d,i) {
var colorIndex = Math.random() * (20 - 0) + 0;
return color(colorIndex); })
.attr("fill","none")
.attr("class","line");
This does not draw lines with different colours. Further, when I do this
this.path = svg.append("path")
.attr("d", line(newData))
.style("stroke", function(d,i) {
return color(4); })
.attr("fill","none")
.attr("class","line");
The color is still blue.
Why is that happening?
This is happening because domain was not set -
d3.scale.category10() not behaving as expected
has the answer
I have set up a minimal fiddle to show you the proper way to set up the line function. I also changed the color scheme to category(10) to show more contrasting colors (you can still use category20 and see a difference in colors though). Here is the FIDDLE.
var lineFunction = d3.svg.line()
.x(function (d) {
return d.x;
})
.y(function (d) {
return d.y;
})
.interpolate("linear");
I am trying to use D3 to render lines, but when I try to do this, the lines get rendered as polygons. I am not sure why. I included a screenshot to show you what it looks like.
Here is the code:
// Creates a time scale using the x_extent
// defined above
var x_scale = d3.time.scale()
.range([margin, width - margin])
.domain(x_extent);
// Creates a similarity scale using the y_extent.
// defined above.
var y_scale = d3.scale.linear()
.range([height - margin, margin])
.domain(y_extent);
// Construct a line.
var line = d3.svg.line()
.x(function(d) {
return x_scale(d.date);
})
.y(function(d) {
return y_scale(d.similarity);
});
// Render a line.
d3.select("svg")
.append("path")
.attr("d", line(data));
Try setting fill and stroke explicitly when appending the path, i.e.
d3.select("svg")
.append("path")
.attr("fill", "none")
.attr("stroke", "black")
.attr("d", line(data));