Stations and its Relationship

How many stations are there? Data is shared for the trip duration between many stations. Filtering the stations interactively and viewing the data transform can provide additional information that is hidden in the clutter. We will be using the drop down for all the available stations. There is whooping 601 stations in data. There are many stations in which the bike trips are very less.

How to build a drop down with all the stations? D3 can easily rescue us from such activities. All we need is location where we want the drop down, the list that is going to enter into the list. The start and the end stations both are same, so only one drop down is created. Format for creating the drop down is referred from the freeCode camp siteDrop Down reference. We will first create two divs that will float on either side of the scatter plot.

Pseudo Code

Representing the distance and duration makes the data very physical in nature, because of the involvement of time and distance dimensions. Lets dive into the Pseudo code of bringing the scatter plot on to the svg. There were couple of gotchas during the making of the charts.

Visual Pseudo

  • The frame of the chart is created using the regular d3.selection method. The axes are appended to the g-elems.The calls to the d3.axis() methods with the updating scales are updated as the new data is provided.
  • When the DOM is built at the page load using the D3 method, the event listener needs to be attached to the selection chain as shown in drop down function below.
  • Much time was spent in trying to reach the drop down select value using the document and d3 DOM query methods. If the Query methods don't find any Object to attach with,the addEventListener cannot read the "Null" value from the query methods.
  • Once the value is extracted from the drop down, use it in the JS filter method to modify the data and feed it into the General Update pattern

Interactive Scatter Plot

Data Format

Simple Array of elements contains the station names. To place them inside the dropdown framework, understanding of the mechanism how it drop down, selection and events linked with the dropdown works is required. Below code shows the process in action.

Drop down with D3

    function buildDropDown(divId, listData, forId, attrName, labelName,rawData) {
        //Build the start station dropdown
        const dropStrt = d3.select(`#${divId}`)
            .append('label')
            .attr('for',forId)
            .text(labelName)
        
        const startStnDd = dropStrt.append('select')
            .attr('name',attrName)
            .attr('class','w-50')
            .attr('id',forId)
            //placing the event listener here leads to entire list selected
            .on('change',function(e, d){
                var start = this.value;
                scatterPlot(rawData,start);
            }) 
        startStnDd.selectAll('option')
            .data(listData)
            .join('option')
            .attr('value', d => d)
            .text(d =>d)
    
        }
                            

Coding Interactive Chart

        function scatterPlot(tabData, startStation) {
            filteredData = tabData.filter((d) => d.startStn === startStation);
            //Domain is attached seperately and called.
            xScale.domain(d3.extent(filteredData, (d) => d.tripDuration))
            yScale.domain(d3.extent(filteredData, (d) => d.haversignDist))
            
            xAxis.transition().duration(1000).call(d3.axisBottom(xScale));
            yAxis.transition().duration(1000).call(d3.axisLeft(yScale));
            
            var toolTip = d3
                .select("#chart")
                .append("div")
                .style("opacity", 0)
                .attr("class", "ba ph4 pv2 mb2 dib br3 bw2 f6 bg-light-blue");
            var mouseOver = function (d) {
                console.log(d3.mouse(this));
                toolTip
                .html(
                    `Trip Duration: ${d.tripDuration}
Haversign Distance: ${d.haversignDist}
Ride Type:${d.rideableType}` ) .transition() .duration(1000) .style("opacity", 1); }; var mouseOut = function (d) { toolTip.transition().duration(1000).style("opacity", 0); d3.select(this).style("opacity", 0.7); }; const marks = svg .selectAll("circle") .data(filteredData) .join( enter => enter.append('circle') .attr("cx", (d) => xScale(d.tripDuration)) .attr("cy", (d) => yScale(d.haversignDist)) .attr("fill", (d) => ride(d.rideableType)) .attr("r", 5) .style("opacity", 0.7) .on("mouseover", mouseOver) .on("mouseleave", mouseOut), update => update .attr('opacity',0.3) .transition().duration(2500) .attr('opacity',0.9), exit => exit .transition().duration(2500) .attr('transform',(d,i)=> `translate(${d.tripDuration + 25} ${d.haversignDist + 50})`) .remove() )