Strange Gridline Behavior - javascript

Dashboard 1: https://bl.ocks.org/diggetybo/073f2f9b4b9a0c88211c9c643e47e9a9
Dashboard 2: https://bl.ocks.org/diggetybo/c16c1168705ea18b7d8711c15e90f8ec
I would love if someone could explain why the gridlines in the second link on the bottom right-hand graph are of a higher tick interval (or whatever you want to call it) than the ones in the first link. The d3 template is one I made a few weeks ago and it's just something I'm copying and pasting to use with different data sets. However, despite hours of double checking everything, I'm still not sure why it's doing that.
The only thing that's different is the data, but they are of very similar types of data, the domains should be similar. For example, the bottom right hand graph is all positive number for both dashboards. Maybe it's being parsed differently for some strange reason?
Let me know how you did it, whether you brute forced the styling of the gridlines, or if you found the trigger of the problem. That is to say, why it chose to add so many more gridlines on that graph but none of the others.
Thank you

To regulate the number of ticks use ticks(4)
read here this will generate 4 ticks in x axis.
var xGridlineNodes = svg.append('g')
.attr('transform', 'translate(' + margins.left + ',' + (totalHeight - margins.bottom + axisPadding) + ')')
.call(xGridlinesAxis.tickSize(-graphHeight - axisPadding, 0, 0).tickFormat("").ticks(4));
The reason why there are more ticks in dashboard2 than in dashboard1 is because of the different data sets (there is no css tricks in that). May be some expert can throw some light on why more ticks.
Here is a working plunk in which i have regulated the number of ticks
If you know what the tick values will be then use tickValues read here

Related

How to format array of values to form a distribution for google-charts histogram?

I have 1000 values in no particular order but I'd like to format them into a normal distribution to plot on a histogram using google-charts.
I've tried using d3.js and I got it working just based off some examples but it looks extremely ugly and I don't have enough time to learn d3 in and out to get the results I want. Google-charts visual format are great.
The problem is google-charts expects data in a format where each value has a name along with headers. So when I organized it into this:
'dsSample1': [
['price', 'number'],
['price', 11386.057139142767],
['price', 27659.397260273952],
['price', 44159.39726027395],
...
from
'dsSample2': [
11386.057139142767,
27659.397260273952,
44159.39726027395,
28026.04112639835,
...
google charts works, but I get the following:
This is as close as I've come to getting it working in d3: https://jsfiddle.net/0jtrq17x/1/. It works but it's extremely ugly.
I've managed to arrange the array data into bins using some d3 code but it is imcompatible with google-charts and I don't know to make it compatible, and also don't know how to format the data so it plays nice with google-charts histogram
this code
var values = this.hypo.dsSample2.map(x => {
return x + 128608.42487322348
})
var max = d3.max(values)
var min = d3.min(values)
var x = d3.scale.linear()
.domain([min, max])
.range([0, 800]);
var histGenerator = d3.layout.histogram()
.bins(x.ticks(100))
(values)
this.data1 = histGenerator
returns this array transformation
My problem is I don't know how to massage my array of data so I can get something like this in google-charts:
there are two data formats for the google charts version.
a single series format, with the names,
or a multi-series format, with just the numbers.
it is ok to use the multi-series format with a single series.
so, assigning names is not required.
but you will have to convert each value to its own array.
'dsSample1': [
[11386.057139142767],
[27659.397260273952],
[44159.39726027395],
...
from
'dsSample2': [
11386.057139142767,
27659.397260273952,
44159.39726027395,
...
you can use the map method to format the data.
dsSample.map(function (value) {
return [value];
});
see following fiddle...
https://jsfiddle.net/x684f1vs/
I know you have decided against D3, but since your question is still tagged with d3.js, I will post an answer using D3 anyways :)
I have made an updated JSFiddle, with an adaption of your code:
https://jsfiddle.net/w7r80cfo/1/
In short, to manipulate this histogram, look to the following lines:
1038 and 1039 to change the dimensions (width and height respectively) of the visualization. The values given are in pixels.
1049 to change the number of buckets for you histogram. Currently it is set to 100.
1083 to change the width of the individual bars. Currently, I've set it to 0.25 of the space calculated for each bar. If you e.g. change 0.25 to 1 the bars will be so wide, they will be drawn right next to each other.
1085 to change the color of the bars. Currently they are given a darker shade of red the higher number of values they represent. If you want e.g. just blue, change the line to .attr("fill", "steelblue")
Play around with these values and see if you can get to a chart that is close to what you want.
To elaborate a bit on the changes I've made, they consist mainly of the following:
Line 1038: lowered the width to 600.
Line 1073: updated to position the visualization correctly:
.attr('transform', `translate(${margin.left},${margin.top})`);
Line 1083: lowered the width of the bars by multiplying by 0.25:
.attr("width", (x(data[0].dx) - x(0)) * 0.25)
Other than that I have removed the following code to remove the text labels, as they indeed made the chart look messy:
bar.append("text")
.attr("dy", ".75em")
.attr("y", -12)
.attr("x", (x(data[0].dx) - x(0)) / 2)
.attr("text-anchor", "middle")
.text(function(d) { return "$" + d3.format(",.2f")(d.x); });
Besides this, I have added an y axis and changed the way the axes are drawn in order to make them look a bit nicer. I can go into detail about these changes, but I think they are of lesser interest to your goal.
Hope this helps!

How to set a minimum range on the y-axis for a stacked area chart in d3

I'm creating a stacked chart using nvd3, similar to the example on the nvd3 website.
However, my data set is a lot more uniform than their example; I'm actually visualizing a funnel with multiple steps over time, each step describing the % that made it from the last step to this one, so it ranges from 100% to about 80%. So it ends up just looking like 4 straight rectangles (see below).
I'd like to know if there is some way of setting a minimum value to display on the y-axis so that each step only takes into account the data that is actually likely to fluctuate, leading to a clearer indication of peaks and troughs.
I've tried using .range([100, 80]) and .domain([80, 100]) but neither seems to make any difference.
For example:
var y = d3.scale.linear().range([100, 80]);
chart.yAxis
.scale(y)
.tickFormat(d3.format(',.2f'));
Full code for my example is available here.
Any ideas how to achieve this?

Fit the cumulative percentage line to the sorted histogram output with d3 for a pareto chart histogram

This is what I have so far: https://gist.github.com/daluu/fc1cbcab68852ed3c5fa and http://bl.ocks.org/daluu/fc1cbcab68852ed3c5fa. I'm trying to replicate Excel functionality.
The line fits the default histogram just fine as in the base/original http://bl.ocks.org/daluu/f58884c24ff893186416. And I'm able to sort the histogram in descending frequency, although in doing so, I switched x scales (from linear to ordinal). I can't seem to map the line to the sorted histogram correctly at this point. It should look like the following examples in terms of visual representation:
the Excel screenshot in a comment in my gist referenced above
the pareto chart sorted histogram in this SO post
the pareto chart (similar to but not exactly a sorted histogram) made with d3 here
What's the best design approach to get the remaining part working? Should I have started with a single x scale and not need to switch from linear to ordinal? If so, I'm not sure how to apply the histogram layout correctly using an ordinal scale or how not to use a linear x scale as a source of input to the histogram layout and still get the desired output.
Using the same ordinal scale with the code I have so far, the line looks ok but it's not the curve I am expecting to see.
Any help appreciated.
The main issue with the line is that the cumulative distribution needs to be recalculated after the bar is sorted, or if you're gunning for a static pareto chart, the cumulative distribution needs to be calculated in the target sort order. For this purpose i've created a small function to do this calculation:
function calcCDF(data){
data.forEach(function(d,i){
if(i === 0){
d.cum = d.y/dataset.length
}else{
d.cum = (d.y/dataset.length) + data[i-1].cum
}
})
return data
}
In my case, i'm toggling the pareto sort on/off and recalculating the d.cum property each time. One could theoretically create two cumulative dist properties to start with; i.e. d.cum for a regular ordered distribution and say d.ParetoCum for the sorted cumulative, but i'm using d.cum on a tooltip and decided against that.
Per the axis, i'm using a single ordinal scale which i think is cleaner, but required some work on getting the labels to be meaningful for number ranges since tick-marks and labels no longer delineate the bins as one would get with a linear scale. My solution here was to just use the number range as the tick mark e.g. "1 - 1.99" and add a function to alternate tickmarks (got that solution a while ago from Alternating tick padding in d3.js).
For the bar sorting, i'm using this d3 example as a reference in case you need to understand in the context of a simpler/smaller example.
See this fiddle that incorporates all of the above. If you want to use it, i would suggest adding a check to avoid the user being able to toggle off both bars and line (left a note in the code...should be trivial)
Instead of sorting the y.
data.sort(function(a,b){ return b.y - a.y;});
you should be sorting the x
data.sort(function(a,b){ return a.x - b.x;});
Working code here

how to use string values as axis ticks properly in d3js? Not able to map data correctly can't figure out whats wrong in this code

I am new to D3. In my scatterplot i need to plot usernames for y-axis but data and axis tick values are out of order can anybody help me find out what's wrong with this code ?
Full link to my code : Scatterplot code
I don't see anything major in your code. A couple of things:
1.) The sorting on your y-axis is fine. It's sorted in the order they appear in your data. As #mdml says in the comments, you can sort them differently if you desire.
2.) You have an "odd" point in your data. Everything is occurring around Nov-27-2014-12:33 except for one point on the 28th. This is causing d3 to pick a larger range for the x-axis and plotting most your data points on top of each other.
3.) You should probably "center" your points in relation to you y-axis:
.attr("cy", function(d) { return y(d.user) + y.rangeBand() / 2; })
Here's an example tweaking some things.

D3 - issues on first transition after initialization

I have created this jsbin http://jsbin.com/ibewux/3/edit to show a strange behavior on transitions.
When the chart is initialized, it correctly displays the data (see the table below it).
If I try to change the chart type through the dropdown menu, some series are swapped; after this happens, the series are not swapped anymore.
Same thing happens if you click on updateChartData button; first time it will swap the series compared to the data displayed in the table.
So it seems that only the first transition after initialization is subject to this unwanted swap.
It's a short piece of code and wonder if you can spot the reason why this happens.
Thanks
When isVerticalChart is true, you are using an ordinal scale with domain svg.pointsNames (which seems to be an array of strings of the form "Col " + i):
x = d3.scale.ordinal().domain(svg.pointsNames);
However, you then go on to use the datum index with this scale, instead of these strings:
.attr("x", function(d, i) { return isVerticalChart ? x(i) : x(d.y0 - d.size); })
I think you should be passing a string from the domain to the scale here to avoid the strange behaviour you're seeing.
It only works at the moment because if you pass a key to an ordinal scale that hasn't been seen before, it will add it to the domain.
There may be other issues, but hopefully that gets you closer.

Categories

Resources