Calculate daily average for selected period in PHP I would like to calculate the average for the same days (e.g. Monday, Tuesday, etc) in a selected period:

$data = array(
    '2016-05-01' =&gt; 100, 
    '2016-05-02' =&gt; 150, // monday
    '2016-05-03' =&gt; 5,
    '2016-05-04' =&gt; 5,
    '2016-05-05' =&gt; 25,
    '2016-05-06' =&gt; 25,
    '2016-05-07' =&gt; 25,
    '2016-05-08' =&gt; 25,
    '2016-05-09' =&gt; 55, // monday again
    '2016-05-10' =&gt; 25,
    '2016-05-11' =&gt; 35,
    '2016-05-12' =&gt; 25,
    '2016-05-13' =&gt; 125,
    '2016-05-14' =&gt; 25,
    '2016-05-15' =&gt; 225,
    '2016-05-16' =&gt; 25, // and again...
    '2016-05-17' =&gt; 25,
    '2016-05-18' =&gt; 25,
    '2016-05-19' =&gt; 25,
    '2016-05-20' =&gt; 25,
    '2016-05-21' =&gt; 25,
);

// Store occurrence of same days 
$countDays  = array('Mon' =&gt; 0, 'Tue' =&gt; 0, 'Wed' =&gt; 0, 'Thu' =&gt; 0, 'Fri' =&gt; 0, 'Sat' =&gt; 0, 'Sun' =&gt; 0);

// Store values
$output = array('Mon' =&gt; 0, 'Tue' =&gt; 0, 'Wed' =&gt; 0, 'Thu' =&gt; 0, 'Fri' =&gt; 0, 'Sat' =&gt; 0, 'Sun' =&gt; 0);

// Count days
foreach($data as $key =&gt; $value) {

    $dayName = date('D', strtotime($key));

    $countDays[$dayName]++;
}

// Calculate average
foreach($data as $key =&gt; $value) {

    $dayName = date('D', strtotime($key));

    $output[$dayName] += round($value / $countDays[$dayName]);
}


For example, I'd expect the following output for all the available (three) Mondays:


  (150 + 55 + 25) / 3 = 230 / 3 = 76
The only change I would make is in your two foreach loops. If you see below, I have made the change I would recommend making. This will make the loop a bit shorter and more accurate.

// Store occurrence of same days 
$countDays  = array('Mon' =&gt; 0, 'Tue' =&gt; 0, 'Wed' =&gt; 0, 'Thu' =&gt; 0, 
     'Fri' =&gt; 0, 'Sat' =&gt; 0, 'Sun' =&gt; 0);

// Store values
$output = array('Mon' =&gt; 0, 'Tue' =&gt; 0, 'Wed' =&gt; 0, 'Thu' =&gt; 0, 
     'Fri' =&gt; 0,'Sat' =&gt; 0, 'Sun' =&gt; 0);

// Count days
foreach($data as $key =&gt; $value) {

    $dayName = date('D', strtotime($key));

    $countDays[$dayName]++;
    //add up all the qty when you go through the array the first time
   // IE all the Tuesdays in the array get added up.
    $output[$dayName] += $value;
}

// Calculate average
foreach($output as $key =&gt; $value) {
    //now take all the totals you just made in the other loop, and avg them
    $output[$key] = round($value / $countDays[$key]);
}


This is the only way I can see to improve the code. This way, you have a 'shorter' second foreach loop, which may improve the speed of your code a bit. You could also do the $value by reference and change it on the fly, but I think the way I have it now is clearer. This way you aren't doing the math more then once per array element, so you only do the avg for something like Tuesday once.

As Pinoniq stated you can drop the second foreach loop and add a function, and use array_map to do the rounding. Leave the first foreach loop the same and then add this, instead of the other foreach loop.  

function average($a, $b){
    return round($a/$b);
}
$output = array_map("average",$output,$countDays);
//var_dump($output); //&lt;-only if you want to test results.


Downside: You lose your index keys if you do it like this. However, you can easily fix that by just keeping the keys in an array, and then print them out at the same time, or use array_combine($keys,$values); to get your output array back.