Adding annotations between subplots in horizontal bar graph (Plotly javascript) - javascript

I am making a javascript plotly bar graph to represent system downtime and I want to add annotations between my subplots, like this:
Here's the fiddle for the plot code, and the code here as well:
<head>
<!-- Plotly.js -->
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
<div id="bar"></div>
</body>
var hoursDown, hoursOperational = [];
hoursDown = [8, 16, 8];
hoursOperational = hoursDown.map(x => 25 - x);
hoursDown2 = [10, 3, 3];
hoursOperational2 = hoursDown2.map(x => 25 - x);
var hoursDownTrace = {
x: hoursDown,
y: ["A", "B", "C"],
name: 'Down',
orientation: 'h',
marker: {
color: 'black',
},
type: 'bar',
width: .5
};
var hoursOperationalTrace = {
x: hoursOperational,
y: ["A", "B", "C"],
name: 'Operational',
orientation: 'h',
type: 'bar',
width: .2,
marker: {
color: 'green',
}
};
var hoursDownTrace2 = {
x: hoursDown2,
y: ["E", "F", "G"],
xaxis: 'x2',
yaxis: 'y2',
name: 'Down',
orientation: 'h',
marker: {
color: 'black',
},
type: 'bar',
width: .5
};
var hoursOperationalTrace2 = {
x: hoursOperational2,
y: ["E", "F", "G"],
name: 'Operational',
orientation: 'h',
type: 'bar',
width: .2,
xaxis: 'x2',
yaxis: 'y2',
marker: {
color: 'green',
}
};
var myData = [hoursDownTrace, hoursOperationalTrace, hoursDownTrace2, hoursOperationalTrace2];
var layout={
title: 'My Title',
barmode: 'stack',
xaxis: {side: 'top', bargap: 10},
xaxis2: {anchor: 'y2', side: 'top', bargap: 10},
xaxis3: {anchor: 'y3'},
yaxis: {domain: [0, 0.266]},
yaxis2: {domain: [0.366, 0.633]},
yaxis3: {domain: [0.733, 1]},
}
var annotations={
xref: 'paper',
yref: 'paper',
x: 0.01,
y: 0.9,
text: 'Annotation',
showarrow: false,
row: 3,
col: 1
}
Plotly.newPlot('bar', myData, layout);
Someone has done something similar in this answer but I wasn't able to integrate it into my code. I also tried several of the options from the plotly annotations documentation page to no luck.

Related

plotly two y-axis same position of zero-line

I want to plot two axis (bar + scatter) on a plotly chart with javascript, but I can't get the zero baseline of the second y-axis to align with the first axis.
Here is the result of the current version:
The Zero-line of the right y-axis (the scatter line) is higher than the zero-line of the left y-axis. I would want to have them on the same height in the plot, basically overlapping.
I create the Plotly object like this:
const trace1 = { x: dates, y: y1, name: 'item', type: 'bar' };
const trace2 = { x: dates, y: y1_cumsum, name: 'Total', yaxis: 'y2', type: 'scatter' };
Plotly.newPlot(MYDIV, [trace1,trace2], {
margin: {t: 0},
barmode: 'group',
hovermode: 'x unified',
yaxis: {title: 'item', dtick: 1},
yaxis2: {
title: 'total',
overlaying: 'y',
side: 'right'
},
showlegend: true,
legend: {
x: 0.25,
xanchor: 'right',
y: 1
}
});
I tried to change position in the config, but this does only affect the x-position, not where the y-axis starts. I can't find any suitable attribute in the docs (https://plotly.com/javascript/reference/layout/yaxis/) that would achieve that.
How can I set the position of the second y-axis to be the same as the first one?
Thanks.
Assuming you don't have negative values in your data, you can set layout.yaxis.rangemode = 'tozero'for one or both of your axes.
const trace1 = {
x: [3, 4, 5],
y: [0, 15, 13],
mode: 'markers+lines',
type: 'scatter',
yaxis: 'y2'
};
const trace2 = {
x: [3, 4, 5],
y: [1, 0, 3],
type: 'bar'
};
Plotly.newPlot('myDiv', [trace1,trace2], {
margin: {t: 0},
barmode: 'group',
hovermode: 'x unified',
yaxis: {title: 'item', dtick: 1},
yaxis2: {
title: 'total',
overlaying: 'y',
side: 'right',
rangemode: 'tozero'
},
showlegend: true,
legend: {
x: 0.25,
xanchor: 'right',
y: 1
}
});
<head>
<!-- Load plotly.js into the DOM -->
<script src='https://cdn.plot.ly/plotly-2.11.1.min.js'></script>
</head>
<body>
<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>
</body>

How to position legend on top instead of bottom in Plotly?

I want to display the legend on the top of chart, but under the title. I looked for the API, and did not find anything related changing position, but only setting orientation.
var myData = [
{
fcst_valid_local: "2013-01-04 22:23:00",
pop: 20,
temp: 38,
},
{
fcst_valid_local: "2013-02-04 22:23:00",
pop: 15,
temp: 39,
},
{
fcst_valid_local: "2013-03-04 22:23:00",
pop: 2,
rh: 70,
}
];
var data = [
{
x: myData.map(d => d.fcst_valid_local),
y: myData.map(d => d.temp),
type: 'line'
},
{
x: myData.map(d => d.fcst_valid_local),
y: myData.map(d => d.pop),
type: 'bar',
yaxis: 'y2'
}
];
var layout = {
title: 'Daily Forecast',
yaxis: {
autorange: true,
range: [0, 100],
},
yaxis2: {
range: [0, 100],
side: 'right',
overlaying: 'y',
type: 'linear'
},
legend: {orientation: 'h', side: 'top'}
};
Plotly.newPlot('myDiv', data, layout);
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="myDiv" style="width: 480px; height: 400px;"><!-- Plotly chart will be drawn inside this DIV --></div>
You can position the legend by setting its x and y values. For your graph it would be something like:
legend: {x: 0.4, y: 1.2}
var myData = [
{
fcst_valid_local: "2013-01-04 22:23:00",
pop: 20,
temp: 38,
},
{
fcst_valid_local: "2013-02-04 22:23:00",
pop: 15,
temp: 39,
},
{
fcst_valid_local: "2013-03-04 22:23:00",
pop: 2,
rh: 70,
}
];
var data = [
{
x: myData.map(d => d.fcst_valid_local),
y: myData.map(d => d.temp),
type: 'line'
},
{
x: myData.map(d => d.fcst_valid_local),
y: myData.map(d => d.pop),
type: 'bar',
yaxis: 'y2'
}
];
var layout = {
title: 'Daily Forecast',
yaxis: {
autorange: true,
range: [0, 100],
},
yaxis2: {
range: [0, 100],
side: 'right',
overlaying: 'y',
type: 'linear'
},
legend: {x: 0.4, y: 1.2}
};
Plotly.newPlot('myDiv', data, layout);
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="myDiv" style="width: 480px; height: 400px;">
add:
layout(legend = list(orientation = 'h', xanchor = "center", x = 0.5, y= 1))
to fit legend as horizontal, in the middle and at the top.

Plotly.js Create stacked and grouped bar chart

How to create barchart on Plotly.js with grouped and stacked bars? I need structure like that:
Barchart with stacked and grouped charts
It is possible to create a grouped-and-stacked bar chart in Plotly.js by creating each group as a subplot. It's not as simple as setting a top-level feature like 'barmode': 'stacked+grouped' but because it's more elemental it offers more options.
See https://community.plot.ly/t/combination-of-grouped-and-stacked-bar-chart/2154
Here each subplot references a shared common yaxis and its own xaxis. Each xaxis gets a "domain" which here means a portion of the overall bottom axis width. Here the first group gets [0.0, 0.33], the second [0.34, 0.66] and the third [0.67, 1.0]
Plotly.newPlot(
"myDiv",
[
{
x: ["A", "B", "C"],
y: [0.3, 0.35, 0.4],
type: "bar",
name: "series 1a",
xaxis: 'x1',
barmode: 'stack',
marker: {color: '#448'}
},
{
x: ["A", "B", "C"],
y: [0.6, 0.50, 0.40],
type: "bar",
name: "series 1b",
xaxis: 'x1',
barmode: 'stack', marker: {color: '#88C'}
},
{
x: ["A", "B", "C"],
y: [0.1, 0.15, 0.20],
type: "bar",
name: "series 1c",
xaxis: 'x1',
barmode: 'stack',
marker: {color: '#CCF'}
},
{
x: ["A", "B", "C"],
y: [0.3, 0.35, 0.4],
type: "bar",
name: "series 2a",
xaxis: 'x2',
barmode: 'stack', marker: {color: '#080'}
},
{
x: ["A", "B", "C"],
y: [0.25, 0.15, 0.05],
type: "bar",
name: "series 2b",
xaxis: 'x2',
barmode: 'stack', marker: {color: '#8c8'}
},
{
x: ["A", "B", "C"],
y: [0.45, 0.50, 0.55],
type: "bar",
name: "series 2c",
xaxis: 'x2',
barmode: 'stack', marker: {color: '#CFC'}
},
{
x: ["A", "B", "C"],
y: [0.3, 0.35, 0.4],
type: "bar",
name: "series 3a",
xaxis: 'x3',
barmode: 'stack', marker: {color: '#880'}
},
{
x: ["A", "B", "C"],
y: [0.6, 0.50, 0.40],
type: "bar",
name: "series 3b",
xaxis: 'x3',
barmode: 'stack', marker: {color: '#CC8'}
},
{
x: ["A", "B", "C"],
y: [0.1, 0.15, 0.20],
type: "bar",
name: "series 3c",
xaxis: 'x3',
barmode: 'stack', marker: {color: '#FFC'}
},
],
{
barmode: "stack",
yaxis: {tickformat: '%'},
xaxis: {
domain: [0, 0.33],
anchor: 'x1',
title: 'Apples'
},
xaxis2: {
domain: [0.33, 0.66],
anchor: 'x2', title: 'Pears'
},
xaxis3: {
domain: [0.67, 1.0],
anchor: 'x3', title: 'Cherries'
}
}
);
Newer answer as of 2021
Plotly.js now allows nested categorical axes without needing to create subplots with dedicated axes (see https://plotly.com/python/categorical-axes/)
The above chart has
Plotly.newPlot(
"myDiv",
[
{
x: [
["Apples","Apples","Apples","Pears","Pears","Pears","Dates","Dates","Dates"],
["East", "South","West","East", "South","West","East", "South","West"]
],
y: [0.3, 0.35, 0.4,0.3, 0.35, 0.4,0.3, 0.35, 0.4],
type: "bar",
name: "Snack",
marker: {color: '#448'}
},
{
x: [
["Apples","Apples","Apples","Pears","Pears","Pears","Dates","Dates","Dates"],
["East", "South","West","East", "South","West","East", "South","West"]
],
y: [0.6, 0.50, 0.40,0.25, 0.15, 0.05,0.6, 0.50, 0.40],
type: "bar",
name: "Ingredient",
marker: {color: '#88C'}
},
{
x: [
["Apples","Apples","Apples","Pears","Pears","Pears","Dates","Dates","Dates"],
["East", "South","West","East", "South","West","East", "South","West"]
],
y: [0.1, 0.15, 0.20,0.45, 0.50, 0.55,0.1, 0.15, 0.20],
type: "bar",
name: "Garnish",
marker: {color: '#CCF'}
}
],
{
barmode: "stack",
yaxis: {tickformat: '%'},
xaxis: {
type: 'multicategory',
title: 'Fruit'
},
yaxis: {
type: '',
range: [0,1],
tickformat: "0.0%"
}
}
);

Plotly: create horizontal timeline

That's what i have so far...
Plotly.plot('graph', [{
type: 'bar',
y: [1,0,0],
x: [1,2,1],
orientation: 'h',
base: [0,2,5]
}, {
type: 'bar',
y: [1,1,1],
x: [2,1,2],
orientation: 'h',
base: [0,3,5]
}])
<head>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
<div id="graph"></div>
</body>
How can I use dates on the horizontal axis instead of numeric values?
Finally timeline was created!
Codepen.io link: https://codepen.io/elv1s42/pen/bKVEJb
Sharing with everyone in case you will need it:
var layout = {
height: 300,
yaxis: {
showgrid: false,
zeroline: false,
showline: false,
showticklabels: false
}
};
Plotly.plot('graph', [{
x: ['2017-11-04 22:23:00', '2017-11-04 22:24:00'],
y: [1, 1],
type: 'scatter',
opacity: 0.5,
line: { color: 'red', width: 20 },
mode: 'lines',
name: 'First event'
},{
x: ['2017-11-04 22:24:00', '2017-11-04 22:24:30'],
y: [1, 1],
type: 'scatter',
opacity: 0.5,
line: { color: 'green', width: 20 },
mode: 'lines',
name: 'Second event'
},{
x: ['2017-11-04 22:25:00', '2017-11-04 22:26:00'],
y: [1, 1],
type: 'scatter',
opacity: 0.5,
line: { color: 'yellow', width: 20 },
mode: 'lines',
name: 'Third event'
}], layout)
<head>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
<div id="graph"></div>
</body>
You need to use x axis type property. you can specify x axis as date type:
Like
x:{type:"date"}
I updated your example. please take a look at the below example
Plotly.plot('graph', [{
type: 'bar',
y: [1,0,0],
x: ['2000-01-01', '2000-01-02', '2000-01-03'],
orientation: 'v',
base: [0,2,5]
}, {
type: 'bar',
y: [1,1,1],
x: ['2000-01-01', '2000-01-02', '2000-01-03'],
orientation: 'v',
base: [0,3,5]
}],{xaxis:{type:"date"}})
<head>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
<div id="graph"></div>
</body>

How to add a name or label to shapes in plotly?

I have created a simple plotly line graph as follows:
var trace1 = {
x: [1, 2, 3, 4],
y: [10, 15, 13, 17],
type: 'scatter'
};
var layout = {
xaxis:{
title:"x-axis",
tickangle:45,
rangemode:'nonnegative',
autorange:true,
exponentformat: "none"
},
yaxis:{
title: "Time",
tickangle:45,
rangemode:'nonnegative',
range:[0,20],
autorange: false
},
shapes: [
{
type: 'line',
xref: 'paper',
x0: 0,
y0: threshold1,
x1: 1,
y1: threshold1,
line:{
color: 'rgb(255, 0, 0)',
width: 2,
dash:'dot'
},
},
{
type: 'line',
xref: 'paper',
x0: 0,
y0: threshold2,
x1: 1,
y1: threshold2,
line:{
color: 'rgb(0, 255, 0)',
width: 2,
dash:'dot'
},
}
]
};
Plotly.newPlot(myDiv,[trace1],layout);
Now, I want to add a name or label to the threshold1 and threshold2 that I have created in 'shapes' under 'layout'. I searched the plotly JS documentation but did'nt get anything useful there. How can I do this. Any help would be appreciated.
You could create another trace with mode: 'text'. There is certainly more than one way of doing it but this one is simple and does not need complicated data replication.
var threshold1 = 12;
var threshold2 = 16;
var offset = 0.75;
var trace1 = {
x: [1, 2, 3, 4],
y: [10, 15, 13, 17],
type: 'scatter'
};
var trace2 = {
x: [Math.min.apply(Math, trace1.x) + offset,
Math.max.apply(Math, trace1.x) - offset],
y: [threshold1 - offset, threshold2 - offset],
mode: 'text',
text: ['lower threshold', 'upper threshold'],
showlegend: false
}
var layout = {
xaxis: {
title: "x-axis",
tickangle: 45,
rangemode: 'nonnegative',
autorange: true,
exponentformat: "none"
},
yaxis: {
title: "Time",
tickangle: 45,
rangemode: 'nonnegative',
range: [0, 20],
autorange: false
},
shapes: [{
type: 'line',
xref: 'paper',
x0: 0,
y0: threshold1,
x1: 1,
y1: threshold1,
line: {
color: 'rgb(255, 0, 0)',
width: 2,
dash: 'dot'
},
}, {
type: 'line',
xref: 'paper',
x0: 0,
y0: threshold2,
x1: 1,
y1: threshold2,
line: {
color: 'rgb(0, 255, 0)',
width: 2,
dash: 'dot'
},
}]
};
Plotly.newPlot(myDiv, [trace1, trace2], layout);
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id='myDiv'></div>
You can use annotations:
layout.annotations = [
{
showarrow: false,
text: "Your text here",
align: "right",
x: 1,
xanchor: "right",
y: threshold1,
yanchor: "bottom"
},
{
showarrow: false,
text: "Your second text here",
align: "right",
x: 1,
xanchor: "right",
y: threshold2,
yanchor: "bottom"
}
],
Add just name property to your trace like
name = 'Xyz'
This Link might help you to fix it out.

Categories

Resources