I have been trying to utilize the tickvals/ticktext on plotlyjs to be able to show duplicate values on a graph for the xaxis. It works in the aspect of separating the data (having multiple duplicate values be on the xaxis, but a 1:1 data point) -- the issue that I am having is that no xaxis tick marks or xaxis labels show up for the ticks.
Here is a code pen of my problem:
https://codepen.io/hiquetj/pen/yLeBNjJ
Here is the code for easier reading:
var trace1 = {
y: [1323,1070,849,1312,1214,1264,680,2006,1625,0,1199,1770,1880,708,603,649,1384,732,2312,92,1377,1125,1219,1757,1207,2397,1190,1818,2846,1200,1685,1563,1203,1059,820,4303,812,3640,1924,4185,1269,2263,1140,1210,1638,1362,4915,1594,683,1222],
mode: 'markers'
};
var trace2 = {
y: [5870,1574,1372,2093,1361,1388,615,1927,947,,1040,,,638,546,542,1051,637,4161,289,1103,0,1308,1658,1340,2198,1245,1568,2392,1297,1583,1281,1282,697,482,3633,653,3233,2096,3815,1401,2116,867,1232,1420,1010,4091,478,208,1262],
mode: 'lines'
};
var trace3 = {
y: [1141,1324,424,668,414,407,494,1763,1100,,522,360,108,474,145,621,689,234,154,40,303,364,407,1133,347,1527,358,1745,1223,345,1131,1024,365,754,614,1894,287,5332,363,568,335,1545,1294,383,1255,1107,2090,612,66,390],
mode: 'lines+markers'
};
var data = [ trace1, trace2, trace3 ];
var layout = {
xaxis: {
ticktext: [24346247,24346247,24346247,24346247,24332892,24332892,24332892,24332670,24332670,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24316962,24316962,24316962,24290013,24290013,24290013,24290013,24290013,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933],
tickvals: [24346247,24346247,24346247,24346247,24332892,24332892,24332892,24332670,24332670,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24316962,24316962,24316962,24290013,24290013,24290013,24290013,24290013,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933],
},
};
Plotly.newPlot('myDiv', data, layout, {showSendToCloud: true});
Example of x axis labels not showing up through codepen.
If you do not set x values for your traces, they are automatically assigned x values from 0 to n. Your ticktexts will therefore only be visible if your tickval array is [0, 1, 2, 3, ..., n], see this jsFiddle: https://jsfiddle.net/9okdx4b2/
I am playing with d3.js to draw a curve like the below. The below was drawn in Excel. As I am trying to achive the below result, I am facing an issue where my Y axis data lives in nested array and I am having a trouble to expose that.
Using the code below, I am able to get the x axis but whenever I try to bring my y axis, the data would come up as undefined.
var w = 900;
var h = 180;
var margin = {
'top': 5,
'right': 20,
'bottom': 20,
'left': 50
};
//creating axis
function buildLine(data) {
var xScale = d3.scale.linear()
.domain([100, d3.max(data, function(d) {
return d.spend;
})])
.range([margin.left, w - margin.right], 100);
/*var yScale=d3.scale.linear()
.domain([0,d3.max(data.arr,function(d){return d.y})])
.range([h-padding,10])
.nice();*/ //getting error as it is nested
var xAxisGen = d3.svg.axis().scale(xScale).orient("bottom").ticks(15);
/* var yAxisGen=d3.svg.axis().scale(yScale).orient("left");*/
var svg = d3.select("body").append("svg").attr({
width: w,
height: h
});
/*var yAxis= svg.append("g")
.call(yAxisGen)
.attr("class","axis")
.attr("transorm","translate("+padding+",0)");*/
var xAxis = svg.append("g")
.call(xAxisGen)
.attr("class", "axis")
.attr("transorm", "translate(" + padding + ",0)");
}
d3.json("sample-data.json", function(error, data) {
//check the file loaded properly
if (error) { //is there an error?
console.log(error); //if so, log it to the console
} else { //If not we're golden!
//Now show me the money!
ds = data; //put the data in the global var
}
buildLine(data);
data.forEach(function(jsonData) {
var lineData = d3.range(0, jsonData.spend, 100)
.map(x => [x, jsonData.alpha * (1 - 2.71828 * (-jsonData.beta * x))]);
/* console.log("this is the data:",lineData);*/
//i think line date returns an array with each item in it also an array of 2 items
var arr = [];
for (var i = 0; i < lineData.length; i++) {
arr.push({
x: lineData[i][0],
y: lineData[i][1]
});
}
jsonData.arr = arr;
console.log(jsonData);
});
});
*********The data structure as below ******************
So there is one object and there needs to be a line for each object and therefore each object has nested array which holds x, y and I need to get the Y to build y.axis. My brain feels like a marshmallow right now.
{x: 10000, y: 286.89585120000004}
{x: 10100, y: 288.364809712}
{x: 10200, y: 289.833768224}
{x: 10300, y: 291.30272673600007}
{x: 10400, y: 292.771685248}
I have an array of data in this format:
var data = [{x:0,y1:1, y2:2}, {x:1, y1:2, y2:2},...]
I'd like to use d3 to plot this with the help of the line function.
So, I created 2 paths on my svg container...
var path1 = svg.append("path");
var path2 = svg.append("path");
Now, to draw the first line, I have used:
var lineFunction = d3.svg.line()
.x(function(d){return d.x}
.y(function(d){return d.y1}
.interpolate("linear")
and
path1.attr("d", lineFunction(data))
And that worked great. However, how do I now draw the second line? I can of course create a new lineFunction that returns d.y2 for the y value, but that goes completely against the DRY principle. I think my workflow is not quite the right way to do it, so may I ask how are you actually supposed to do it? In other words, how should I create a line function that will work with both the y1 and y2 data?
To expand on the commend from #Lars, the trick here is to first pivot your data to be an array of objects that each represents an individual line.
var newData = [
{
name: "y1",
points: [ { x:0, y:1},{x:1,y:2}]
},
{
name: "y2",
points: [ { x:0, y:2},{x:1,y:2}]
},
];
Your lineFunction can then operate generically on x and y:
var lineFunction = d3.svg.line()
.x(function(d){return d.x}
.y(function(d){return d.y}
.interpolate("linear")
You can then bind this data to the elements in your visualisation and add a path for each data entry:
var lines = svg.selectAll(".line").data(newData);
lines.enter().append("path")
.attr("class","line")
.attr("d",function(d) {
return lineFunction(d.points);
});