Group line plotting in D3 with d3.group - javascript

I am working with a tidy-long data structure with three columns: date, ID, num_orders.
date ID num_orders
"2018-08-22" 1 3
"2018-08-23" 7 1
"2018-08-23" 10 1
"2018-08-23" 17 1
"2018-08-23" 19 1
.
.
.
I would like to plot a line for each ID with date and num_orders as the x- and y-axis respectively, using D3.js. I am using this as a model for what I am doing, but in that code, the author is using the nest() function, which is no longer used in v6 of D3; the method used now is group(). So my code now is:
const margin = { top: 10, right: 30, bottom: 30, left: 60 };
const width = 1000 - margin.left - margin.right;
const height = 600 - margin.top - margin.bottom;
const svg = d3.select('#my_dataviz')
.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("./data.json")
.then( function(data) {
const grouped_data = d3.group(data, d => d.ID);
parseDate = d3.timeParse('%Y-%m-%d')
const xScale = d3.scaleTime()
.domain(d3.extent(data, d => parseDate(d.date)))
.range([0, width]);
svg.append('g')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(xScale));
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.num_orders)])
.range([height, 0]);
svg.append('g')
.call(d3.axisLeft(yScale));
const myColor = d3.scaleOrdinal()
.domain(grouped_data.keys())
.range(d3.schemeSet3);
svg.selectAll('.line')
.data(grouped_data)
.enter()
.append('path')
.attr('fill', 'none')
.attr('stroke', d => myColor(d.keys))
.attr('stroke-width', 1.5)
.attr('d', function(d){
return d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.num_orders))
(d.values);
});
} )
So far I can get the axis with tick-marks to show up, but none of the lines are showing up, which makes me think the problem is in the final svg.selectAll('.line') statement. I'm pretty new to D3, so any guidance on this problem is appreciated. (And if you have any overall suggestions for my code, I also welcome this.)

d3.line() is accepting arrays only, while d.values() is an iterator.
By converting it into an array the problem is solved.
Notice that, on the snippet I removed the parseDate because I am generating data as Dates.
You most likely will need to keep the parseDate
const margin = { top: 10, right: 30, bottom: 30, left: 60 };
const width = 1000 - margin.left - margin.right;
const height = 600 - margin.top - margin.bottom;
var x = d3.timeDays(new Date(2020, 06, 01), new Date(2020, 10, 30));
var y = Array.from({length: x.length}, Math.random).map(n => Math.floor(n * 10) + 5);
var data = x.map((v, i) => {
return {
"date": v,
"id": Math.floor(Math.random() * (10 + 1)),
"num_orders": y[i]
};
});
const svg = d3.select('#my_dataviz')
.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})`);
const grouped_data = d3.group(data, d => d.id);
parseDate = d3.timeParse('%Y-%m-%d');
const xScale = d3.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([0, width]);
svg.append('g')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(xScale));
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.num_orders)])
.range([height, 0]);
svg.append('g')
.call(d3.axisLeft(yScale));
const myColor = d3.scaleOrdinal()
.domain(grouped_data.keys())
.range(d3.schemeSet3);
const line = d3.line()
.x(d => { return xScale(d.date); })
.y(d => yScale(d.num_orders));
svg.selectAll('.line')
.data(grouped_data)
.enter()
.append('path')
.attr('fill', 'none')
.attr('stroke', d => myColor(d[0]))
.attr('stroke-width', 1.5)
.attr('d', (d) => line(Array.from(d.values())[1]));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.5.0/d3.min.js"></script>
<div id="my_dataviz"></div>

Try to parse the data on the line generator
const margin = { top: 10, right: 30, bottom: 30, left: 60 };
const width = 1000 - margin.left - margin.right;
const height = 600 - margin.top - margin.bottom;
const svg = d3.select('#my_dataviz')
.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("./data.json")
.then( function(data) {
const grouped_data = d3.group(data, d => d.ID);
parseDate = d3.timeParse('%Y-%m-%d')
const xScale = d3.scaleTime()
.domain(d3.extent(data, d => parseDate(d.date)))
.range([0, width]);
svg.append('g')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(xScale));
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.num_orders)])
.range([height, 0]);
svg.append('g')
.call(d3.axisLeft(yScale));
const myColor = d3.scaleOrdinal()
.domain(grouped_data.keys())
.range(d3.schemeSet3);
svg.selectAll('.line')
.data(grouped_data)
.enter()
.append('path')
.attr('fill', 'none')
.attr('stroke', d => myColor(d.keys))
.attr('stroke-width', 1.5)
.attr('d', function(d){
return d3.line()
.x(d => xScale(parseData(d.date)))
.y(d => yScale(d.num_orders))
(d.values);
});
} )

Related

Line Chart path in D3 JS not displaying Properly

I am trying to implement a line chart through this function. when I try to add the path, the path alone is not getting displayed. any help would be appreciated. (last 10 lines of the code add the path to the graph)
function drawLineChart(country) {
console.log(countryValueMap[country])
var margin = {top: 60, right: 110, bottom: 50, left: 50},
width = 800 - margin.left - margin.right + 50,
height = 500 - margin.top - margin.bottom + 50;
// document.getElementById("my_dataviz").innerHTML = "";
const lineSvg = d3.select("#linechart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
const x = d3.scaleTime()
.range([0 , width])
.domain([new Date(1958,0,1), new Date(2011,0,1)])
lineSvg.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x).ticks(5).tickFormat(d => d.getFullYear()))
const y = d3.scaleLinear()
.domain([0,countryMaxValueMap[country]])
.range([height, 0])
lineSvg.append("g")
.call(d3.axisRight(y).tickSize(width)).call(g => g.select(".domain")
.remove())
.call(g => g.selectAll(".tick:not(:first-of-type) line")
.attr("stroke-opacity", 0.5)
.attr("stroke-dasharray", "2,2"))
.call(g => g.selectAll(".tick text")
.attr("x", 4)
.attr("dy", -4));
lineSvg.append("path")
.datum(countryValueMap[country])
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d) { return x(d.year) })
.y(function(d) { return y(d.gdp) })
)
}
When I try to execute the above code, this is the output I am getting.
I tried logging the value of d3.year and d3.gdp and the variable works fine.
Given that the line is at 1970 (the start of epoch time), it looks like something is wrong with the how the years are represented in your data. Since you are using a scaleTime, d.year must be a date object. It can't just be an integer representing the year.

How to structure Vue for Interactive D3 Chart

In this Vue component, am trying to create an interactive bar chart hover is seems to be recreating the group element every time the data is updated. If someone can tell me where the problem is because am stuck since I've tried both the general update pattern as well as nest updated pattern.
export default {
name: "StatisticsUI",
props:["reps"],
mounted(){
this.setOptions(),
this.genChart()
},
updated(){
this.genChart()
},
methods:{
......
genChart(){
const data = [
["CCP",2],
["ZPA",1],
["ERA",3],
["POS",4],
]
const svg = d3.select("svg")
const width = svg.attr("width")
const height = svg.attr("height")
const margin ={left: 50, right:50, top:50, bottom:50}
const innerWidth = width - margin.left - margin.right
const innerHeight = height - margin.top - margin.bottom
const g = svg.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
const yAxis = g.append("g").attr("class", "y-axis")
const xAxis = g.append("g").attr("class", "x-axis")
const xValue = d => d[0]
const yValue = d => d[1]
const xScale = d3.scaleBand().domain(data.map(xValue)).range([0, innerWidth]).padding(0.2);
const yScale = d3.scaleLinear().domain([0, d3.max(data, yValue)]).range([innerHeight, 0]);
yAxis.call(d3.axisLeft(yScale));
xAxis
.call(d3.axisBottom(xScale))
.attr("transform", `translate(0, ${innerHeight})`)
let rect = g.selectAll("rect").data(data);
rect.exit().remove()
rect
.enter()
.append("rect")
.merge(rect)
.attr("fill", "#69b3a2")
.attr("x", (d) => xScale(xValue(d)))
.attr("width", xScale.bandwidth())
.attr("height", 0)
.attr("y", innerHeight)
.transition()
.duration(1000)
.delay((d, i) => i * 50)
.ease(d3.easeBounce)
.attr("y", (d) => yScale(yValue(d)))
.attr("height", function (d) {
return innerHeight - yScale(yValue(d));
});
}
}
}

Line Graph D3.js Error : <path> attribute d: Expected number, "MNaN,289.8LNaN,27…"

LineGraph is not plotted only the axis are shown.
Error shown is : d3.v4.min.js:2 Error: attribute d: Expected number, "MNaN,289.8LNaN,27…".
The time is in Unix code maybe that's causing the error.
The file shows X-axis with time and Y-axis with temperature.
I have tried converting unix to a timestamp, but I need it in minutes/seconds.
The javascript Part :
const xValue = d => new Date(d.timestamp * 1000);
const xLabel = 'Time';
const yValue = d => d.temprature;
const yLabel = 'Temperature';
const margin = { left: 120, right: 30, top: 20, bottom: 120 };
const svg = d3.select('svg');
const width = svg.attr('width');
const height = svg.attr('height');
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const g = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
const xAxisG = g.append('g')
.attr('transform', `translate(0, ${innerHeight})`);
const yAxisG = g.append('g');
xAxisG.append('text')
.attr('class', 'axis-label')
.attr('x', innerWidth / 2)
.attr('y', 100)
.text(xLabel);
yAxisG.append('text')
.attr('class', 'axis-label')
.attr('x', -innerHeight / 2)
.attr('y', -60)
.attr('transform', `rotate(-90)`)
.style('text-anchor', 'middle')
.text(yLabel);
const xScale = d3.scaleTime();
const yScale = d3.scaleLinear();
const xAxis = d3.axisBottom()
.scale(xScale)
.tickPadding(15)
.ticks(5)
.tickSize(-innerHeight);
const yTicks = 5;
const yAxis = d3.axisLeft()
.scale(yScale)
.ticks(yTicks)
.tickPadding(15)
.tickSize(-innerWidth);
const line = d3.line()
.x(d => xScale(xValue(d)))
.y(d => yScale(yValue(d)))
.curve(d3.curveBasis);
const row = d => {
d.timestamp = new Date(d.timestamp * 1000);
d.temprature = +d.temprature;
return d;
};
d3.csv('http://localhost:8000/result.csv', row, data => {
xScale
.domain(d3.extent(data, xValue))
.range([0, innerWidth]);
yScale
.domain(d3.extent(data, yValue))
.range([innerHeight, 0])
.nice(yTicks);
g.append('path')
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('stroke-width', 4)
.attr('d', line(data));
xAxisG.call(xAxis);
yAxisG.call(yAxis);
});
The CSV file :
temprature,time
22.34,1553974814384
24.77,1554453925188
25.09,1554455725250
25.73,1554457525395

How to align x axis with bars respectively in Combo Chart (Bars and Lines)?

I have a combo/ bars & lines chart based on D3.js. The x axis domain contains min and max dates, and bars are based on values. But the last bar (rect) is outside the chart. I can bring it in by forcing it (manually) but it won't reflect the data.
var data = [
{
fcst_valid_local: "2018-11-13T14:00:00-0600",
pop: 20,
rh: 67,
temp: 38,
wspd: 7
},
{
fcst_valid_local: "2018-11-14T15:00:00-0600",
pop: 15,
rh: 50,
temp: 39,
wspd: 8
},
{
fcst_valid_local: "2018-11-15T16:00:00-0600",
pop: 10,
rh: 90,
temp: 40,
wspd: 9
}
];
// Margins, width and height.
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 500 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
// Date parsing.
const parseDate = d3.timeParse("%Y-%m-%dT%H:%M:%S%Z");
data.forEach(function (d) {
d.date = parseDate(d.fcst_valid_local);
});
// Set scale domains.
var x = d3.scaleTime().range([0, width])
.domain(d3.extent(data, function (d) {
return d.date;
}));
var y0 = d3.scaleLinear().range([height, 0]).domain([0, 100]);
const y1 = d3.scaleLinear()
.range([height, 0])
.domain([0, d3.max(data, (d) => d.pop)]);
// Construct our SVG object.
const svg = d3.select('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append('g').attr('class', 'container')
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Set x, y-left and y-right axis.
var xAxis = d3.axisBottom(x)
.ticks(d3.timeDay.every(1))
// .tickFormat(d3.timeFormat('%b %d, %H:%M'))
.tickSize(0).tickPadding(10);
var y0Axis = d3.axisLeft(y0)
.ticks(5).tickSize(0);
var y1Axis = d3.axisRight(y1).ticks(5).tickSize(0);
svg.append("g")
.attr("class", "x-axis axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y-axis axis")
.attr("transform", "translate(" + 0 + ", 0)")
.call(y0Axis);
svg.append("g")
.attr("class", "y-axis axis")
.attr("transform", "translate(" + width + ", 0)")
.call(y1Axis);
// Draw bars.
var bars = svg.selectAll(".precips")
.data(data);
bars.exit().remove();
bars.enter().append("rect")
.attr("class", "precip")
.attr("width", width / data.length - 50)
.attr("x", function (d) {
return x(d.date);
})
.attr("y", height)
.transition().duration(1000)
.attr("y", function (d) {
return y0(d.pop);
})
.attr("height", function (d) {
return height - y0(d.pop);
});
const lineRH = d3.line()
.x((d) => x(d['date']))
.y(d => y0(d['rh']));
svg.append('path')
.datum(data)
.attr('class', 'line')
.attr('fill', 'none')
.attr('stroke', 'red')
.attr('stroke-linejoin', 'round')
.attr('stroke-linecap', 'round')
.attr('stroke-width', 1.5)
.attr('d', lineRH);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>
Although an answer has been accepted, I'd like to let you know that you don't have to manipulate the data (as it might be fetched from an API as well) but you can play around the x.domain() as it's all about setting the right domain here.
Try using d3 time_nice to round off the time scale domains
Play around with d3 time methods to change the dates (there are a lot here)
Here's an example of using the second approach from above and setting the x domain:
var x = d3.scaleTime().range([0, width])
.domain([d3.min(data, function (d) {
return d.date;
}), d3.timeDay.offset(d3.max(data, function (d) { return d.date; }), 1)]);
Explanation: This is offsetting the max date from the data by 1 day and so the new x.domain() would come out as:
(2) [Tue Nov 13 2018 15:00:00 GMT-0500 (Eastern Standard Time), Fri Nov 16 2018 17:00:00 GMT-0500 (Eastern Standard Time)]
which results in a chart as follows:
var data = [
{
fcst_valid_local: "2018-11-13T14:00:00-0600",
pop: 20,
rh: 67,
temp: 38,
wspd: 7
},
{
fcst_valid_local: "2018-11-14T15:00:00-0600",
pop: 15,
rh: 50,
temp: 39,
wspd: 8
},
{
fcst_valid_local: "2018-11-15T16:00:00-0600",
pop: 10,
rh: 90,
temp: 40,
wspd: 9
}
];
// Margins, width and height.
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 500 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
// Date parsing.
const parseDate = d3.timeParse("%Y-%m-%dT%H:%M:%S%Z");
data.forEach(function (d) {
d.date = parseDate(d.fcst_valid_local);
});
// Set scale domains.
var x = d3.scaleTime().range([0, width])
.domain([d3.min(data, function (d) {
return d.date;
}), d3.timeDay.offset(d3.max(data, function (d) { return d.date; }), 1)]);
var y0 = d3.scaleLinear().range([height, 0]).domain([0, 100]);
const y1 = d3.scaleLinear()
.range([height, 0])
.domain([0, d3.max(data, (d) => d.pop)]);
//console.log(x.domain());
// Construct our SVG object.
const svg = d3.select('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append('g').attr('class', 'container')
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Set x, y-left and y-right axis.
var xAxis = d3.axisBottom(x)
.ticks(d3.timeDay.every(1))
// .tickFormat(d3.timeFormat('%b %d, %H:%M'))
.tickSize(0).tickPadding(10);
var y0Axis = d3.axisLeft(y0)
.ticks(5).tickSize(0);
var y1Axis = d3.axisRight(y1).ticks(5).tickSize(0);
svg.append("g")
.attr("class", "x-axis axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y-axis axis")
.attr("transform", "translate(" + 0 + ", 0)")
.call(y0Axis);
svg.append("g")
.attr("class", "y-axis axis")
.attr("transform", "translate(" + width + ", 0)")
.call(y1Axis);
// Draw bars.
var bars = svg.selectAll(".precips")
.data(data);
bars.exit().remove();
bars.enter().append("rect")
.attr("class", "precip")
.attr("width", width / data.length - 50)
.attr("x", function (d) {
return x(d.date);
})
.attr("y", height)
.transition().duration(1000)
.attr("y", function (d) {
return y0(d.pop);
})
.attr("height", function (d) {
return height - y0(d.pop);
});
const lineRH = d3.line()
.x((d) => x(d['date']) + (width / data.length - 50)/2)
.y(d => y0(d['rh']));
svg.append('path')
.datum(data)
.attr('class', 'line')
.attr('fill', 'none')
.attr('stroke', 'red')
.attr('stroke-linejoin', 'round')
.attr('stroke-linecap', 'round')
.attr('stroke-width', 1.5)
.attr('d', lineRH);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>
I also tried with .nice() and a fun part would be to use the d3 time intervals within .nice(). Feel free to play around with those and let me know if you have any questions.
Also, I'm offsetting the line (path) by the barwidth/2 in the line generator fn.
d3.line()
.x((d) => x(d['date']) + (width / data.length - 50)/2)
Hope this helps as well.
Add a dummy data item that is a bit later then the last item
Here it is done hard coded but you can add it dynamic based on the date of the last item
var data = [
{
fcst_valid_local: "2018-11-13T14:00:00-0600",
pop: 20,
rh: 67,
temp: 38,
wspd: 7
},
{
fcst_valid_local: "2018-11-14T15:00:00-0600",
pop: 15,
rh: 50,
temp: 39,
wspd: 8
},
{
fcst_valid_local: "2018-11-15T16:00:00-0600",
pop: 10,
rh: 90,
temp: 40,
wspd: 9
},
{
fcst_valid_local: "2018-11-16T01:00:00-0600"
}
];
// Margins, width and height.
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 500 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
// Date parsing.
const parseDate = d3.timeParse("%Y-%m-%dT%H:%M:%S%Z");
data.forEach(function (d) {
d.date = parseDate(d.fcst_valid_local);
});
// Set scale domains.
var x = d3.scaleTime().range([0, width])
.domain(d3.extent(data, function (d) {
return d.date;
}));
var y0 = d3.scaleLinear().range([height, 0]).domain([0, 100]);
const y1 = d3.scaleLinear()
.range([height, 0])
.domain([0, d3.max(data, (d) => d.pop)]);
// Construct our SVG object.
const svg = d3.select('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append('g').attr('class', 'container')
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Set x, y-left and y-right axis.
var xAxis = d3.axisBottom(x)
.ticks(d3.timeDay.every(1))
// .tickFormat(d3.timeFormat('%b %d, %H:%M'))
.tickSize(0).tickPadding(10);
var y0Axis = d3.axisLeft(y0)
.ticks(5).tickSize(0);
var y1Axis = d3.axisRight(y1).ticks(5).tickSize(0);
svg.append("g")
.attr("class", "x-axis axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y-axis axis")
.attr("transform", "translate(" + 0 + ", 0)")
.call(y0Axis);
svg.append("g")
.attr("class", "y-axis axis")
.attr("transform", "translate(" + width + ", 0)")
.call(y1Axis);
// Draw bars.
var bars = svg.selectAll(".precips")
.data(data);
bars.exit().remove();
bars.enter().append("rect")
.attr("class", "precip")
.attr("width", width / data.length - 50)
.attr("x", function (d) {
return x(d.date);
})
.attr("y", height)
.transition().duration(1000)
.attr("y", function (d) {
return y0(d.pop);
})
.attr("height", function (d) {
return height - y0(d.pop);
});
const lineRH = d3.line()
.x((d) => x(d['date']))
.y(d => y0(d['rh']));
svg.append('path')
.datum(data)
.attr('class', 'line')
.attr('fill', 'none')
.attr('stroke', 'red')
.attr('stroke-linejoin', 'round')
.attr('stroke-linecap', 'round')
.attr('stroke-width', 1.5)
.attr('d', lineRH);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

Why are there no ticks on my X (time) axis?

QUESTION:
Why are there no ticks on my X (time) axis xAxis?
CODE:
<script type="text/javascript">
d3.json("https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json", function(error, json) {
if (error) {
return console.warn(error);
}
visualizeIt(json);
});
function visualizeIt(data) {
const dataset = data.data;
const margin = {
top: 10,
right: 6,
bottom: 20,
left: 70
}
const w = 900 - margin.left - margin.right;
const h = 500 - margin.top - margin.bottom;
const barWidth = Math.ceil(w / dataset.length);
const format = d3.timeFormat("%Y-%m");
const mindate = dataset[0][0];
const maxdate = dataset[274][0];
const xScale = d3.scaleTime()
.domain([mindate, maxdate])
.range([0, w]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[1])])
.range([h, 0]);
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale)
const svg = d3.select("#results")
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom);
svg.append("g")
.attr("transform", "translate(50," + (h+margin.top) + ")")
.call(xAxis);
svg.append("g")
.attr("transform", "translate(50," + margin.top + ")")
.call(yAxis);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d,i) => 50+barWidth*i)
.attr("y", (d, i) => yScale(d[1]) + margin.top)
.attr("width", barWidth)
.attr("height", (d, i) => h - yScale(d[1]))
.attr("fill", "navy")
.attr("class", "bar");
}
</script>
There are some problems in your code, but I'll address only those related to the x-axis ticks:
You want to parse the strings and return dates, not the other way around. Thus, instead of using timeFormat, your conts format should use timeParse:
const format = d3.timeParse(specifier)
That brings us to the second problem: the specifier in your const format is wrong. You're missing %d here, which is the day, since your strings are like this: "1947-01-01". So, it should be:
const format = d3.timeParse("%Y-%m-%d")
You have to use the parser in your dates:
const mindate = format(dataset[0][0]);
Do the same for maxdate.
Here is your updated CodePen: https://codepen.io/anon/pen/GmjRzY?editors=1010

Categories

Resources