d3 unevenly distributed scaling - d3.js

any suggestions for drawing axes with unequal spacing between the values. For instance I am currently drawing axes using:
yScale = d3.scale.linear().domain([0, 60000]).range([height, 0])
I need more spacing between 0 and 5000 than distributing all the data points equally

Try using a polylinear scale:
yScale = d3.scale.linear().domain([0, 5000, 60000]).range([height, height/2, 0])
The range (0, 5000) and (5000, 60000) will both be given the same amount of space.

Related

How to handle zoom and pan in d3 scaleOrdinal

I have to create a custom stock chart with variable width x axis for each date.
I am using d3.scaleOrdinal for creating the x-axis
const xScale = d3.scaleOrdinal()
.domain(["16-09-2022", "17-09-2022", "18-09-2022", "19-09-2022", "20-09-2022"])
.range([0, 260, 500, 750, 900,1010]);
While zooming using geometric approach, the axis got scaled as a whole(i.e ticks, ticklabel, axis line) which I want to work like scaleLinear.
svg.select("#xaxis")
.attr("transform", `translate(${transform.x},${margin.top})scale(${transform.k}) `)
Can anybody suggest how to achieve the desired result with d3 v7
Thanks in advance
You need to use a continuous scale, like scaleLinear, otherwise it won't work because the ordinal scale cannot interpolate between values.
Think of it like having an array with indexes 0, 1, 2. There is no index 0.5 or 1.5, because ordinals are discrete whole values.

Set xaxis of imagesc with scaled binned values

I have a matrix(20x400) and I am plotting it with imagesc in MATLAB where y axis having 20 values and xaxis having 400 values.
However, I would like to know how can I scale this xaxis 400 to intervals like between 0:20 = 1, 20:40 = 2 until 380:400 = 20; and setting x axis of imagesc in 0-20 scale with the values of 0-20.
I hope it is clear what I am intended to do.

DimpleJS. Y axis values in percentages

I am plotting Vertical Grouped Bar Chart from a csv file which contains Discount, Rating and Clicked. The data is csv is like 55,2,1 and 40,5,0 etc. Here the first value(55,40) are the discounts, (2,5) rating and 1 and 0 correspond to clicked and not clicked respectively. On plotting the chart with following code.
var svg2 = dimple.newSvg("#discountContainer", 590, 400);
d3.csv("/svm1000.csv", function (data) {
var myChart2 = new dimple.chart(svg2, data);
myChart2.setBounds(60, 30, 510, 330)
myChart2.addCategoryAxis("x", ["rating", "action"]);
var y = myChart2.addMeasureAxis("y", "discount");
//y.tickFormat = "%";
myChart2.addSeries("action", dimple.plot.bar);
myChart2.addLegend(65, 10, 510, 20, "right");
myChart2.draw();
});
The problem is I want to represent y axis in percentage in multiple of 10, like 0%, 10%, 20% .. 100%. Right now the y axis values are like 0,2k,4k,6k...20k. So how to represent y axis in percentage.
I see this question is old, so this answer may not help you, but for others facing similar requirements this might be helpful.
dimple.js provide method to have percentage series
myChart2.addPctAxis("y", "discount");
but remember you can't create both Value and Percentage in same axis, you might need to have dual axis graph
var x = myChart2.addCategoryAxis("x", ["rating", "action"]);
var y1 = myChart2.addPctAxis("y", "discount");
var y2 = myChart2.addMeasureAxis("y", "amount"); // the field with value ranges 1000...
also you don't able to use grouped bar chart; for axis 1 use bar chart and for axis 2 use line or vice versa like
myChart2.addSeries("action", dimple.plot.bar, [x, y1]);
myChart2.addSeries("action", dimple.plot.line, [x, y2]);

D3.js - Log scale starting at zero

I am plotting a y axis which should be defined in log scale. The range is from 0 to 1000.
If I try,
var yScale = d3.scale.log().domain([0, 1000]).range([height, 0]);
d3.svg.axis().scale(yScale).orient("left");
Then only 0.01 is shown in the y axis. According to the d3 documentation, log scale range cannot have zero.
I tried this https://stackoverflow.com/a/13228478/690567, but using the scale in the axis throws error.
Is there any other way plot this range (0 to 1000) in y axis?

Bar chart with negative values

I need to create a d3 bar chart that can have negative values. Ideally the axis zero position should be calculated based on the extent of the data, but I'd settle for a solution that assumes symmetric positive and negative extent, i.e. that it would be always in the middle of the chart.
Here's an example of what I'd like to achieve.
OK, let's say you have an array of numbers as your dataset, and this includes some positive and negative values:
var data = [-15, -20, -22, -18, 2, 6, -26, -18];
You'll want two scales to construct a bar chart. You need one quantitative scale (typically a linear scale) to compute the bar positions along the x-axis, and a second ordinal scale to compute the bar positions along the y-axis.
For the quantitative scale, you typically need to compute the domain of your data, which is based on the minimum and maximum value. An easy way to do that is via d3.extent:
var x = d3.scale.linear()
.domain(d3.extent(data))
.range([0, width]);
You might also want to nice the scale to round the extent slightly. As another example, sometimes you want the zero-value to be centered in the middle of the canvas, in which case you'll want to take the greater of the minimum and maximum value:
var x0 = Math.max(-d3.min(data), d3.max(data));
var x = d3.scale.linear()
.domain([-x0, x0])
.range([0, width])
.nice();
Alternatively, you can hard-code whatever domain you want.
var x = d3.scale.linear()
.domain([-30, 30])
.range([0, width]);
For the y-axis, you'll want to use rangeRoundBands to divide the vertical space into bands for each bar. This also lets you specify the amount of padding between bars. Often an ordinal scale is used with some identifying data—such as a name or a unique id. However, you can also use ordinal scales in conjunction with the data's index:
var y = d3.scale.ordinal()
.domain(d3.range(data.length))
.rangeRoundBands([0, height], .2);
Now that you've got your two scales, you can create the rect elements to display the bars. The one tricky part is that in SVG, rects are positioned (the x and y attributes) based on their top-left corner. So we need to use the x- and y-scales to compute the position of the top-left corner, and that depends on whether the associated value is positive or negative: if the value is positive, then the data value determines the right edge of the bar, while if it's negative, it determines the left edge of the bar. Hence the conditionals here:
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d, i) { return x(Math.min(0, d)); })
.attr("y", function(d, i) { return y(i); })
.attr("width", function(d, i) { return Math.abs(x(d) - x(0)); })
.attr("height", y.rangeBand());
Lastly, you can add an axis to display tick marks on top. You might also compute a fill style (or even a gradient) to alter the differentiate the appearance of positive and negative values. Putting it all together:
Bar Chart with Negative Values

Resources