Hello Community,
i have currently a small issue that i can not solve by my own…
I am using the Billiballa/bilibala-echarts-panel: Echarts panel for grafana (github.com) in Grafana and i need to display multiple boxplots over multiple timegroups.
Currently the boxplots are all shown in the last time group. That should not be the case any more and every boyplot shall be shown in the dedicated time group
Can anybody support or does anybody have experience with that panel plugin?
const xAxisData = [];
const boxPlotSeriesByTimeGroup = {};
data.series.forEach((s) => {
const sData = Array.from(s.fields.find((f) => f.name === 'value_double').values.buffer);
const sTime = Array.from(s.fields.find((f) => f.name === 'systime').values.buffer);
// Group the timestamps by 30 minutes
const groupedTime = sTime.reduce((acc, t) => {
const date = new Date(t);
const roundedMinutes = Math.round(date.getMinutes() / 30) * 30;
date.setMinutes(roundedMinutes);
const timeGroup = `${date.getMonth() + 1}-${date.getDate()} ${date.getHours()}:${date.getMinutes().toString().padStart(2, '0')}`;
if (!acc[timeGroup]) {
acc[timeGroup] = [];
}
acc[timeGroup].push(t);
return acc;
}, {});
// Loop over the time groups and calculate box plot statistics
Object.entries(groupedTime).forEach(([timeGroup, timestamps]) => {
// Convert timestamps to x-axis data
xAxisData.push(timeGroup.split(' ').join('\n'));
// Calculate box plot statistics
const timeGroupData = sData.filter((d, i) => timestamps.includes(sTime[i]));
timeGroupData.sort((a, b) => a - b);
const q1 = timeGroupData[Math.floor(timeGroupData.length * 0.25)];
const q2 = timeGroupData[Math.floor(timeGroupData.length * 0.5)];
const q3 = timeGroupData[Math.floor(timeGroupData.length * 0.75)];
const iqr = q3 - q1;
const min = timeGroupData[0];
const max = timeGroupData[timeGroupData.length - 1];
const whiskerMin = timeGroupData.find((d) => d >= q1 - 1.5 * iqr);
const whiskerMax = timeGroupData.find((d) => d <= q3 + 1.5 * iqr);
const boxData = [min, q1, q2, q3, max];
const whiskerData = [whiskerMin, whiskerMax];
// Add box plot series for the time group
if (!boxPlotSeriesByTimeGroup[timeGroup]) {
boxPlotSeriesByTimeGroup[timeGroup] = [];
}
boxPlotSeriesByTimeGroup[timeGroup].push({
data: [boxData, whiskerData],
itemStyle: {
color: 'yellow',
},
type: 'boxplot',
tooltip: {
formatter: (params) => {
if (params.componentType === 'series') {
const {
value
} = params;
if (value instanceof Array) {
return `Min: ${value[0]}<br>Q1: ${value[1]}<br>Median: ${value[2]}<br>Q3: ${value[3]}<br>Max: ${value[4]}`;
} else {
return `Value: ${value}`;
}
}
},
},
});
});
});
xAxisData.sort();
const axisOption = {
axisTick: {
show: true,
},
axisLine: {
show: true,
},
axisLabel: {
color: 'rgba(128, 128, 128, .9)',
formatter: (value) => value.toString().split('\n').join(' '),
},
splitLine: {
lineStyle: {
color: 'rgba(128, 128, 128, .2)',
},
},
};
const series = Object.entries(boxPlotSeriesByTimeGroup).flatMap(([timeGroup, boxPlotSeries]) => {
return boxPlotSeries.map((seriesData) => {
return {
data: seriesData.data,
type: 'boxplot',
itemStyle: {
color: 'yellow',
},
tooltip: {
formatter: (params) => {
if (params.componentType === 'series') {
const {
value
} = params;
if (value instanceof Array) {
return `Min: ${value[0]}<br>Q1: ${value[1]}<br>Median: ${value[2]}<br>Q3: ${value[3]}<br>Max: ${value[4]}`;
} else {
return `Value: ${value}`;
}
}
},
},
};
});
});
return {
backgroundColor: 'transparent',
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
},
legend: {
left: '0',
bottom: '0',
textStyle: {
color: 'rgba(128, 128, 128, .9)',
},
},
xAxis: Object.assign({
type: 'category',
data: xAxisData,
max: xAxisData.length - 1,
inverse: false,
},
axisOption
),
yAxis: Object.assign({
type: 'value',
min: 'dataMin',
axisLabel: {
formatter: '{value}',
},
},
axisOption
),
grid: {
left: 0,
right: 16,
top: 6,
bottom: 24,
containLabel: true,
},
series,
};