Newbie
Newbie

Reputation: 177

Returning mean/average for selected valued D3.js

I have this json array which is returned in this format from a mySQL database using PHP:

 [{"dateTimeTaken":"2013-02-28 05:04:16","reading":"10.7","parameterType":"Flouride"},
 {"dateTimeTaken":"2013-02-28 05:04:21","reading":"10.5","parameterType":"Flouride"},
 {"dateTimeTaken":"2013-02-28 05:04:26","reading":"15.1","parameterType":"pH"},
 {"dateTimeTaken":"2013-02-28 05:04:31","reading":"4.4","parameterType":"Temperature"}...

I have two dropdown lists - where the user will select a) "parameterType" and then b) "month". I would like to return the mean/average reading for each day within the selected month for the selected parameterType.

Not sure how I can do this in D3 - but thought it may be something along the lines of:

Not sure if I'm completely off the mark though - or how I can even achieve this?

UPDATE:

    d3.select("#parameterType").on("change", function() { filterData(); });

    d3.select("#dateTimeTaken").on("change", function() { filterData(); });

    function filterData()
    {
        var selectedParameter = document.getElementById("parameterType").value;
        var selectedMonth = document.getElementById("dateTimeTaken").value;

        var selectedData = data.filter(function(d) 
        {
            return d.parameterType == selectedParameter &&
                    d.dateTimeTaken.getMonth() == (selectedMonth-1);
        });

        console.log(selectedData);//RETURNING EMPTY ARRAY?

        mean = d3.mean(selectedData,function(d) { return d.reading})

        //UPDATE GRAPH
        x.domain(d3.extent(data, function(d) { return d.dateTimeTaken; }));
        y.domain(d3.extent(data, function(d) { return d.reading; }));

        svg.select("path.line")
            .attr("d", line(data));

        svg.select(".x.axis")
            .transition()
            .duration(750)
            .ease("linear")
            .call(xAxis);

        svg.select(".y.axis")
            .transition()
            .duration(750)
            .ease("linear")
            .call(yAxis);   
    }
    });
    });

Upvotes: 3

Views: 14304

Answers (1)

zjonsson
zjonsson

Reputation: 2206

What you are looking for is standard javascript Array.filter method:

See https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/filter

For each "redraw" you would create a filtered subset:

  var selectedData = data.filter(function(d) {
    return d.parameterType == selectedParameter &&
           +d.dateTimeTaken.slice(5,7) == selectedMonth;
  })

and the mean can be easily calculated

mean = d3.mean(selectedData,function(d) { return +d.reading})

Please note that by putting a plus sign (+) in front of a variable a conversion to a numeric value is attempted.

However at this point you might realize that it's quite inconvenient to work with dates in string format. What you might do is do a little preprocessing before any filtering:

var dateFmt = d3.time.format("%Y-%m-%d %H:%M:%S");

data.forEach(function(d) {
  d.reading = +d.reading;  // convert to number
  d.dateTimeTaken = dateFmt.parse(d.dateTimeTaken);  // convert to javascript date
});

Here I'm using the d3.time.format functionality to convert a string date into a javascript date (see https://github.com/mbostock/d3/wiki/Time-Formatting)

In this case your filter (see above) would be slightly different:

  var selectedData = data.filter(function(d) {
    return d.parameterType == selectedParameter &&
           +d.dateTimeTaken.getMonth() == (selectedMonth-1);
  })

Please note that because getMonth() is 0 for January and 11 for December, I have to substract one from selectedMonth to get a proper comparison.

Upvotes: 4

Related Questions