How to plot time data on a D3.js line graph - javascript

I have a ton of data associated with time. I want to plot a, hopefully, simple line graph. A simplified example:
var data = [{ time: 13:30, size: 100 }, { time: 13:37, size: 500}, { time: 13: 42, size: 300 }
{ time: 13:51, size: 150 }, { time: 13:56, size: 175 }, { time: 15:59, size: 75 }
{ time: 16:11, size: 75 }, { time: 16:37, size: 125 }, { time: 15:27, size: 200 } [...]
{ time: 20:36, size: 500 }]
Many time values, and corresponding size values. Of course, I do not want to plot every single time value on this graph. Instead I want to take the lowest value, 13:30, then plot the time on the axes at 30 minute intervals (i.e. 13:30, 14:00, 14:30 ... 20:30) until I hit the latest time in my array of data. At the same time, I want to plot every size value. So, the graph will only display a tick for 13:30 and 14:00, but the values that correspond with 13.37, 13.42, 13.51, 13.56 will be plotted on the line.
How would I go about doing this?
My first attempt was something like this:
var graph = d3.select('.graph'),
WIDTH = 790,
HEIGHT = 250,
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
}
xScale = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]),
yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([smallest, largest]),
xAxis = d3.svg.axis().scale(xScale),
yAxis = d3.svg.axis().scale(yScale).orient("left");
NB the "smallest" and "largest" variables are the smallest and largest size values in my data array, calculated elsewhere. Obviously this is wrong because this would plot every single time value on the axes (as explained above, I do not want this) and even if I did it errors and glitches horribly.
How would I go about achieving what I want to achieve?
Thx
-- Gaweyne

Solved it. d3.time.scale not d3.scale.linear()
xScale = d3.time.scale(range([MARGINS.left, WIDTH - MARGINS.right]).domain(new Date([//Earliest Date//]), new Date([//Latest Date//]))

Related

How to add more ticks to D3 timeline charts

I have a stacked time line chart, but I am unable to include more ticks in the chart.
I've tried this code:
var chart = d3.timeline().showAxisTop().stack().background('#C0C0C0').orient('top')
.relativeTime()
//.absoluteTime()
.tickFormat({
format: function(d) {
displayDate.setHours(hours++);
return formatter(displayDate);
},
tickTime: d3.time.hours,
ticks: 20,
tickInterval: 1,
tickSize: 30,
});
chart.margin({
left: 120,
right: 0,
top: 50,
bottom: 0
});
chart.labelMargin(25);
var svg = d3.select("#timelineAxisTop").append("svg").attr("width", width)
.datum(testData).call(chart)
.selectAll("text").attr("class", "timeLineFont");
// $('.tick timeLineFont').attr("x", 75).attr("y", -12);
$('.tick').find('text').attr('x', 85).attr('y', -12);
};
chart image
As per the image shown in your question your interval is 1 hour for each tick so better change:
ticks : 20 to ticks : (d3.time.hour,1) by eliminating tickInterval and if you still want more ticks then change your ticks appropriately may be ticks : (d3.time.mintues,45) for example

Plotly.js adds top-margin to graphs inconsistently, how to prevent it

With Plotly.js I'm getting a top-margin added sometimes (not consistently), where the total height of the graph is 300px, but the graph itself is only 150px high. The SVG container then is stretched and the actual graph is smaller. What can I do to prevent this white-space, and why does it only show up selectively?
Plotly Matlab syntax that results in 300px div instead of a 300px graph:
`% PLOT MEAN MOVEMENT
data = {...
struct(...
'x', nScan, ...
'y',fastmotion, ...
'type', 'scatter')...
};
if max(fastmotion) < 0.3
yminval = 0.3;
else
yminval = round(max(fastmotion) + 1);
end
layout = struct(...
'yaxis', struct(...
'title', 'Movement (mm)', ...
'range', [0, yminval]));
header{3} = 'Absolute Movement';
layout.width = 800;
layout.height = 300;
p = plotlyfig;
p.data = data;
p.layout = layout;
p.PlotOptions.FileName = 'plot_5';
html_file = plotlyoffline(p);
html_file;`
You can check this answer on a different question, and here is the fiddle.
The quick code you can use:
var layout = {
margin: {
l: 20,
r: 20,
b: 20,
t: 20,
pad: 5
}, title: false
};
As mfedoten says on his answer: But be careful if you have tick labels, if you set margins to zero the labels will be cropped
So apparently line 68 in plotlyfig.m caused the issue:
obj.PlotlyDefaults.MinTitleMargin = 80;
Even though I had no title, it sometimes added 80 px on top of the graph, maxing out at the specified graph height. Setting this value to 0 solves the problem.
Probably line 68 in plotlyfig.m just set default margins.
You can set the margins manually like that:
p.layout.margin = struct('b', 15,'l', 30, 'r', 0, 't', 0);
You can find documentation on margins here.
But be careful if you have tick labels, if you set margins to zero the labels will be cropped.

keep fixed size of the bars in Highcharts

I want to maintain the same size of the bars. no matter how many there are values.
here is the size I want to have all bars.
when added four values the bars become smaller.
I want all the bars are the same size. no matter that I have to scroll to see the other bars (this is what I want).
this is my code:
http://jsfiddle.net/Laxfsbtb/
$('#container').highcharts({
chart: {
type: 'bar'
},
series: [{
name: 'text1',
data: [1000, 950,920,880,850,234],
color: "#FF0000"
}, {
name: 'text2',
data: [800,770,750,740,730,4324],
color: "#000000"
}, {
name: 'text3',
data: [600,540,535,500,400,324],
color: "#00FF00"
}]
});
});
This can be done with the pointWidth parameter like:
plotOptions: {
series: {
pointWidth: 20 //width of the bar/column/point.
}
},
To allow scrollbar you should probably upgrade to highstock but that only works horizontally. Or you could set up a div that allows the chart to be "larger" on the inside and scroll through that div window.
Not sure precisely what you're looking for, but this might help.
I put together an example a while ago to adjust the height of the chart according to the number of bars, using some preset parameters:
var barCount = chartData.length;
var pointWidth = 20;
var marginTop = 60;
var marginRight = 10;
var marginBottom = 50;
var marginLeft = 100;
var pointPadding = 0.3;
var chartHeight = marginTop
+ marginBottom
+ ((pointWidth * barCount) * (1 + groupPadding + pointPadding));
So, tell it what size you want the bars, how much padding between them, how much margin at top and bottom of chart, and how many data points you have.
Bars will stay the same size and spacing while the chart itself grows to accommodate them.
example:
http://jsfiddle.net/jlbriggs/kpu5d1qf/
To see it work, change the 12 in this line:
var chartData = randomData(12, true);
To whatever number you want.
((Edit
Since you are working with grouped data, you'll have to change the math a little bit.you'll need to account for the number of groups, and multiply hat by the groupPadding, added to the number of points * the pointPadding.
You'll also have to make getting your count of data points slightly more complex.

jQuery Flot Charts: Auto bar width with dynamic items

My charts output dynamic data based on input filters. These can have 1 to 30 bars and they resize on screen resize/device. Just an example, currently where there's < 5 bars and the charts width is 1138px (max), then I have pretty big bars in width.
Q. How is this problem dealth with?
var options = {
xaxis: { ticks: ticks},
grid: { clickable: false, hoverable: true },
series: { stack: true, bars: {show: true,align: 'center',barWidth: 0.5,lineWidth: 2,fillColor: {colors: [{opacity: 0.9}, {opacity: 0.9}]}} },
legend: {container: ".widget-legend"}
};
Assuming you want to give your bars the same pixel width whether there are 1 or 30 bars, you can calculate the value for barWidth from the width of the chart (in x axis units and pixels, correcting for axes and margins) using cross-multiplication. A reasonable pixel width for up to 30 bars on 1100 pixels would be around 20 pixels per bar.
var chartWidthInPixels = 1100 * 0.95; // or $('#chart').width() * 0.95
var barWidthInPixels = 20; // or chartWidthInPixels / 50
var chartWidthInAxisUnits = (max(ticks) - min(ticks)) + 1; // this will be 1 for one bar
var barWidthInAxisUnits = barWidthInPixels * (chartWidthInAxisUnits / chartWidthInPixels);
For one bar with the above example values this gives around 0.019 for the barWidth. By variation of the constants in the formulas you can modify the calculation.

How I can set maximum value at graphael y axis and why?

I have several points that I try to represent using a graphael line chart. Almost all of them are below 0.03. However, the chart sets 1 as the maximum and all points are shown to be very down at the chart. When I have even one point over 0.03, graphael sets the maximum value something more than 0.03 and therefore the chart displays correctly. What can I do for the rest cases where all my points are below 0.03? It is really very ungly, and not helpful at all.
Is there a way to set the max value of the y axis automatically?
If you cannot help me, can you please run it, just to tell me if he can run it normally? It wouldn't take much time...
This is what I mean
I noticed that it also might produce very wrong y axis labels...
My code is shown below
var lines = r.linechart(30, 30, 600, 440,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71]],[[0.02046,0.00635,0.02813,0.02808,0.02385,0.00729,0.02145,0.01978,0.02683,0.03006,0.03105,0.01211,0.0083,0.0022,0.02172,0.01541,0.01181,0.02418,0.00552,0.02708,0.01011,0.0105,0.0294,0.00132,0.00615,0.02303,0.00065,0.00967,0.00381,0.02167,0.01357,0.0221,0.02512,0.00918,0.01072,0.01083,0.00598,0.00195,0.01716,0.00347,0.03058,0.01815,0.02899,0.01537,0.0241,0.0241,0.00451,0.00088,0.01574,0.00688,0.0143,0.0024,0.03047,0.02876,0.00528,0.00996,0.00865,0.02681,0.02194,0.00082,0.00664,0.01178,0.01596,0.00516,0.0165,0.00895,0.01869,0.03082,0.02318,0.01089,0.00943,0.00986]], {axisxstep : 12,axisystep : 5,nostroke: false, axis: "0 0 1 1", symbol: "circle", smooth: true }).hoverColumn(function () {
this.tags = r.set();
for (var i = 0, ii = this.y.length; i < ii; i++) {
this.tags.push(r.tag(this.x, this.y[i], this.values[i], 160, 10).insertBefore(this).attr([{ fill: "#fff" }, { fill: this.symbols[i].attr("fill") }]));
}
}, function () {
this.tags && this.tags.remove();
});

Categories

Resources