phparraysobjectaveragearray-column

Calculate average of all values in a specific column of a 2d array


I need to find the average of all AdjClose values in my two dimensional array.

I have an array stored in a variable $data. It looks like this:

["data"]=>
  array(22) {
    [0]=>
    object(stdClass)#234 (7) {
      ["Date"]=>
      string(10) "2016-08-31"
      ["Open"]=>
      string(9) "767.01001"
      ["High"]=>
      string(10) "769.090027"
      ["Low"]=>
      string(10) "765.380005"
      ["Close"]=>
      string(10) "767.049988"
      ["Volume"]=>
      string(7) "1247400"
      ["AdjClose"]=>
      string(10) "767.049988"
    }
    [1]=>
    object(stdClass)#240 (7) {
      ["Date"]=>
      string(10) "2016-08-30"
      ["Open"]=>
      string(10) "769.330017"
      ["High"]=>
      string(10) "774.466003"
      ["Low"]=>
      string(10) "766.840027"
      ["Close"]=>
      string(10) "769.090027"
      ["Volume"]=>
      string(7) "1127100"
      ["AdjClose"]=>
      string(10) "769.090027"
    }

It has around 22 entries and I want to iterate through every ["AdjClose"] and calculate the average of these numbers.

From what I understand, I should write something like: if(@$data->data->AdjClose) but this is where my problems begin.

Can someone explain to me please how to iterate through the objects/rows access and store the AdjClose values and calculate the average?


Solution

  • Here's an example of an iterative solution, since you were asking about how that would work:

    // initialize sum and total
    $sum = 0;
    $total = 0;
    
    foreach ($data->data as $obj) {
        if (isset($obj->AdjClose)) {   // verify that the current object has an AdjClose
            $sum += $obj->AdjClose;    // add it to the sum
            $total++;                  // increment the count
        }
    }
    echo $sum / $total;                // display the average
    

    I added the if (isset($obj->AdjClose) check because you asked about if(@$data->data->AdjClose). I thought that implied that AdjClose might not be present in some of the objects. If that is the case, I wanted to show how to check for it rather than using the error suppression operator (@). If you want items without AdjClose to be included in the average as zeroes, you can move the $total++ outside the if block.


    If you have PHP 7, you can also do this using array_column (but again, unless you want to include missing AdjClose properties in your average as zeroes, only use this if AdjClose is defined on all of the objects).

    $average = array_sum(array_column($data->data, 'AdjClose')) / count($data->data)