Reputation: 327
I have a collection of "answers" (multi-dimensional array) which is extracted from a database. I need to perform a calculation on each value so that I can show the results on a graph.
Here is some sample input:
$array = [
'A1' => [1 => 1, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0, 10 => 0],
'A2' => [1 => 1, 2 => 1, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0, 10 => 0],
'A3' => [1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0, 10 => 0]
];
I want to calculate a percentage value from the multidimensional array using this kind of logic:
[A1] => Array( ([1]*100/sum([1]+[1]+[1]), [2]*100/sum([2]+[2]+[2]),..... )
[A2] => Array( ([1]*100/sum([1]+[1]+[1]), [2]*100/sum([2]+[2]+[2]),..... )
[A3] => Array( ([3]*100/sum([1]+[1]+[1]), [2]*100/sum([2]+[2]+[2]),..... )
How can I do this?
My desired output:
[
'A1' => [1 => 50, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0, 10 => 0],
'A2' => [1 => 50, 2 => 100, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0, 10 => 0],
'A3' => [1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0, 10 => 0]
]
Upvotes: 0
Views: 1012
Reputation: 47894
Dustin's answer was generating a lot of Division by zero warnings, so I thought I'd take the time to write up own answer.
Since the sample input array has subarrays of equal length, I'll not bother with isset()
and simply trust that calling array_column()
from the first row will access all available values.
In the first, foreach()
$v
is declared but not used because array_column()
gathers it with the other vertical data. $column_totals
is a 1-dimensional array of sums.
Because individual calculations must be conducted on each element of the multi-dimensional input array, two loops are used.
Before performing the calculation, checking the "current value" and the "column sum value"
for a zero value enables the quick return of 0
(and avoids Warnings); otherwise use the OP's formula.
*For those not familiar with the Order of Operations, no parentheses are needed in the formula because reading the expression left-to-right will maintain the logic with *
and /
.
Code: (Demo)
$array = [
'A1' => [1 => 1, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0, 10 => 0],
'A2' => [1 => 1, 2 => 1, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0, 10 => 0],
'A3' => [1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0, 10 => 0]
];
foreach (current($array) as $k => $v) {
$column_totals[$k] = array_sum(array_column($array, $k));
}
foreach ($array as $key => $row) {
foreach ($row as $k => $v) {
$result[$key][$k] = (!$v || !$column_totals[$k]) ? 0 : $v * 100 / $column_totals[$k];
}
}
var_export($result);
Output:
array (
'A1' =>
array (
1 => 50,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 0,
9 => 0,
10 => 0,
),
'A2' =>
array (
1 => 50,
2 => 100,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 0,
9 => 0,
10 => 0,
),
'A3' =>
array (
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 0,
9 => 0,
10 => 0,
),
)
Upvotes: 1
Reputation: 2086
Ahh, I see what you're trying to do now.
Try this
$totals = array();
// First get our totals.
foreach ($mainArray as $subKey => $subArray) {
foreach ($subArray as $k => $v) {
// Add the column to our total.
$totals[$k] = isset($totals[$k]) ? $totals[$k] + $v : $v;
}
}
$answers = array();
// Then build our answers.
foreach ($mainArray as $subKey => $subArray) {
$answers[$subKey] = array();
foreach ($subArray as $k => $v) {
$answers[$subKey][$k] = ($v * 100) / $totals[$k];
}
}
print_r($answers);
Upvotes: 2