I am using echarts (js). Is there any way to connect the dot of the scatter plot with the 0 value of the y axis? It should be like a pacf plot (https://www.statsmodels.org/stable/_images/graphics_tsa_plot_pacf.png)
It should be something like this:
In order to allow the reproducibility, this is the chart option:
let data = {
"schema": {
"fields": [
{
"name": "tamaño",
"type": "string"
},
{
"name": "expo",
"type": "number"
},
{
"name": "impo",
"type": "number"
},
{
"name": "saldo",
"type": "number"
}
],
"pandas_version": "1.4.0"
},
"data": [
{
"tamaño": "Micro",
"expo": 1988766908.4407976,
"impo": 4256928697.57,
"saldo": -2268161789.129203
},
{
"tamaño": "Pequeña",
"expo": 3681585633.166469,
"impo": 7548231175.14,
"saldo": -3866645541.9735312
},
{
"tamaño": "Mediana",
"expo": 7626112142.6330385,
"impo": 12756460382.520002,
"saldo": -5130348239.886964
},
{
"tamaño": "Grande",
"expo": 64637850302.33969,
"impo": 38622133149.46996,
"saldo": 26015717152.869728
}
]
}
let categories = data.data.map(item => item.tamaño);
let expoData = data.data.map(item => item.expo/ 1_000_000);
let impoData = data.data.map(item => -item.impo/ 1_000_000);
let saldoData = data.data.map(item => item.saldo/ 1_000_000);
let lineData = saldoData.map((d, i) => [[0, d], [0, i]]);
console.log(lineData)
export var optionActividadIntercambio = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
// }
},
legend: {
bottom: 10,
},
xAxis: [
{
type: 'value',
},
],
yAxis: [
{
type: 'category',
data: categories,
axisTick: {
show: false
}
}
],
series: [
{
name: 'Exportaciones',
type: 'bar',
data: expoData,
stack: 'Total',
emphasis: {
focus: 'series'
},
label: {
show: false,
position: 'inside'
},
itemStyle:{color:"rgba(238,178,9,1)"}
},
{
name: 'Importaciones',
type: 'bar',
data: impoData,
stack: 'Total',
emphasis: {
focus: 'series'
},
label: {
show: false
},
itemStyle:{color:"rgba(163,133,165,1)"}
},
{
name: 'Saldo',
type: 'scatter',
data: saldoData,
// stack: 'Total',
emphasis: {
focus: 'series'
},
label: {
show: false,
position: 'left'
}
},
{
name: 'Saldo Line',
type: 'line',
data: lineData,
showSymbol: true, // don't show symbols for line series
lineStyle: {
width: 10 // thinner line
}
}
]
};
Help is much appreciated, since I've passed hours reading the documentation😢.
Best regards
You already defined the line in your chart, but the coordinates are wrong; in a first attempt, the coordinates could be thought as:
let lineData = saldoData.flatMap((d, i) => [[d, i], [0, i]]);
This creates a multi-segment that goes continuously from the first data to the last. In order to get rid of the unwanted connections between levels, one could simply introduce a null
point in between:
let lineData = saldoData.flatMap((d, i) => [[d, i], [0, i], []]);
which interrupts the line as intended in conjunction with keeping the default conectNulls
: false
.
And with tweaking the visual properties of the line, one can have this snippet:
const dom = document.getElementById('chart-container');
const myChart = echarts.init(dom, null, {
renderer: 'canvas',
useDirtyRect: false
});
const data = {
"schema": {
"fields": [{
"name": "tamaño",
"type": "string"
},
{
"name": "expo",
"type": "number"
},
{
"name": "impo",
"type": "number"
},
{
"name": "saldo",
"type": "number"
}
],
"pandas_version": "1.4.0"
},
"data": [{
"tamaño": "Micro",
"expo": 1988766908.4407976,
"impo": 4256928697.57,
"saldo": -2268161789.129203
},
{
"tamaño": "Pequeña",
"expo": 3681585633.166469,
"impo": 7548231175.14,
"saldo": -3866645541.9735312
},
{
"tamaño": "Mediana",
"expo": 7626112142.6330385,
"impo": 12756460382.520002,
"saldo": -5130348239.886964
},
{
"tamaño": "Grande",
"expo": 64637850302.33969,
"impo": 38622133149.46996,
"saldo": 26015717152.869728
}
]
}
let categories = data.data.map(item => item.tamaño);
let expoData = data.data.map(item => item.expo / 1_000_000);
let impoData = data.data.map(item => -item.impo / 1_000_000);
let saldoData = data.data.map(item => item.saldo / 1_000_000);
let lineData = saldoData.flatMap((d, i) => [[d, i], [0, i], []]);
const optionActividadIntercambio = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
},
legend: {
bottom: 10,
},
xAxis: [{
type: 'value',
},],
yAxis: [{
type: 'category',
data: categories,
axisTick: {
show: false
}
}],
series: [{
name: 'Exportaciones',
type: 'bar',
data: expoData,
stack: 'Total',
emphasis: {
focus: 'series'
},
label: {
show: false,
position: 'inside'
},
itemStyle: {
color: "rgba(238,178,9,1)"
}
},
{
name: 'Importaciones',
type: 'bar',
data: impoData,
stack: 'Total',
emphasis: {
focus: 'series'
},
label: {
show: false
},
itemStyle: {
color: "rgba(163,133,165,1)"
}
},
{
name: 'Saldo',
type: 'scatter',
data: saldoData,
emphasis: {
focus: 'series'
},
label: {
show: false,
position: 'left'
}
},
{
name: 'Saldo Line', // no name to exclude from legend
type: 'line',
data: lineData,
showSymbol: false,
itemStyle: {
opacity: 0 // to remove line ends from legend
},
lineStyle: {
color: '#000',
width: 2
},
tooltip: {
show: false // remove redundant info from tooltip
},
label: {
show: false
}
}
]
};
myChart.setOption(optionActividadIntercambio);
window.addEventListener('resize', myChart.resize);
#chart-container {
position: relative;
height: 100vh;
overflow: hidden;
}
<div id="chart-container"></div>
<script src="https://fastly.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
The same in jsFiddle.
Now, since we have the line series, we can use that to create both the line and the point (so remove the scatter
series). The only difficulty would be to show only one of the points at the end of the line; that can be done using
the fact that symbol
(as well as symbolSize
) can be given functions as values, so they can be changed from
point to point. For example,
symbol: value => value[0] ? 'circle' : 'none'
will make a circle only for those points that have a non-zero value. Full code in jsFiddle
If zero date values are possible, a safer solution would be to add the symbol in the data point, as the third coordinate:
let lineData = saldoData.flatMap((d, i) => [[d, i, 'circle'], [0, i], []]);
with
symbol: value => value[2] || 'none',
Full code in jsFiddle.
Another possibility, with some advantages, would be to make the line as a markLine
of the scatter series. The data for the markLine
could be constructed as:
let markLineData = saldoData.map((d, i) => [{coord: [d, i]}, {coord: [0, i]}]);
and with that the markLine
option inside the scatter
series would be:
markLine:{
symbol: 'none',
lineStyle:{
color: '#000',
type: 'solid',
width: 2
},
data: markLineData
}
Full code in jsFiddle.