Skip to main content
Announcements
See what Drew Clarke has to say about the Qlik Talend Cloud launch! READ THE BLOG
cancel
Showing results for 
Search instead for 
Did you mean: 
cahenson2
Contributor II
Contributor II

Set Analysis not working as expected in extension

I'm currently working on a custom visualization extension. In the extension I currently have two measures. The first measureis used to calculate quantiles for the dataset as a whole and then to translate the quantiles into a box plot.

  • (=Aggr({1<Student=>} NODISTINCT Max(Final_Score), Student, Domain)

The second measure is used to plot the individual data points on top of the box plot. 

  • (=Aggr(NODISTINCT Max(Final_Score), Student, Domain)

The set analysis and overall data structure appear correct when I look at the data in a table with the appropriate selections. In the visualization, however, initially everything appears correctly, but when I initiate a selection for Student the box plot calculated from Measure 1 disappears and only the data points for the selected student remain. I'm creating the extension in d3 and the code is included below.

Thanks in advance for any help.

 

define(["jquery", "./d3.v4.min", "./initialProperties", "./properties", "text!./CCP_Grouped_Multi.css"],
    function ($, d3, initProps, props, cssContent) {
        "use strict"
        $('<style>').html(cssContent).appendTo('head');
        return {
            initialProperties: initProps,
            definition: props,
            support: {
                snapshot: true,
                export: false,
                exportData: false
            },

            paint: function ($element, layout) {

                var hypercube = layout.cube1;
                console.log(hypercube);

                var margin = {
                    top: 20,
                    right: 20,
                    bottom: 60,
                    left: 40
                },
                    width = $element.width() - margin.left - margin.right,
                    height = $element.height() - margin.top - margin.bottom,
                    center = height / 2,
                    offset = 50;

                var id = "ID_D3" + layout.qInfo.qId;
                $element.attr("id", id); //assign to $element the attribute id set as "ID_D3"
                d3.select("#" + id).html(null);  //clear div so that it doesn't re-render with each run

                var dataset = layout.qHyperCube.qDataPages[0].qMatrix.map(function (d) {
                    return {
                        "d_1": d[0].qText, //Domain
                        "d_2": d[1].qText, //Student
                        "d_3": d[2].qNum, //Box plot measure (=Aggr({1<Student=>} NODISTINCT Max(Final_Score), Student, Domain)
                        "d_4": d[3].qNum //Data points measure (=Aggr(NODISTINCT Max(Final_Score), Student, Domain)
                    }
                });

                //Calculate distribution components (Adjust with d3.nest)
                var sumstat = d3.nest() // nest function allows to group the calculation per level of a factor
                    .key(function (d) { return d.d_1; })
                    .rollup(function (g) {
                        return {
                            "min": d3.quantile(g, 0, g => g.d_3),
                            "q1": d3.quantile(g, .25, g => g.d_3),
                            "med": d3.quantile(g, .5, g => g.d_3),
                            "q3": d3.quantile(g, .75, g => g.d_3),
                            "max": d3.quantile(g, 1, g => g.d_3)
                        }
                    })
                    .entries(dataset)
                console.log("sumstat:", sumstat)

                //Create svg object
                var svg = d3.select("#" + id)
                    .append("svg")
                    .attr("width", width + margin.left + margin.right)
                    .attr("height", height + margin.top + margin.bottom)
                    .append("g")
                    .attr("transform",
                        "translate(" + margin.left + "," + margin.top + ")");

                // Show the X scale (Need to find consistent way to translate the position: currently shifts at resizing)
                var x = d3.scaleLinear()
                    .domain([0, 1])
                    .range([0, width])
                svg
                    .append("g")
                    .attr("class", "axis")
                    .attr("transform", "translate(0," + height + ")")
                    .call(d3.axisBottom(x).tickValues([0, 1]).tickFormat(d3.format(".0%")));

                // Add X axis label:
                svg
                    .append("text")
                    .style("text-anchor", "middle")
                    .attr("x", width / 2)
                    .attr("y", height + margin.bottom - 15)
                    .text("Range");

                // Show the Y scale
                var y = d3.scaleBand()
                    .range([height, 0])
                    .domain(["CM", "CR", "HX", "PE"])
                    .padding(.4);
                svg.append("g")
                    .call(d3.axisLeft(y).tickSize(0))
                    .select(".domain").remove()

                // Show the boxes (shape outlines commented out)
                svg
                    .selectAll("boxes")
                    .data(sumstat)
                    .enter()
                    .append("rect")
                    .attr("y", function (d) { return y(d.key); })
                    .attr("x", function (d) { return (x(d.value.min)) })
                    .attr("width", function (d) { return (x(d.value.q1) - x(d.value.min)) })
                    .attr("height", center / 4)
                    // .attr("height", y.bandwidth())
                    // .attr("stroke", "gray")
                    .style("fill", "#EEEEEE")
                    .text("Minimum");


                svg
                    .selectAll("boxes")
                    .data(sumstat)
                    .enter()
                    .append("rect")
                    .attr("y", function (d) { return y(d.key); })
                    .attr("x", function (d) { return (x(d.value.q1)) })
                    .attr("width", function (d) { return (x(d.value.med) - x(d.value.q1)) })
                    .attr("height", center / 4)
                    // .attr("height", y.bandwidth())
                    // .attr("stroke", "gray")
                    .style("fill", "#CCCCCC");

                svg
                    .selectAll("boxes")
                    .data(sumstat)
                    .enter()
                    .append("rect")
                    .attr("y", function (d) { return y(d.key); })
                    .attr("x", function (d) { return (x(d.value.med)) })
                    .attr("width", function (d) { return (x(d.value.q3) - x(d.value.med)) })
                    .attr("height", center / 4)
                    // .attr("height", y.bandwidth())
                    // .attr("stroke", "gray")
                    .style("fill", "#999999");

                svg
                    .selectAll("boxes")
                    .data(sumstat)
                    .enter()
                    .append("rect")
                    .attr("y", function (d) { return y(d.key); })
                    .attr("x", function (d) { return (x(d.value.q3)) })
                    .attr("width", function (d) { return (x(d.value.max) - x(d.value.q3)) })
                    .attr("height", center / 4)
                    // .attr("height", y.bandwidth())
                    // .attr("stroke", "gray")
                    .style("fill", "#666666");

               
                //Adding individual data points (Change to rectangle with a value representing student store +- 5% of max-min) also: Convert to d3.nest() and sub for dataset (key/value)
                var color = d3.scaleLinear()
                    .domain([.5, 1])
                    .range(["#e7ecfc", "#1045e3"]);
                svg
                    .selectAll("indPoints")
                    .data(dataset)
                    .enter()
                    .append("circle")
                    .attr("cx", function (d) { return (x(d.d_4)) })
                    .attr("cy", function (d) { return (y(d.d_1) + (y.bandwidth() - (center / 7))) }) //Will have to adjust for flexibility
                    .attr("r", 4)
                    .style("fill", function (d) { return (color(+d.d_2)) });

               

            }
        }
    })

 

Labels (1)
0 Replies