I've searched in the official d3.js documentation, as well as, here in stackoverflow to find a way to add custom tickValues to a time scale axis; However, i haven't stumble across any documentation that confirms that something like that is possible.
So in essence, i have a time scale axis and i would like to show specific hours
e.g. i'd like to do something like this :
xHourAxis
.ticks(d3.time.hours, 2)
.tickFormat(d3.time.format('%I %p'))
.tickValues(2, 4, 6, 8, 10, 12) ;
So i want to display tick values every 2 hours, but not including the first (12 am) and the last (12 pm).
Does anyone know if there is any workaround for that?
Nearly there, but your code has two problems: First the tick values must be specified in an array, and second those values should be Javascript date objects. i.e. you just provide an array of dates to tickValues so your code would looks something like this:
xHourAxis
.tickFormat(d3.time.format('%I %p'))
.tickValues([new Date(2000,10,5), new Date(2005,2,7), new Date(2007,11,11)]);
Also, note that you needn't call the ticks() if you are going to later specify custom values.
Related
First, I want to apologise for any mistakes in asking the question properly according to the site rules, it's my first time doing it and I tried my best.
So I have the following issue:
Let's say I have that data (consider it - date / value):
I then init a chart with it, the only relevant option to that moment is:
xaxis: { mode: "time" }
and I get the following result:
("Дек" == December)
Now my problem is that there are mid-day hours in the legend which I don't want. I want only days in it. I tried adding this to the xasis:
tickSize: [1, "day"]
but it creates a legend entry for each day of the whole timespan (01.12, 02.12, 03.12 and so on to 06.12) and I want only the days for which I have some data present.
After a while spent in searching in documentation and google I found that there is actually another property for this:
minTickSize: [1, "day"]
That does the trick.
Is there any workaround to have tickMarkPlacement set as "between" on a datetime Axis? I am aware is not supported by the API but I was hoping to find some sort of hack/plugin.
You can fudge it with the x axis label's x property.
Example:
http://jsfiddle.net/jlbriggs/3qtZr/36/
[[update after comments:
if you mean that you want the data points to also line up 'between', then there isn't a good easy way.
My approach would be
1) make sure there is only one data point per axis tick, ideally
2) adjust the x value of the data point to push it to the right in a way that corresponds with the label offset
3) adjust tooltip formatters to correct the date for display
or, 4) just go with categories
However, if you can explain why you want to do this, what effect you're going for, perhaps there's more that can be done.
{{further updates:
After playing around a little more, I found another way to fudge the data point placement, though I am unclear whether you need that.
Example here:
http://jsfiddle.net/jlbriggs/3qtZr/39/
It uses the pointPlacement property.
The catch is that the pointPlacement property doesn't work if there is not a columns series present with as many data points as the line series, it seems.
So this method adds and hidden dummy column series in order to make the pointPlacement property affect the line series.
Not elegant, but it beats having to adjust the data values and then re-adjust them in the formatter.
I have a set of data for dates. What value should I provide the X axis values? How do I make Rickshaw display the X data values as dates?
I looked around the docs and examples and cannot find anything.
I've just started using Rickshaw and was in the exact situation.
But, before I go any further, Rickshaw documentation is virtually nonexistent which is very upsetting because the performance of Rickshaw compared to other JS graphing libraries is outstanding.
The best way to find examples is to dig into the source code and example code on their github page try to make sense of things (not the way documentation should be).
That being said, let's try and build a strong base of questions/answers here on StackOverflow!
So, back to the question :) It looks like you've already found your own solution to the question, but I'll provide my solution as well.
Rather than using Rickshaw.Graph.Axis.Time, I've used Rickshaw.Graph.Axis.X and set the tickFormat accordingly.
var data = [ { x: TIME_SINCE_EPOCH_IN_SECONDS, y: VALUE },
{ x: NEXT_TIME_SINCE_EPOCH_IN_SECONDS, y: NEXT_VALUE } ]
var xAxis = new Rickshaw.Graph.Axis.X({
graph: graph,
tickFormat: function(x){
return new Date(x * 1000).toLocaleTimeString();
}
})
xAxis.render();
toLocaleTimeString() can be any of the Javascript date functions, such as toLocaleString(), toLocaleDateString(), toTimeString(), or toUTCString(). Obviously, because the tickFormat takes a function as an argument one can supply their own formatter.
Koliber, I'd be interested to understand your answer if you could provide more detail as well.
Additional to Lars' reply, I found by default Rickshaw is calling
.toUTCString(x.value*1000) //(just ctrl+F to find where =) ).
In my case, I saw different time label on X between Graphite and Rickshaw for this reason, and it works beautifully once I changed it to
.toLocaleString(x.value*1000).
Plus, you may need modify this in two places : Rickshaw.Graph.Axis.Time and the ...HoverDetails
I have finally figured out that the X axis values should be epoch time values. Then, using the code from the examples I was able to show a proper time scale.
I still have a problem because I would like to show the tick marks on weeks on the X axis. However, setting timeUnit to 'week' causes JavaScript errors. It works with other time units though.
None of this worked for me. What worked with angularjs was:
'x' : d3.time.format.iso.parse(date).getTime(), 'y' : 10
Code
Example of my problem: http://jsfiddle.net/x46RQ/
Goal
I want the graph to be a bar graph like so: http://jsfiddle.net/Lbd85/ but obviously with dates as the x axis. If I add my data into that fiddle, it messes up like the one listed above as seen here: http://jsfiddle.net/73G7Z/
Questions
Why are all 3 days provided in the data variable not displaying?
Why are the bars not lined up with their appropriate x-axis ticks?
Why does changing the data and mode to time totally mess up what would otherwise be a functional and accurate bar graph?
Environment
jQuery 1.7.1
jQuery Mobile 1.0.1
Flot 0.7
Thanks
Let me know if any additional information is required.
Part #1, You specified a min y value of 0 in your flot options, and your data point #2 has a value of zero. So it's there but just very small, almost invisible.
Part #2, you have to offset your dates by the users timezone:
Something like this:
var tzOffset = new Date();
tzOffset = tzOffset.getTimezoneOffset()*60*1000;
data.push([(new Date("2012/02/20").getTime()-tzOffset), 1]);
Part #3, Your graph is a mess because you specified a width when in fact the option you were looking for is barWidth and you need to specify the width in terms of time, i.e. milliseconds. See here for how. Something like barWidth: 12*60*60*1000 looks OK.
So in summary, this is what it will look like: http://jsfiddle.net/ncTd3/
This is quite a daunting project to a Protovis newcomer, but maybe you could help me split it into digestible chunks?
What I would like to build is an "interactive Area chart", as sketched here:
First of all, it's the data ...
I have data for provinces in Excel:
Province Year 10 100 1000 10000
A 1970 2 4 6 3
A 1971 3 6 8 5
B 1970 6 9 12 6
B 1971 4 8 11 8
.... ... . . . .
For each province and year, I would like to be able to draw an area chart:
vis.add(pv.Area)
.data(data.ProvinceA[1970])
.bottom(1)
.interpolate("basis")
.left(function(d) x(d.x))
.height(function(d) y(d.y))
.fillStyle("rgb(21,173,210)")
.anchor("top").add(pv.Line)
.lineWidth(3);
Then I would like to add 2 types of interactivity:
Selection of Province
Time slider
Together, the selection checkboxes and the time slider determine which areas are visible at any given time.
If, for example, Province A is selected and the year is 1984, only that area is displayed. If the time slider is now dragged, the corresponding years are now displayed for Province A. If another Province is checked, the areas are overlayed and both areas are redrawn when the time slider moves.
Protovis questions:
How do I format the data (province, year, x, y) for this application?
How do I achieve the binding of checkboxes to area?
How do I implement the time slider? Within Protovis or like an external component with listeners that trigger re-rendering of the graph?
Formatting data: The first step is to get it into JSON, using some external tool (I really like Google Refine for this, though it's a pretty big tool if this is all you need it for - try Mr. Data Converter for a quick and dirty option). These tools will probably give you data as a JSON object, like this:
`[{"Province":"A", "Year":"1970", "10":2, "100":4, "1000":6, "10000":3}, ...]`
Once you have the data available as JSON, you'll want to get it into shape for your vis. You're going to want to pass each pv.Area an array of values - from your description it looks like you want the [10, 100, 1000, 10000] values. Protovis has a lot of tools for manipulating data - see the pv.Nest operator. There are lots of ways you might approach this - I might do this:
data = pv.nest(data)
.key(function(x) {return x.Province})
.key(function(x) {return x.Year})
.rollup(function(v) {
return [v[0]['10'], v[0]['100'], v[0]['1000'], v[0]['10000']];
});
which gives you an object like:
{
A: {
1970: [2,4,6,3]
// ...
},
// ...
}
This sets you up for the interface elements. Keep the array of checked Provinces and the current year in global variables:
var currentProvinces = ['A', 'B', ...];
var currentYear = 1970;
and set up your area to reference those variables:
// a containing panel to help with layout and data
var panel = vis.add(pv.Panel)
.data(function() currentProvinces); // making this a function allows it to
// be re-evaluated later
// the area itself
var area = panel.add(pv.Area)
.data(function(province) data[province][currentYear]);
// plus more area settings as needed
Now use some other library - I'm partial to jQuery, with jQuery UI for the slider - to create your interface elements. The onchange function for each element just needs to set the corresponding global variable and call vis.render() (assuming your root panel is called vis). This should be pretty simple - see here for a Protovis example using jQuery UI to make a time slider very similar to what you have in mind.
I think that you are trying to make that pair of charts:
http://mbostock.github.io/protovis/ex/zoom.html