Search code examples
phparraysmultidimensional-arrayroundingpercentage

Calculate percentage for each row between a column value and the sum of the entire column


I want to calculate the percentage for each row in an array based on a specific column value and the total of all values in that column.

Sample data:

$results = [
    ['type' => 'AA', 'count' => 4],
    ['type' => 'AE', 'count' => 59],
    ['type' => 'AF', 'count' => 13],
    ['type' => 'BB', 'count' => 44],
    ['type' => 'BC', 'count' => 16],
    ['type' => 'BD', 'count' => 36]
];

Desired result:

[
  ['type' => 'AA', 'count' => 4, 'percent' => '2%'],
  ['type' => 'AE', 'count' => 59, 'percent' => '34%'],
  ['type' => 'AF', 'count' => 13, 'percent' => '8%'],
  ['type' => 'BB', 'count' => 44, 'percent' => '26%'],
  ['type' => 'BC', 'count' => 16, 'percent' => '9%'],
  ['type' => 'BD', 'count' => 36, 'percent' => '21%'],
]

My code:

foreach($results as $row) {
   $count = $row['count'];
   $type = $row['type'];
   $array[$type][] = $count;
}

Solution

  • Before performing the arithmetic on each row, you'll need to sum the count values for all rows (for your sample data, the total is 172).

    Then loop over the rows, calculate the percentage and push the new associative rows into the new array.

    Code: (Demo)

    $results = [
        ['type' => 'AA', 'count' => 4],
        ['type' => 'AE', 'count' => 59],
        ['type' => 'AF', 'count' => 13],
        ['type' => 'BB', 'count' => 44],
        ['type' => 'BC', 'count' => 16],
        ['type' => 'BD', 'count' => 36]
    ];
    $total = array_sum(
        array_column($results, 'count')
    ); // 172
    
    foreach($results as &$row) {
        $row['percent'] = round($row['count'] / $total * 100, 0) . '%';
    }
    var_export($results);
    

    Or instead of the classic loop, you can use a modern arrow function inside of array_map() to merge the new column into each row.

    var_export(
        array_map(
            fn($row) => $row + ['percent' => round($row['count'] / $total * 100, 0) . '%'],
            $results
        )
    );
    

    Output (from either approach):

    array (
      0 => 
      array (
        'type' => 'AA',
        'count' => 4,
        'percent' => '2%',
      ),
      1 => 
      array (
        'type' => 'AE',
        'count' => 59,
        'percent' => '34%',
      ),
      2 => 
      array (
        'type' => 'AF',
        'count' => 13,
        'percent' => '8%',
      ),
      3 => 
      array (
        'type' => 'BB',
        'count' => 44,
        'percent' => '26%',
      ),
      4 => 
      array (
        'type' => 'BC',
        'count' => 16,
        'percent' => '9%',
      ),
      5 => 
      array (
        'type' => 'BD',
        'count' => 36,
        'percent' => '21%',
      ),
    )