Related
I have an Django app and need some datavisualization and I am blocked with ORM.
I have a models Orders with a field created_at and I want to present data with a diagram bar (number / year-month) in a dashboard template.
So I need to aggregate/annotate data from my model but did find a complete solution.
I find partial answer with TruncMonth and read about serializers but wonder if there is a simpliest solution with Django ORM possibilities...
In Postgresql it would be:
SELECT date_trunc('month',created_at), count(order_id) FROM "Orders" GROUP BY date_trunc('month',created_at) ORDER BY date_trunc('month',created_at);
"2021-01-01 00:00:00+01" "2"
"2021-02-01 00:00:00+01" "3"
"2021-03-01 00:00:00+01" "3"
...
example
1 "2021-01-04 07:42:03+01"
2 "2021-01-24 13:59:44+01"
3 "2021-02-06 03:29:11+01"
4 "2021-02-06 08:21:15+01"
5 "2021-02-13 10:38:36+01"
6 "2021-03-01 12:52:22+01"
7 "2021-03-06 08:04:28+01"
8 "2021-03-11 16:58:56+01"
9 "2022-03-25 21:40:10+01"
10 "2022-04-04 02:12:29+02"
11 "2022-04-13 08:24:23+02"
12 "2022-05-08 06:48:25+02"
13 "2022-05-19 15:40:12+02"
14 "2022-06-01 11:29:36+02"
15 "2022-06-05 02:15:05+02"
16 "2022-06-05 03:08:22+02"
expected result
[
{
"year-month": "2021-01",
"number" : 2
},
{
"year-month": "2021-03",
"number" : 3
},
{
"year-month": "2021-03",
"number" : 3
},
{
"year-month": "2021-03",
"number" : 1
},
{
"year-month": "2021-04",
"number" : 2
},
{
"year-month": "2021-05",
"number" : 3
},
{
"year-month": "2021-06",
"number" : 3
},
]
I have done this but I am not able to order by date:
Orders.objects.annotate(month=TruncMonth('created_at')).values('month').annotate(number=Count('order_id')).values('month', 'number').order_by()
<SafeDeleteQueryset [
{'month': datetime.datetime(2022, 3, 1, 0, 0, tzinfo=<UTC>), 'number': 4},
{'month': datetime.datetime(2022, 6, 1, 0, 0, tzinfo=<UTC>), 'number': 2},
{'month': datetime.datetime(2022, 5, 1, 0, 0, tzinfo=<UTC>), 'number': 1},
{'month': datetime.datetime(2022, 1, 1, 0, 0, tzinfo=<UTC>), 'number': 5},
{'month': datetime.datetime(2021, 12, 1, 0, 0, tzinfo=<UTC>), 'number': 1},
{'month': datetime.datetime(2022, 7, 1, 0, 0, tzinfo=<UTC>), 'number': 1},
{'month': datetime.datetime(2021, 9, 1, 0, 0, tzinfo=<UTC>), 'number': 2},
'...(remaining elements truncated)...'
]>
Try adding the order_by on the original field if you have multi-year data.
from django.db.models import Sum
from django.db.models.functions import TruncMonth
Orders.objects.values(month=TruncMonth('created_at')).
order_by("created_at").annotate(Sum('number')
kendo version 2015.1.429
I can't figure out why this doesn't work. I've been fighting with it for hours to no avail. I've tried all sorts of variations on the axis name, etc.
Any ideas?
#(Html.Kendo().Chart<OTIS.AppServ.Reporting.ViewModels.ItemDailyForecast>()
.Name("chart_ItemForecastByDay")
.Theme("Silver")
.HtmlAttributes(new { #class = "widgetFullWidth" })
.Title("Item Daily Forecast")
.Legend(legend => legend
.Position(ChartLegendPosition.Bottom)
.Visible(true)
)
.Events(events => events
.Render("hideChartLoadingImage")
)
.AutoBind(true)
.DataSource(ds => ds
.Read(read => read.Action("GetItemForecastByDay", "InventoryReports", new { area = "Reporting", intItemId = Model, intDaysOut = 90}))
.Sort(sort =>
{
sort.Add(model => model.Date).Ascending();
})
)
.Series(series =>
{
series
.Line(model => model.DailyUnitBalanceQty)
//.Column(model => model.DailyUnitBalanceQty)
.Name("Units Avail")
//.Color("#5cbe2d")
.Aggregate(ChartSeriesAggregate.Sum)
.Axis("Axis1")
.Tooltip(tooltip => tooltip
.Visible(true)
.Template("#= series.name # (#= kendo.toString(category, 'd') #, #= kendo.format('{0:n0}', value) #)")
)
;
})
.Series(series =>
{
series
.Line(model => model.DailyDaysOnHandQty)
//.Column(model => model.DailyDaysOnHandQty)
.Name("Days On Hand")
//.Color("#5cbe2d")
.Aggregate(ChartSeriesAggregate.Sum)
.Axis("Axis1")
.Tooltip(tooltip => tooltip
.Visible(true)
.Template("#= series.name # (#= kendo.toString(category, 'd') #, #= kendo.format('{0:n0}', value) #)")
)
;
})
.Series(series =>
{
series
.Column(model => model.DailyReceiptQty)
.Name("Receipt Qty")
//.Color("#5cbe2d")
.Aggregate(ChartSeriesAggregate.Sum)
.Axis("Axis1")
.Spacing(0.0)
.Gap(0.0)
.Tooltip(tooltip => tooltip
.Visible(true)
.Template("#= series.name # (#= kendo.toString(category, 'd') #, #= kendo.format('{0:n0}', value) #)")
)
;
})
.CategoryAxis(axis => axis
.Date()
.BaseUnit(ChartAxisBaseUnit.Days)
.Categories(model => model.Date)
.Labels(labels => {
labels.Rotation(90);
}
)
.AxisCrossingValue(0, 1000)
)
.ValueAxis(axis => axis
.Numeric("Axis1")
.Labels(labels => labels.Format("{0:n0}"))
.PlotBands(bands =>
{
//bands.Add().From(-10).To(50).Color("#c00").Opacity(0.3);
bands.Add().From(49).To(50).Color("#c00").Opacity(0.8);
})
)
.ChartArea(chartArea => chartArea
.Background("transparent")
.Height(300)
)
.PlotArea(plotArea => plotArea
.Background("transparent")
//.Margin(40)
)
)
<script>
$(function(){
var chart = $("#chart_ItemForecastByDay").data("kendoChart");
options["categoryAxis"] = { plotBands: [{ from: "3/17/2019", to: "3/20/2019", color: "green", opacity: 0.3 }] };
options["yAxis"] = { plotBands: [{ from: 20, to: 30, color: "blue", opacity: 0.3 }] };
options["valueAxis"] = { plotBands: [{ from: 10, to: 20, color: "yellow", opacity: 0.3 }] };
options["Axis1"] = { plotBands: [{ from: 10, to: 20, color: "yellow", opacity: 0.3 }] };
chart.setOptions(options);
}
</script>
For Categorical Charts types we should use the categoryAxis and valueAxis plotBands.
<script>
var stats = [
{ value: 48, date: new Date("2014/01/01") },
{ value: 50, date: new Date("2014/01/02") },
{ value: 55, date: new Date("2014/01/03") },
{ value: 35, date: new Date("2014/01/04") },
{ value: 30, date: new Date("2014/01/05") },
{ value: 30, date: new Date("2014/01/20") },
{ value: 50, date: new Date("2014/01/21") },
{ value: 45, date: new Date("2014/01/22") },
{ value: 40, date: new Date("2014/01/23") },
{ value: 35, date: new Date("2014/01/24") },
{ value: 40, date: new Date("2014/01/25") },
{ value: 42, date: new Date("2014/01/26") },
{ value: 40, date: new Date("2014/01/27") },
{ value: 35, date: new Date("2014/01/28") },
{ value: 43, date: new Date("2014/01/29") },
{ value: 38, date: new Date("2014/01/30") },
{ value: 30, date: new Date("2014/01/31") }
];
$("#chart").kendoChart({
dataSource: {
data: stats
},
series: [{
type: "column",
aggregate: "avg",
field: "value",
categoryField: "date"
}],
categoryAxis: {
type: "date",
majorGridLines: {
visible: false
}
},
valueAxis: {
line: {
visible: false
}
}
});
$(function(){
var chart = $("#chart").data("kendoChart");
var options = {};
var fromDate = new Date("2014/01/15");
var toDate = new Date("2014/01/20");;
options["categoryAxis"] = { plotBands: [{ from: fromDate, to: toDate, color: "green", opacity: 0.3 }] };
options["valueAxis"] = { plotBands: [{ from: 10, to: 20, color: "yellow", opacity: 0.3 }] };
chart.setOptions(options);
});
</script>
While for the Scatter Chart types we should use xAxis and yAxis plotBands
<script>
function createChart() {
$("#chart").kendoChart({
title: {
text: "Rainfall - Wind Speed"
},
legend: {
position: "bottom"
},
seriesDefaults: {
type: "scatter"
},
series: [{
name: "January 2008",
data: [
[16.4, 5.4], [21.7, 2], [25.4, 3], [19, 2], [10.9, 1], [13.6, 3.2], [10.9, 7.4], [10.9, 0], [10.9, 8.2], [16.4, 0], [16.4, 1.8], [13.6, 0.3], [13.6, 0], [29.9, 0], [27.1, 2.3], [16.4, 0], [13.6, 3.7], [10.9, 5.2], [16.4, 6.5], [10.9, 0], [24.5, 7.1], [10.9, 0], [8.1, 4.7], [19, 0], [21.7, 1.8], [27.1, 0], [24.5, 0], [27.1, 0], [29.9, 1.5], [27.1, 0.8], [22.1, 2]]
},{
name: "January 2009",
data: [
[6.4, 13.4], [1.7, 11], [5.4, 8], [9, 17], [1.9, 4], [3.6, 12.2], [1.9, 14.4], [1.9, 9], [1.9, 13.2], [1.4, 7], [6.4, 8.8], [3.6, 4.3], [1.6, 10], [9.9, 2], [7.1, 15], [1.4, 0], [3.6, 13.7], [1.9, 15.2], [6.4, 16.5], [0.9, 10], [4.5, 17.1], [10.9, 10], [0.1, 14.7], [9, 10], [2.7, 11.8], [2.1, 10], [2.5, 10], [27.1, 10], [2.9, 11.5], [7.1, 10.8], [2.1, 12]]
},{
name: "January 2010",
data: [
[21.7, 3], [13.6, 3.5], [13.6, 3], [29.9, 3], [21.7, 20], [19, 2], [10.9, 3], [28, 4], [27.1, 0.3], [16.4, 4], [13.6, 0], [19, 5], [16.4, 3], [24.5, 3], [32.6, 3], [27.1, 4], [13.6, 6], [13.6, 8], [13.6, 5], [10.9, 4], [16.4, 0], [32.6, 10.3], [21.7, 20.8], [24.5, 0.8], [16.4, 0], [21.7, 6.9], [13.6, 7.7], [16.4, 0], [8.1, 0], [16.4, 0], [16.4, 0]]
}],
xAxis: {
max: 35,
title: {
text: "Wind Speed [km/h]"
},
crosshair: {
visible: true,
tooltip: {
visible: true,
format: "n1"
}
}
},
yAxis: {
min: -5,
max: 25,
title: {
text: "Rainfall [mm]"
},
axisCrossingValue: -5,
crosshair: {
visible: true,
tooltip: {
visible: true,
format: "n1"
}
}
}
});
var chart = $("#chart").data("kendoChart");
var options = {};
var fromDate = new Date("2014/01/15");
var toDate = new Date("2014/01/20");;
options["xAxis"] = { plotBands: [{ from: 10, to: 20, color: "yellow", opacity: 0.3 }] };
options["yAxis"] = { plotBands: [{ from: -5, to: 0, color: "red", opacity: 0.3 }] };
chart.setOptions(options);
}
$(document).ready(createChart);
$(document).bind("kendo:skinChange", createChart);
</script>
I'm Working on Chart.js, wanted to implement Select All and Unselect All option for labels. I'm trying to find it out but couldn't get anything such.
Please do help me out if anything such feature can be implemented.
If you need to show/hide charts selecting/unselecting all labels here is an example:
var barChartData = {
labels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32],
datasets: [{
label: 'One',
backgroundColor: 'rgba(206, 0, 23, 1)',
data: [0, 1, 3, 0, 2, 0, 0, 2, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 2, 1, 0, 1, 2, 1, 1, 0, 0, 0, 2, 2, 0, 3]
}, {
label: 'Two',
backgroundColor: 'rgba(206, 0, 23, 0.75)',
data: [0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1]
}, {
label: 'Three',
backgroundColor: 'rgba(206, 0, 23, 0.5)',
data: [0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 1]
}]
};
var ctx = document.getElementById('canvas').getContext('2d');
var chartInstance = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
title: {
display: false,
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
});
$("#toggle").click(function() {
chartInstance.data.datasets.forEach(function(ds) {
ds.hidden = !ds.hidden;
});
chartInstance.update();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<button id="toggle">show/hide all</button>
<canvas id="canvas" height="500" width="800"></canvas>
Jsfiddle: https://jsfiddle.net/beaver71/00q06vjp/
Credits: see https://github.com/chartjs/Chart.js/issues/3009
Update: for pie chart use "meta", see: https://jsfiddle.net/beaver71/u0y0919b/
For ChartJS 2.9.3, this works as requested by David in the comments:
const chart = ...
chart.data.datasets.forEach(dataset => {
Object.keys(dataset._meta).forEach(key => {
const current = !dataset._meta[key].hidden
dataset._meta[key].hidden = current || null
})
})
chart.update()
Toggles all with a button, while playing nicely with the individual toggling in the chart legend.
V3 Answer
You can use a custom generateLabels function together with a custom onClick to get it as an extra legendItem like so:
const defaultLegendClickHandler = Chart.defaults.plugins.legend.onClick;
const pieDoughnutLegendClickHandler = Chart.controllers.doughnut.overrides.plugins.legend.onClick;
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderColor: 'orange'
}
]
},
options: {
plugins: {
legend: {
onClick: (evt, legendItem, legend) => {
const type = legend.chart.config.type;
let allLegendItemsState = [];
if (legendItem.text === 'hide all datasets' || legendItem.text === 'show all datasets') {
if (typeof legend.hideAll === 'undefined') {
legend.hideAll = false;
}
legend.chart.data.datasets.forEach((dataset, i) => {
legend.chart.setDatasetVisibility(i, legend.hideAll)
});
legend.hideAll = !legend.hideAll;
legend.chart.update();
return;
}
if (type === 'pie' || type === 'doughnut') {
pieDoughnutLegendClickHandler(evt, legendItem, legend)
} else {
defaultLegendClickHandler(evt, legendItem, legend);
}
allLegendItemsState = legend.chart.data.datasets.map((e, i) => (legend.chart.getDatasetMeta(i).hidden));
if (allLegendItemsState.every(el => !el)) {
legend.hideAll = false;
legend.chart.update();
} else if (allLegendItemsState.every(el => el)) {
legend.hideAll = true;
legend.chart.update();
}
},
labels: {
generateLabels: (chart) => {
const datasets = chart.data.datasets;
const {
labels: {
usePointStyle,
pointStyle,
textAlign,
color
}
} = chart.legend.options;
const legendItems = chart._getSortedDatasetMetas().map((meta) => {
const style = meta.controller.getStyle(usePointStyle ? 0 : undefined);
return {
text: datasets[meta.index].label,
fillStyle: style.backgroundColor,
fontColor: color,
hidden: !meta.visible,
lineCap: style.borderCapStyle,
lineDash: style.borderDash,
lineDashOffset: style.borderDashOffset,
lineJoin: style.borderJoinStyle,
strokeStyle: style.borderColor,
pointStyle: pointStyle || style.pointStyle,
rotation: style.rotation,
textAlign: textAlign || style.textAlign,
datasetIndex: meta.index
};
});
legendItems.push({
text: (!chart.legend.hideAll || typeof chart.legend.hideAll === 'undefined') ? 'hide all datasets' : 'show all datasets',
fontColor: color,
fillStyle: 'turquoise', // Box color
strokeStyle: 'turquoise', // LineCollor around box
});
return legendItems;
}
}
}
}
}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.js"></script>
</body>
The correct answer result in :
chart.data.datasets.forEach((obj, index) => {
let meta = this.eval_chart.getDatasetMeta(index);
meta.hidden = !meta.hidden || null;
});
chart.update();
As wrote in the documentation : https://www.chartjs.org/docs/latest/configuration/legend.html#custom-on-click-actions
I have a horizontal bar chart with two datasets
I am trying to superimpose the blue bars onto red.so that the intesection can be a start time and the bar can indicate a range.
is there any way to do this?
data: {
labels: ["C#", "ASP.NET MVC", "WebAPI", "SQL", "Entity Framework","NServiceBus / MSMQ", "WCF", "WPF / XAML", "",
"HTML / CSS", "JavaScript", "Angular JS v1","",
"DI / IoC", "TDD / Unit Testing", "UI Testing (Seleno)", "CI (Teamcity)"],
datasets: [
{
label:"# years",
data: [3, 2, 1, 4, 6, 2, 0.5, 0.25, 0,
7, 2, 0.5, 0,
2, 2, 0.5, 0.5],
backgroundColor: 'red',
borderWidth: 0
},
{
label:"# years",
data: [6, 4, 3, 6, 6, 2, 0.5, 0.25, 0,
7, 2, 0.5, 0,
2, 2, 0.5, 0.5],
backgroundColor: 'blue',
borderWidth: 0
}
]
}
options:{
scales: {
xAxes: [{ stacked:true}]
}
}
Hi all im starting to work with couchdb
im trying to rereduce this reduce function
function(key,values,rereduce){
if(rereduce === true){
//HELP HERE
return results;
}
values.forEach(function(doc){
if(results[(doc.id-1)]){
results[(doc.id-1)].valori.push(doc.valore);
}else{
results[(doc.id-1)] = {
id:doc.id,
nome:doc.nome,
unita:doc.unita,
valori:[doc.valore]
};
}
});
return results;
}
someone can help me to rereduce this?
this is my Map output data
[2015, 7, 6, 0, 0, 26]
ID: bfc53ce117b53ec023c528e0c3039fc7
{nome: "COT ist.INGRESSO ", valore: 309.6, id: 1, unita: "mg/Nm", ora: "00:00:26"}
[2015, 7, 6, 0, 0, 26]
ID: bfc53ce117b53ec023c528e0c303a032
{nome: "COT ist. USCITA ", valore: 5.4, id: 2, unita: "mg/Nm", ora: "00:00:26"}
[2015, 7, 6, 0, 0, 26]
ID: bfc53ce117b53ec023c528e0c303adf4
{nome: "Media TOC NIRA ", valore: 6.8, id: 3, unita: "mg/Nm", ora: "00:00:26"}
[2015, 7, 6, 0, 0, 26]
ID: bfc53ce117b53ec023c528e0c303b6a7
{nome: "Media TOC Giorn. ", valore: 7.3, id: 4, unita: "mg/Nm", ora: "00:00:26"}
[2015, 7, 6, 0, 1, 26]
ID: bfc53ce117b53ec023c528e0c303c3ee
{nome: "COT ist.INGRESSO ", valore: 410.9, id: 1, unita: "mg/Nm", ora: "00:01:26"}
[2015, 7, 6, 0, 1, 26]
ID: bfc53ce117b53ec023c528e0c303c7e6
{nome: "COT ist. USCITA ", valore: 7, id: 2, unita: "mg/Nm", ora: "00:01:26"}
[2015, 7, 6, 0, 1, 26]
ID: bfc53ce117b53ec023c528e0c303cb60
{nome: "Media TOC NIRA ", valore: 6.4, id: 3, unita: "mg/Nm", ora: "00:01:26"}
[2015, 7, 6, 0, 1, 26]
ID: bfc53ce117b53ec023c528e0c303d729
{nome: "Media TOC Giorn. ", valore: 6.9, id: 4, unita: "mg/Nm", ora: "00:01:26"}
[2015, 7, 6, 0, 2, 26]
ID: bfc53ce117b53ec023c528e0c303df8e
{nome: "COT ist.INGRESSO ", valore: 306.7, id: 1, unita: "mg/Nm", ora: "00:02:26"}
etc....
What i need after the reduce is:
[{nome:"COT ist.Ingresso", id:1, unita:"mg/Nm",valori:[309.6,5.4,.....]}
{name:"thename",id:2, unita:"mg/Nm",valori:[6.8,3.5,......]}...]
this is an array of 4 object (one each id) with valori field is the concat of the various valore field, ( ordered by key or ora property)