Search code examples
phparraysmultidimensional-arraygroupingaverage

Group row data in a 2d array and calculate average of a column in each group


There are similar questions on Stack Overflow but nothing quite like mine, and I also want to double check that I am doing this the most efficient way (resource wise).

I have surveys that are submitted and I want to tally the results. Each survey is saved in a multidimensional array like so:

Array ( [name] => Clark Kent [rating] => 5 )

These are coming from a loop as they are separate database entries.

So I am beginning by creating a new array with all these combined:

$mods = array();
$index = -1;
foreach($fields as $field) {
  $index++;
  $mods[$index]['name'] = $field['name'];
  $mods[$index]['rating'] = $field['rating'];
}

Then I am grouping these so that all the ratings for the same name are together, so I can sum them later.

$groups = array();
foreach ($mods as $value) {
  $groups[$value['name']][] = $value;
}

This produces the following:

Array ( 
  [Clark Kent] => Array (
    [0] => Array (
        [name] => Clark Kent
        [rating] => 5
        )
    [1] => Array (
        [name] => Clark Kent
        [rating] => 5
        )
    )
[Peter Parker] => Array (
    [0] => Array (
        [name] => Peter Parker
        [rating] => 5
        )
    [1] => Array (
        [name] => Peter Parker
        [rating] => 5
        )
    )
[Bruce Wayne] => Array (
    [0] => Array (
        [name] => Bruce Wayne
        [rating] => 5
        )
    [1] => Array (
        [name] => Bruce Wayne
        [rating] => 5
        )
    )
[Bruce Banner] => Array (
    [0] => Array (
        [name] => Bruce Banner
        [rating] => 5
        )
    [1] => Array (
        [name] => Bruce Banner
        [rating] => 5
        )
    )
)

What I am trying to accomplish would be something like this:

<table>
  <tr>
    <td>Clark Kent</td>
    <td>{average of all ratings}</td>
  </tr>
</table>

I'm most of the way there, but I am stuck! I'm not sure how to get the grouped name that doesn't have any type of index or key so I can use that value for my table. Then I need to sum each grouped values.


Solution

  • I would do all the necessary math in the loop that reads the data from the database. Something like this:

    $ratings = array();
    while ($row = $result->fetch_assoc()) {
        $name = $row['name'];
        if (!isset($ratings[$name])) {
            $ratings[$name] = array('count' => 1, 'sum' => $row['rating']);
        }
        else {
            $ratings[$name]['count']++;
            $ratings[$name]['sum'] += $row['rating'];
        }
    }
    

    Then you can just output your table like so:

    echo "<table>";
    foreach ($ratings as $name => $r) {
        echo "<tr><td>$name</td><td>" . round($r['sum'] / $r['count'], 1) . "</td></tr>";
    }
    echo "</table>";