Skip to content

Compound.Boxplot

Generates a Box Plot compound SVG Visual showing statistical distribution

DaxLib.SVG.Compound.Boxplot( x, y, width, height, paddingX, paddingY, axisRef, measureRef, fillColor, strokeColor, showOutliers )
Parameter Type Required Description
x INT64 The x position of the compound
y INT64 The y position of the compound
width INT64 The width of the compound
height INT64 The height of the compound
paddingX DOUBLE The horizontal padding percentage (0.0-1.0, e.g., 0.1 = 10% padding)
paddingY DOUBLE The vertical padding percentage (0.0-1.0, e.g., 0.1 = 10% padding)
axisRef ANYREF EXPR The column that the measure will be evaluated against
measureRef NUMERIC EXPR The measure to evaluate
fillColor STRING Color for the box fill
strokeColor STRING Color for lines, whiskers, and median
showOutliers BOOLEAN Whether to show outlier points beyond whiskers

STRING An SVG box plot showing statistical distribution including quartiles, median, whiskers, and optionally outliers

DaxLib.SVG.SVG(
    500,
    100,
    BLANK(),
    DaxLib.SVG.Compound.Boxplot(
        0,                  // x
        0,                  // y
        500,                // width
        100,                // height
        0.05,               // paddingX
        0.02,               // paddingY
        Dates[Date],        // axisRef
        [Total Cost],       // measureVal
        DaxLib.SVG.Colour.Theme(
            "Power BI",
            25
        ),                  // fillColour
        DaxLib.SVG.Colour.Theme(
            "Power BI",
            25
        ),                  // strokeColour
        TRUE                // showOutliers
    ),
    BLANK()
)
function 'DaxLib.SVG.Compound.Boxplot' =
    (
        x: INT64,
        y: INT64,
        width: INT64,
        height: INT64,
        paddingX: DOUBLE,
        paddingY: DOUBLE,
        axisRef: ANYREF EXPR,
        measureRef: NUMERIC EXPR,
        fillColor: STRING,
        strokeColor: STRING,
        showOutliers: BOOLEAN
    ) =>

        // Apply padding to dimensions
        VAR _X =            x + ( width * ( COALESCE( paddingX, 0 ) / 2) )
        VAR _Y =            y + ( height * ( COALESCE( paddingY, 0 ) / 2) )
        VAR _Width =        width * ( 1 - COALESCE( paddingX, 0 ) )
        VAR _Height =       height * ( 1 - COALESCE( paddingY, 0 ) )

        // Check if Axis is numeric
        VAR axisSample =    MAX( axisRef )
        VAR axisIsNumeric = ISNUMERIC( axisSample ) || ISDATETIME( axisSample )

        // For totals
        // Materialize axis + value once (avoid repeated measure evaluation)
        VAR _Values =
            ADDCOLUMNS(
                VALUES( axisRef ),
                "@Value", measureRef
            )

        VAR _DataNonBlank =
            FILTER( _Values, NOT ISBLANK( [@Value] ) )

        VAR _Data =
            ADDCOLUMNS(
                _DataNonBlank,
                "@AxisIndex",
                    IF(
                        axisIsNumeric,
                        axisRef,
                        RANK( DENSE, CALCULATETABLE( VALUES( axisRef ), ALLSELECTED() ) )
                    )
            )

        VAR _XMin =             MINX( _Data, [@Value] )
        VAR _XMax =             MAXX( _Data, [@Value] )

        VAR _Count =            COUNTROWS( _Data )
        VAR _Min =              MINX( _Data, [@Value] )
        VAR _Max =              MAXX( _Data, [@Value] )

        // Calculate quartiles using standard definitions
        VAR _Q1 =               PERCENTILEX.INC( _Data, [@Value], 0.25 )
        VAR _Median =           PERCENTILEX.INC( _Data, [@Value], 0.5 )
        VAR _Q3 =               PERCENTILEX.INC( _Data, [@Value], 0.75 )

        // Calculate IQR and whisker boundaries (1.5 * IQR rule)
        VAR _IQR =              _Q3 - _Q1
        VAR _LowerWhisker =     MAX( _Min, _Q1 - 1.5 * _IQR )
        VAR _UpperWhisker =     MIN( _Max, _Q3 + 1.5 * _IQR )

        VAR _XWidth =   _X + _Width

        // Scale statistical values to SVG coordinates
        VAR _Q1X =              DaxLib.SVG.Scale.Normalize( _Q1, _XMin, _XMax, _X, _XWidth )
        VAR _MedianX =          DaxLib.SVG.Scale.Normalize( _Median, _XMin, _XMax, _X, _XWidth )
        VAR _Q3X =              DaxLib.SVG.Scale.Normalize( _Q3, _XMin, _XMax, _X, _XWidth )
        VAR _LowerWhiskerX =    DaxLib.SVG.Scale.Normalize( _LowerWhisker, _XMin, _XMax, _X, _XWidth )
        VAR _UpperWhiskerX =    DaxLib.SVG.Scale.Normalize( _UpperWhisker, _XMin, _XMax, _X, _XWidth )

        // Box dimensions - centered vertically with padding
        VAR _BoxHeight =        _Height * 0.6
        VAR _BoxY =             _Y + _Height * 0.2
        VAR _CenterY =          _Y + _Height * 0.5

        // Create outlier points beyond whiskers if enabled
        VAR _OutlierAttr = 
            DaxLib.SVG.Attr.Shapes(
                strokeColor,    // fill
                BLANK(),        // fillOpacity
                BLANK(),        // fillRule
                BLANK(),        // stroke
                BLANK(),        // strokeWidth
                BLANK(),        // strokeOpacity
                BLANK()         // opacity
            )
        VAR _Outliers = 
            IF(
                showOutliers,
                CONCATENATEX(
                    FILTER(
                        _Data,
                        [@Value] < _LowerWhisker || [@Value] > _UpperWhisker
                    ),
                    DaxLib.SVG.Element.Circle(
                        DaxLib.SVG.Scale.Normalize( [@Value], _XMin, _XMax, _X, _XWidth ), // cx
                        _CenterY,           // cy
                        2,                  // radius
                        _OutlierAttr,       // attributes
                        BLANK()             // transforms
                    ),
                    ""
                )
            )

        // Lower whisker line from whisker to Q1 (horizontal)
        VAR _LowerWhiskerLine = 
            DaxLib.SVG.Element.Line(
                _LowerWhiskerX,         // x1
                _CenterY,               // y1
                _Q1X,                   // x2
                _CenterY,               // y2
                DaxLib.SVG.Attr.Shapes(
                    BLANK(),            // fill
                    BLANK(),            // fillOpacity
                    BLANK(),            // fillRule
                    strokeColor,        // stroke
                    1,                  // strokeWidth
                    BLANK(),            // strokeOpacity
                    BLANK()             // opacity
                ),
                BLANK()                 // transforms
            )

        // Upper whisker line from Q3 to whisker (horizontal)
        VAR _UpperWhiskerLine = 
            DaxLib.SVG.Element.Line(
                _Q3X,                   // x1
                _CenterY,               // y1
                _UpperWhiskerX,         // x2
                _CenterY,               // y2
                DaxLib.SVG.Attr.Shapes(
                    BLANK(),            // fill
                    BLANK(),            // fillOpacity
                    BLANK(),            // fillRule
                    strokeColor,        // stroke
                    1,                  // strokeWidth
                    BLANK(),            // strokeOpacity
                    BLANK()             // opacity
                ),
                BLANK()                 // transforms
            )

        // Lower whisker cap (vertical line)
        VAR _LowerCap = 
            DaxLib.SVG.Element.Line(
                _LowerWhiskerX,         // x1
                _BoxY,                  // y1
                _LowerWhiskerX,         // x2
                _BoxY + _BoxHeight,     // y2
                DaxLib.SVG.Attr.Shapes(
                    BLANK(),            // fill
                    BLANK(),            // fillOpacity
                    BLANK(),            // fillRule
                    strokeColor,        // stroke
                    1,                  // strokeWidth
                    BLANK(),            // strokeOpacity
                    BLANK()             // opacity
                ),
                BLANK()                 // transforms
            )

        // Upper whisker cap (vertical line)
        VAR _UpperCap = 
            DaxLib.SVG.Element.Line(
                _UpperWhiskerX,         // x1
                _BoxY,                  // y1
                _UpperWhiskerX,         // x2
                _BoxY + _BoxHeight,     // y2
                DaxLib.SVG.Attr.Shapes(
                    BLANK(),            // fill
                    BLANK(),            // fillOpacity
                    BLANK(),            // fillRule
                    strokeColor,        // stroke
                    1,                  // strokeWidth
                    BLANK(),            // strokeOpacity
                    BLANK()             // opacity
                ),
                BLANK()                 // transforms
            )

        // Main box (Q1 to Q3) - horizontal
        VAR _Box = 
            DaxLib.SVG.Element.Rect(
                _Q1X,                   // x (left of box)
                _BoxY,                  // y
                _Q3X - _Q1X,            // width (Q3 - Q1)
                _BoxHeight,             // height
                2,                      // rx
                2,                      // ry
                DaxLib.SVG.Attr.Shapes(
                    fillColor,          // fill
                    0.5,                // fillOpacity
                    BLANK(),            // fillRule
                    strokeColor,        // stroke
                    1,                  // strokeWidth
                    BLANK(),            // strokeOpacity
                    BLANK()             // opacity
                ),
                BLANK()                 // transforms
            )

        // Median line (vertical)
        VAR _MedianLine = 
            DaxLib.SVG.Element.Line(
                _MedianX,               // x1
                _BoxY,                  // y1
                _MedianX,               // x2
                _BoxY + _BoxHeight,     // y2
                DaxLib.SVG.Attr.Shapes(
                    BLANK(),            // fill
                    BLANK(),            // fillOpacity
                    BLANK(),            // fillRule
                    strokeColor,        // stroke
                    2,                  // strokeWidth (thicker for median)
                    BLANK(),            // strokeOpacity
                    BLANK()             // opacity
                ),
                BLANK()                 // transforms
            )

        // Combined elements
        VAR _CombinedElements = 
            _LowerWhiskerLine &
            _UpperWhiskerLine &
            _LowerCap &
            _UpperCap &
            _Box &
            _MedianLine &
            _Outliers

        RETURN

            IF( NOT ISEMPTY( _Data ), _CombinedElements )

Comments