Skip to content

Compound.Jitter

Generates a Jitter Plot compound SVG Visual showing values as points with x-position based on value and y-position jittered around center

DaxLib.SVG.Compound.Jitter( x, y, width, height, paddingX, paddingY, axisRef, measureRef, pointColor, jitterAmount )
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
pointColor STRING The Hex color of the points (e.g., "#01B8AA")
jitterAmount DOUBLE The amount of y-axis jitter as a percentage of height (0.0-1.0, defaults to 0.3)

STRING An SVG jitter plot showing data points with horizontal positioning based on values and vertical jittering for visibility

DaxLib.SVG.SVG(
    500,
    100,
    BLANK(),
    DaxLib.SVG.Compound.Jitter(
        0,                  // x
        0,                  // y
        500,                // width
        100,                // height
        0.05,               // paddingX
        0.02,               // paddingY
        Dates[Date],        // xAxis
        [Total Cost],       // measureRef
        DaxLib.SVG.Colour.Theme(
            "Power BI",
            25
        )                   // pointColour
        0.5                 // jitterAmount
    ),
    BLANK()
)
function 'DaxLib.SVG.Compound.Jitter' = 
    (
        x: INT64,
        y: INT64,
        width: INT64,
        height: INT64,
        paddingX: DOUBLE,
        paddingY: DOUBLE,
        axisRef: ANYREF EXPR,
        measureRef: NUMERIC EXPR,
        pointColor: STRING,
        jitterAmount: DOUBLE
    ) =>

        // 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 _RawXMin =  MINX( _Data, [@Value] )
        VAR _XMin =     IF( _RawXMin > 0, 0, _RawXMin )
        VAR _XMax =     MAXX( _Data, [@Value] )
        VAR _XWidth =   _X + _Width
        VAR _YHeight =  _Y + _Height
        VAR _CenterY =  _Y + _Height * 0.5
        VAR _JitterRange =  _Height * IF( ISBLANK( jitterAmount ), 0.3, jitterAmount )

        // Points
        VAR _CircleAttr = 
            DaxLib.SVG.Attr.Shapes(
                pointColor,     // fill
                0.5,            // fillOpacity
                BLANK(),        // fillRule
                pointColor,     // stroke
                1,              // strokeWidth
                0.9,            // strokeOpacity
                BLANK()         // opacity
            )
        VAR _CircleElements = 
            CONCATENATEX(
                _Data,
                IF( 
                    NOT ISBLANK( [@Value] ),
                    VAR _Seed =         ABS( [@Value] * 12345 ) + ABS( [@AxisIndex] * 67890 ) + ABS( LEN( FORMAT( [@Value], "0.000000" ) ) * 9876 )
                    VAR _PseudoRandom = MOD( _Seed, 10000 ) / 10000
                    VAR _JitterY =      _CenterY + ( _PseudoRandom - 0.5 ) * _JitterRange
                    VAR _ClampedY =     MAX( _Y, MIN( _YHeight, _JitterY ) )
                    RETURN
                        DaxLib.SVG.Element.Circle(
                            DaxLib.SVG.Scale.Normalize( [@Value], _XMin, _XMax, _X, _XWidth ), // cx
                            _ClampedY,          // cy
                            2,                  // r
                            _CircleAttr,        // attributes
                            BLANK()             // transforms
                        )
                ),
                " ",
                [@AxisIndex],
                ASC
            )

        RETURN

            IF( NOT ISEMPTY( _Data ), _CircleElements )

Comments