Back to Devexpress

Calculate Summaries

wpf-400970-controls-and-libraries-charts-suite-chart-control-calculate-summaries.md

latest21.7 KB
Original Source

Calculate Summaries

  • May 28, 2021
  • 11 minutes to read

The Chart Control can apply a summary function to calculate data source value summaries and display them as series points.

Summary vs Aggregation

Aggregation is similar to summaries but the Chart Control queries and stores data in memory differently.

SummaryAggregation
Store DataChart stores summarized values.Chart stores raw data source values.
Change Detail LevelChart re-loads data from the data source.Chart re-calculates data in memory.
Behave on ZoomChart does not re-calculate aggregated values when it is zoomed.Chart re-calculates value aggregates on each zoom level.
Memory ConsumptionLowHigh

Apply a Summary Function

You can use Chart Designer or markup to apply a summary function.

Important

Automatic summary functions can be calculated only for Series that operate with data points with one value for each argument. If series data points have two or more values (e.g., Range, Financial and Bubble series), you should use Custom Summary Functions instead.

Also note that a summary function cannot be calculated when an axis’s scale mode is Continuous.

Use the Chart Designer

  • Run the Chart Designer.

  • Use the Element Tree on the left to select a series. Then, open its Properties tab on the right.

  • Click the Summary property’s button and select the New Summary item.

  • Use the Function property menu to select a summary function.

  • Type a name of the data source field that provides data for summarization.

  • Click the Save and Exit button to save changes and close the designer.

Use Markup

The following example shows how to apply the “SUM” function:

xaml
<Window.DataContext>
    <local:ChartViewModel/>
</Window.DataContext>
<Grid>
    <dxc:ChartControl>
        <dxc:XYDiagram2D SeriesItemsSource="{Binding SaleSeries}">
            <dxc:XYDiagram2D.SeriesItemTemplate>
                <DataTemplate>
                    <dxc:PointSeries2D DataSource="{Binding Values}"
                                       ArgumentDataMember="Category">
                        <!-- Configure the summary function options. -->
                        <dxc:PointSeries2D.Summary>
                            <dxc:Summary>
                                <dxc:Summary.Function>
                                    <dxc:SumSummaryFunction ValueDataMember="Value"/>
                                </dxc:Summary.Function>
                            </dxc:Summary>
                        </dxc:PointSeries2D.Summary>
                        <!--...-->
                        <dxc:PointSeries2D.Label>
                            <dxc:SeriesLabel Visible="True" 
                                             TextPattern="Sum: ${V}M" 
                                             dxc:MarkerSeries2D.Angle="90" 
                                             ResolveOverlappingMode="JustifyAroundPoint"/>
                        </dxc:PointSeries2D.Label>
                    </dxc:PointSeries2D>
                </DataTemplate>
            </dxc:XYDiagram2D.SeriesItemTemplate>
            <!--...-->
        </dxc:XYDiagram2D>
        <!--...-->
    </dxc:ChartControl>
</Grid>
csharp
public class ChartViewModel {
    public IEnumerable<SaleSeries> SaleSeries { get; private set; }
    public ChartViewModel() {     
        SaleSeries = new Collection<SaleSeries> {
        new SaleSeries {
            Values = new Collection<SaleInfo> {
                new SaleInfo { Category= "Video players", Region = "Asia", Value = 853},
                new SaleInfo { Category= "Video players", Region = "Australia", Value = 321},
                new SaleInfo { Category= "Video players", Region = "Europe", Value = 655},
                new SaleInfo { Category= "Video players", Region = "North America", Value = 1325},
                new SaleInfo { Category= "Video players", Region = "South America", Value = 653},

                new SaleInfo { Category= "Automation", Region = "Asia", Value = 172},
                new SaleInfo { Category= "Automation", Region = "Australia", Value = 255},
                new SaleInfo { Category= "Automation", Region = "Europe", Value = 981D},
                new SaleInfo { Category= "Automation", Region = "North America", Value = 963D},
                new SaleInfo { Category= "Automation", Region = "South America", Value = 123D},

                new SaleInfo { Category= "Monitors", Region = "Asia", Value = 1011D},
                new SaleInfo { Category= "Monitors", Region = "Australia", Value = 359D},
                new SaleInfo { Category= "Monitors", Region = "Europe", Value = 721D},
                new SaleInfo { Category= "Monitors", Region = "North America", Value = 565D},
                new SaleInfo { Category= "Monitors", Region = "South America", Value = 532D},

                new SaleInfo { Category= "Projectors", Region = "Asia", Value = 998D},
                new SaleInfo { Category= "Projectors", Region = "Australia", Value = 222D},
                new SaleInfo { Category= "Projectors", Region = "Europe", Value = 865D},
                new SaleInfo { Category= "Projectors", Region = "North America", Value = 787D},
                new SaleInfo { Category= "Projectors", Region = "South America", Value = 332D},

                new SaleInfo { Category= "Televisions", Region = "Asia", Value = 1356D},
                new SaleInfo { Category= "Televisions", Region = "Australia", Value = 232D},
                new SaleInfo { Category= "Televisions", Region = "Europe", Value = 1323D},
                new SaleInfo { Category= "Televisions", Region = "North America", Value = 1125D},
                new SaleInfo { Category= "Televisions", Region = "South America", Value = 865D}
            }
        }
    };
    }
}
public class SaleSeries {
    public IEnumerable<SaleInfo> Values { get; set; }
}
public class SaleInfo {
    public string Category { get; set; }
    public string Region { get; set; }
    public double Value { get; set; }
}
vb
Public Class ChartViewModel
    Public Property SaleSeries As IEnumerable(Of SaleSeries)

    Public Sub New()
        SaleSeries = New Collection(Of SaleSeries) From {
            New SaleSeries With {
                .Values = New Collection(Of SaleInfo) From {
                    New SaleInfo With { .Category = "Video players", .Region = "Asia", .Value = 853R },
                    New SaleInfo With { .Category = "Video players", .Region = "Australia", .Value = 321R },
                    New SaleInfo With { .Category = "Video players", .Region = "Europe", .Value = 655R },
                    New SaleInfo With { .Category = "Video players", .Region = "North America", .Value = 1325R },
                    New SaleInfo With { .Category = "Video players", .Region = "South America", .Value = 653R },
                    New SaleInfo With { .Category = "Automation", .Region = "Asia", .Value = 172R },
                    New SaleInfo With { .Category = "Automation", .Region = "Australia", .Value = 255R },
                    New SaleInfo With { .Category = "Automation", .Region = "Europe", .Value = 981R },
                    New SaleInfo With { .Category = "Automation", .Region = "North America", .Value = 963R },
                    New SaleInfo With { .Category = "Automation", .Region = "South America", .Value = 123R },
                    New SaleInfo With { .Category = "Monitors", .Region = "Asia", .Value = 1011R },
                    New SaleInfo With { .Category = "Monitors", .Region = "Australia", .Value = 359R },
                    New SaleInfo With { .Category = "Monitors", .Region = "Europe", .Value = 721R },
                    New SaleInfo With { .Category = "Monitors", .Region = "North America", .Value = 565R },
                    New SaleInfo With { .Category = "Monitors", .Region = "South America", .Value = 532R },
                    New SaleInfo With { .Category = "Projectors", .Region = "Asia", .Value = 998R },
                    New SaleInfo With { .Category = "Projectors", .Region = "Australia", .Value = 222R },
                    New SaleInfo With { .Category = "Projectors", .Region = "Europe", .Value = 865R },
                    New SaleInfo With { .Category = "Projectors", .Region = "North America", .Value = 787R },
                    New SaleInfo With { .Category = "Projectors", .Region = "South America", .Value = 332R },
                    New SaleInfo With { .Category = "Televisions", .Region = "Asia", .Value = 1356R },
                    New SaleInfo With { .Category = "Televisions", .Region = "Australia", .Value = 232R },
                    New SaleInfo With { .Category = "Televisions", .Region = "Europe", .Value = 1323R },
                    New SaleInfo With { .Category = "Televisions", .Region = "North America", .Value = 1125R },
                    New SaleInfo With { .Category = "Televisions", .Region = "South America", .Value = 865R }
                }
            }
        }
    End Sub
End Class

Public Class SaleSeries
    Public Property Values As IEnumerable(Of SaleInfo)
End Class

Public Class SaleInfo
    Public Property Category As String
    Public Property Region As String
    Public Property Value As Double
End Class

The example above uses the following API members to configure summary calculations:

MemberDescription
Series.SummaryGets or sets the series data point summarization settings.
SummaryStores the series data point summarize options.
Summary.FunctionSpecifies the summary function that calculates data point values.
DataMemberSummaryFunction.ValueDataMemberGets or sets the data source field that provides data to be aggregated.

Create a Custom Summary Function

The following example shows how to create the “Standard Deviation (STDEV.P)” summary function and apply it to chart data:

xaml
<Window.DataContext>
    <local:ChartViewModel/>
</Window.DataContext>
<Grid>
    <dxc:ChartControl>
        <dxc:XYDiagram2D SeriesItemsSource="{Binding SaleSeries}">
            <dxc:XYDiagram2D.SeriesItemTemplate>
                <DataTemplate>
                    <dxc:PointSeries2D DataSource="{Binding Values}"
                                       ArgumentDataMember="Category">
                        <!-- Configure the summary function options. -->
                        <dxc:PointSeries2D.Summary>
                            <dxc:Summary>
                                <dxc:Summary.Function>
                                    <local:StdDevSummaryFunction ValueDataMember="Value"/>
                                </dxc:Summary.Function>
                            </dxc:Summary>
                        </dxc:PointSeries2D.Summary>
                        <!--...-->
                    </dxc:PointSeries2D>
                </DataTemplate>
            </dxc:XYDiagram2D.SeriesItemTemplate>
            <!--...-->
        </dxc:XYDiagram2D>
        <!--...-->
    </dxc:ChartControl>
</Grid>
csharp
public class StdDevSummaryFunction : DataMemberSummaryFunction {
    public override string Name { get { return "STDEV"; } }

    protected override SeriesPoint[] CreateSeriesPoints(Series series, object argument, string[] functionArguments, DataSourceValues[] values, object[] colors) {
        double[] amount = new double[values.Length];
        double sum = 0.0;
        for(int i = 0; i < values.Length; i++) {
            amount[i] = Convert.ToDouble(values[i][functionArguments[0]]);
            sum += amount[i];
        }
        double averageAmount = sum / values.Length;
        double standardDeviationSquareSum = 0.0;
        for(int i = 0; i < values.Length; i++) {
            double deviation = amount[i] - averageAmount;
            standardDeviationSquareSum += deviation * deviation;
        }
        SeriesPoint seriesPoint = new SeriesPoint() { Argument = argument.ToString(), Value = Math.Round(Math.Sqrt(standardDeviationSquareSum / values.Length), 2) };
        return new SeriesPoint[] { seriesPoint };
    }
}
vb
Public Class StdDevSummaryFunction
    Inherits DataMemberSummaryFunction
    Public Overrides ReadOnly Property Name As String
        Get
            Return "STDDEV"
        End Get
    End Property
    Protected Overrides Function CreateSeriesPoints(ByVal series As Series, ByVal argument As Object, ByVal functionArguments As String(), ByVal values As DataSourceValues(), ByVal colors As Object()) As SeriesPoint()
        Dim amount As Double() = New Double(values.Length - 1) {}
        Dim sum As Double = 0.0
        For i As Integer = 0 To values.Length - 1
            amount(i) = Convert.ToDouble(values(i)(functionArguments(0)))
            sum += amount(i)
        Next
        Dim averageAmount As Double = sum / values.Length
        Dim standardDeviationSquareSum As Double = 0.0
        For i As Integer = 0 To values.Length - 1
            Dim deviation As Double = amount(i) - averageAmount
            standardDeviationSquareSum += deviation * deviation
        Next
        Dim seriesPoint As SeriesPoint = New SeriesPoint() With {
            .Argument = argument.ToString(),
            .Value = Math.Round(Math.Sqrt(standardDeviationSquareSum / values.Length), 2)
        }
        Return New SeriesPoint() {seriesPoint}
    End Function
End Class

Numeric, Time-Span and Date-Time Axis Specifics

For numerical, time-span and date-time x-axis scales, the summary function aggregates data point values for each interval the MeasureUnit (NumericSummaryOptions.MeasureUnit, TimeSpanSummaryOptions.MeasureUnit or DateTimeSummaryOptions.MeasureUnit) property specifies.

The following images illustrate how changes to the measurement unit affect point summaries:

A summary function is not applied.

AverageSummaryFunction is applied. NumericSummaryOptions.MeasureUnit = 1

AverageSummaryFunction is applied. NumericSummaryOptions.MeasureUnit = 5

The following example shows how to change a measurement unit used to calculate numeric x-axis arguments:

xaml
<Window.DataContext>
    <local:ChartViewModel/>
</Window.DataContext>
<Grid>
    <dxc:ChartControl>
        <dxc:XYDiagram2D>
            <dxc:PointSeries2D DataSource="{Binding Data}"
                               ArgumentDataMember="Argument">
                <!-- Configure the summary function options. -->
                <dxc:PointSeries2D.Summary>
                    <dxc:Summary>
                        <dxc:Summary.Function>
                            <dxc:AverageSummaryFunction ValueDataMember="Value"/>
                        </dxc:Summary.Function>
                        <dxc:Summary.NumericSummaryOptions>
                            <dxc:NumericSummaryOptions MeasureUnit="5"/>
                        </dxc:Summary.NumericSummaryOptions>
                    </dxc:Summary>
                </dxc:PointSeries2D.Summary>
                <!--...-->
            </dxc:PointSeries2D>
    </dxc:ChartControl>
</Grid>
csharp
public class ChartViewModel {
    public IEnumerable<DataPoint> Data { get; private set; }
    public ChartViewModel() {
        Data = new Collection<DataPoint> {
            new DataPoint { Argument= 1, Value = 853D},
            new DataPoint { Argument= 1, Value = 321D},
            new DataPoint { Argument= 2, Value = 655D},
            new DataPoint { Argument= 2, Value = 1325D},
            new DataPoint { Argument= 2, Value = 255D},
            new DataPoint { Argument= 2, Value = 981D},
            new DataPoint { Argument= 3, Value = 963D},
            new DataPoint { Argument= 3, Value = 123D},
            new DataPoint { Argument= 3, Value = 1011D},
            new DataPoint { Argument= 5, Value = 1356D},
            new DataPoint { Argument= 5, Value = 232D},
            new DataPoint { Argument= 5, Value = 1323D},
            new DataPoint { Argument= 5, Value = 1125D},
            new DataPoint { Argument= 6, Value = 865D},
            new DataPoint { Argument= 6, Value = 865D},
            new DataPoint { Argument= 10, Value = 1006D},
            new DataPoint { Argument= 10, Value = 236D},
            new DataPoint { Argument= 16, Value = 1090D},
            new DataPoint { Argument= 18, Value = 496D},
            new DataPoint { Argument= 18, Value = 691D},
            new DataPoint { Argument= 20, Value = 1125D},
            new DataPoint { Argument= 20, Value = 600D},
            new DataPoint { Argument= 20, Value = 770D}
        };
    }
}
public class DataPoint {
    public double Argument { get; set; }
    public double Value { get; set; }
}
vb
Public Class ChartViewModel
    Public Property Data As IEnumerable(Of DataPoint)
    Public Sub New()
        Data = New Collection(Of DataPoint) From {
            New DataPoint With {.Argument = 1, .Value = 853R},
            New DataPoint With {.Argument = 1, .Value = 321R},
            New DataPoint With {.Argument = 2, .Value = 655R},
            New DataPoint With {.Argument = 2, .Value = 1325R},
            New DataPoint With {.Argument = 2, .Value = 255R},
            New DataPoint With {.Argument = 2, .Value = 981R},
            New DataPoint With {.Argument = 3, .Value = 963R},
            New DataPoint With {.Argument = 3, .Value = 123R},
            New DataPoint With {.Argument = 3, .Value = 1011R},
            New DataPoint With {.Argument = 5, .Value = 1356R},
            New DataPoint With {.Argument = 5, .Value = 232R},
            New DataPoint With {.Argument = 5, .Value = 1323R},
            New DataPoint With {.Argument = 5, .Value = 1125R},
            New DataPoint With {.Argument = 6, .Value = 865R},
            New DataPoint With {.Argument = 6, .Value = 865R},
            New DataPoint With {.Argument = 10, .Value = 1006R},
            New DataPoint With {.Argument = 10, .Value = 236R},
            New DataPoint With {.Argument = 16, .Value = 1090R},
            New DataPoint With {.Argument = 18, .Value = 496R},
            New DataPoint With {.Argument = 18, .Value = 691R},
            New DataPoint With {.Argument = 20, .Value = 1125R},
            New DataPoint With {.Argument = 20, .Value = 600R},
            New DataPoint With {.Argument = 20, .Value = 770R}
        }
    End Sub
End Class
Public Class DataPoint
    Public Property Argument As Double
    Public Property Value As Double
End Class