I have a d3 graph which specifies the range on the Y axis like this:
var yScale = d3.scaleLinear()
.domain([0, 1]) // input
.range([height, 0]); // output
However a scale of 0 to 1 isn't very useful. I want it to work out what is a suitable range for me. I'm a bit new to this so I thought if I did something like this:
// Data
var dataset = [{
y: 0.1
},
{
y: 0.6
},
{
y: 0.6
},
{
y: 0.7
}
];
var mymax = Math.max(dataset);
Then I can find the maximum value in my dataset, and then feed that into my .domain range like this:
.domain([0, mymax]) // input
However, I appreciate my attempt at this is wrong because I get NaN returned. I think it might be pointing at the letter Y and not my numbers.
I don't feel like this is a duplicate of the question.
var mymax = Math.max.apply(Math, dataset.map(function(o) { return o.y; }));
Related
I want to show values like [0,1,2,..., maxYValue] instead of [0, 0.5, 1, 1.5 ... maxYValue].
var y = d3.scaleLinear()
.range([height - margin, 0])
.domain([0, this.maxYValue]); //maxYValue can be any whole. number
Original:
d3.axisLeft(y).ticks(5).tickSize(-width + margin)
Modified:
d3.axisLeft(y).ticks(5).tickSize(-width + margin).tickFormat("f")
After using tickFormat("f"), it starts displaying the y-axis values like [0,0,0, 1, 1, 1]. It is rounding off the values. But, I want to set a step value to the y-axis values to get the data like [0,1,2,3,.., maxYValue]
If you simply wants all integers up to the maxYValue, instead of using axis.tickFormat on the auto-generated ticks just use d3.range to generate an array based on the scale's domain, and pass that to axis.tickValues:
d3.axisLeft(y).tickValues(d3.range(y.domain()[0], y.domain()[1] + 1, 1));
For instance:
const y = d3.scaleLinear()
.domain([0, 12]);
console.log(d3.range(y.domain()[0], y.domain()[1] + 1, 1))
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.3.0/d3.min.js"></script>
If maxYValue is not the last value in the scale's domain, just use that variable instead.
I have data set like the one shown below. For each date, I have one or more points to plot on the y-axis.
x axis (y axis) - 2021-07-01 (20, 30)
x axis (y axis) - 2021-07-02 (20)
x axis (y axis) - 2021-07-04 (10, 50)
x axis (y axis) - 2021-07-06 (40)
How to plot this data using Plotly js
If you have one or more y-values for each x-value (say in the form of a 2D array), you can loop through this array to flatten it, and repeat the necessary x-values from the original x-value array. The codepen for this is here.
var x = ["2021-07-01","2021-07-02","2021-07-04","2021-07-06"]
var y = [[20, 30],[20],[10,50],[40]]
var x_plot = []
var y_plot = []
for (let i=0; i<y.length; i++) {
for (let j=0; j<y[i].length; j++) {
x_plot.push(x[i])
y_plot.push(y[i][j])
}
}
var trace1 = {
x: x_plot,
y: y_plot,
type: 'scatter',
mode: 'markers'
}
var data = [trace1];
Plotly.newPlot('myDiv', data);
I got answer from code pen.
I think this may be useful for others as well.
If we have two y values for each x value we can duplicate x values to match y values like the one show below.
var data = [
{
x: ['2013-10-04', '2013-10-04', '2014-11-04'],
y: [1, 3, 6],
type: 'scatter'
}
];
Plotly.newPlot('myDiv', data);
I'm building a heat map with a color gradient from green to red. I want cells with value 0 to be green, and values greater or equal than 1 to take the other colors.
I'm building the scale this way :
var colors = [
'#27C24C',
'#7DB22E',
'#D4A10F',
'#F97C20',
'#F35F40',
'#FF0000'
];
var colorScale = d3.scale.quantile()
.domain([0, d3.max(data, function (d) { return d.value; })])
.range(colors);
But this returns me the following quantiles :
[239.16666666666677, 478.3333333333332, 717.5, 956.6666666666664, 1195.8333333333335]
Therefore, I have the following heatmap :
But I would like the pointed cell to be the second shade of green, since its value is strictly greater than 0.
You cannot use only quantile scale in this case. Write custom scale function to treat the zero value separately.
var colors = [
// '#27C24C', this value must not be included in the internal range
'#7DB22E',
'#D4A10F',
'#F97C20',
'#F35F40',
'#FF0000'
];
var colorScaleInternal = d3.scale.quantile()
.domain([0, d3.max(data, function (d) { return d.value; })])
.range(colors);
var colorScale = function(value) {
return !!value ? colorScaleInternal(value) : '#27C24C';
};
While I couldn't find support in D3 for this functionality, I was able to work around it by altering the range array sent to d3. The idea is to check with D3 if the quartiles are repeating, and if so, keep the same color for all of them:
var scale = d3.scale.quantile().domain(domain).range(range);
var quantiles = scale.quantiles();
quantiles.unshift(d3.min(domain));
// Now that you have the quantiles, you can see if some of them are holding the same value,
// and it that case set the minimum value to all of them.
var modifiedRange = [range[0]];
for (var i = 1; i < range.length; i++) {
if (quantiles[i] === quantiles[i - 1]) {
modifiedRange.push(modifiedRange[i - 1]);
} else {
modifiedRange.push(range[i]);
}
}
// set the new scale
scale.range(modifiedRange);
plotly.js 2D histograms and contour plots automatically generate a z-axis range that accommodates the entire range of z values in the dataset being plotted. This is fine to start, but when I click-and-drag on the plot to zoom in, I'd like the z axis range to also zoom in to accommodate only the range of z values currently on display; instead, the z axis never changes. Here's a codepen (forked from the plotly examples, thanks plotly) to play around with: http://codepen.io/anon/pen/MKGyJP
(codepen code inline:
var x = [];
var y = [];
for (var i = 0; i < 500; i ++) {
x[i] = Math.random();
y[i] = Math.random() + 1;
}
var data = [
{
x: x,
y: y,
type: 'histogram2d'
}
];
Plotly.newPlot('myDiv', data);
)
This seems like pretty conventional behavior - am I missing an option in the docs somewhere to do this?
If there's no built-in option to do this, an acceptable alternative solution would be to manually set new z limits in a zoom callback, which is easy enough to implement per this example: http://codepen.io/plotly/pen/dogexw - in which case my question becomes, is there a convenience method to get the min and max z currently on display?
Thanks in advance,
plotly.js doesn't have a zoom-specific callback at the moment(follow this issue for updates).
One alternative would be to add a mode bar button updating the colorscale range:
Plotly.newPlot('myDiv', data, {}, {
modeBarButtonsToAdd: [{
name: 'click here to update the colorscale range',
click: function(graphData) {
var xRange = graphData.layout.xaxis.range,
yRange = graphData.layout.yaxis.range;
var zMin, zMax;
// code that would compute the colorscale range
// given xRange and yRange
// for example given these values:
zMin = 10;
zMax = 20;
Plotly.restyle('myDiv', {zmin: zMin, zmax: zMax});
}
}]
});
Complete example: http://codepen.io/etpinard/pen/JGvNjV
I'm using D3JS and I want an axis in x with this kind of values : 125, 250, 500, 1000 ... until 8000. So multiply by 2 my values each time.
So I tried a Quantize Scales but axis do not support it.
How can I do this ? Can I do a custom mathematical function like y = mx + b (where m = 2 in my case and b = 0) and use it in axis?
Here you can see my code
Podelo
The linear scale is pretty flexible if you mass in multiple values for the range and domain to create a polylinear scale:
tickWidth = (ChartWidth - padding)/7
xScale = d3.scale.linear()
.domain([0, 125, 250, 500, 1000, 2000, 4000, 8000])
.range(d3.range(8).map(function(d){ return d*tickWidth; }));
http://jsfiddle.net/h2juD/6/