1

I need to calculate the average value for each column of data in an array of associative arrays. The result should be a flat, associative array of averages.

Sample array:

$array = [
  [
    "a" => 0.333,
    "b" => 0.730,
    "c" => 0.393
  ],
  [
    "a" => 0.323,
    "b" => 0.454,
    "c" => 0.987
  ],
  [
    "a" => 0.753,
    "b" => 0.983,
    "c" => 0.123
  ]
];

I am looking for a simpler way of processing all the array elements and producing a single array which has a mean value (average) of all the corresponding values.

My current code works, but I'm hoping for a more elegant approach.

$a = []; // Store all a values
$b = []; // Store all b values
$c = []; // Store all c values

for ( $i = 0; $i < count( $array ); $i ++ ) {
    // For each array, store each value in it's corresponsing array
    // Using variable variables to make it easy
    foreach ( $array[ $i ] AS $key => $val ) {
        $k    = $key;
        $$k[] = $val;
    };
}

// Create single array with average of all
$fa = array(
    'a' => array_sum($a) / count($a),
    'b' => array_sum($b) / count($b),
    'c' => array_sum($c) / count($c)
);

The desired result:

[
    'a' => 0.4696666666666667,
    'b' => 0.7223333333333333,
    'c' => 0.501,
]
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
realnsleo
  • 709
  • 2
  • 12
  • 29

2 Answers2

3

Assuming each sub-array has the same keys:

foreach(array_keys($array[0]) as $key) {
    $result[$key] = array_sum($tmp = array_column($array, $key))/count($tmp);
}
  • Get the keys from the first sub-array
  • Loop, extract those values from the main array and calculate
AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
  • Ouch! that missing check for empty array hurts. This will give a warning about missing index `0` if `$array` is empty – Fr0zenFyr Apr 29 '19 at 05:23
  • @Fr0zenFyr just append `?? []` after `$array` so that if there is no `[0]` element, the fallback is an empty array. This way there will be no warnings generated and the loop will simply not be entered. – mickmackusa Jan 04 '23 at 14:14
1

Here is a functional-style approach which will work as @AbraCadaver's answer does.

Code: (Demo)

var_export(
    array_reduce(
        array_keys($array[0] ?? []),
        fn($result, $k) => $result + [$k => array_sum($c = array_column($array, $k)) / count($c)],
        []
    )
);
  1. I used ?? [] as a safeguard for live applications where it is possible that the input array is empty (and does not contain an element at [0]).
  2. Using PHP7.4's arrow function syntax allows the accessibility of the input array without a use() statement.
  3. The + in the custom function is not performing addition; it is uniting the result array with the new associative array -- this serves to push the new element into the returned result array.
mickmackusa
  • 43,625
  • 12
  • 83
  • 136