phparraysmultidimensional-arraygroupingaverage

Group row data of a 2d array by two columns and calculate the averages in each subset


I am trying to find country-wise averages of males and females from this array:

$users = [
    ['id' => 1, 'gender' => 'M', 'dob' => 1990, 'country' => 'IN', 'activity_score' => 34],
    ['id' => 2, 'gender' => 'M', 'dob' => 1980, 'country' => 'US', 'activity_score' => 9],
    ['id' => 3, 'gender' => 'F', 'dob' => 1993, 'country' => 'UK', 'activity_score' => 45],
    ['id' => 4, 'gender' => 'M', 'dob' => 1998, 'country' => 'IN', 'activity_score' => 0],
    ['id' => 5, 'gender' => 'F', 'dob' => 1997, 'country' => 'IN', 'activity_score' => 234],
    ['id' => 6, 'gender' => 'M', 'dob' => 1991, 'country' => 'UK', 'activity_score' => -6],
    ['id' => 7, 'gender' => 'F', 'dob' => 1992, 'country' => 'JP', 'activity_score' => 9],
    ['id' => 8, 'gender' => 'M', 'dob' => 1998, 'country' => 'US', 'activity_score' => 45],
    ['id' => 9, 'gender' => 'F', 'dob' => 2000, 'country' => 'JP', 'activity_score' => 5],
    ['id' => 10, 'gender' => 'M', 'dob' => 2006, 'country' => 'IN', 'activity_score' => 7],
    ['id' => 11, 'gender' => 'F', 'dob' => 1970, 'country' => 'US', 'activity_score' => 32],
    ['id' => 12, 'gender' => 'M', 'dob' => 2011, 'country' => 'IN', 'activity_score' => 21],
];

I find male and female averages with the following code.

foreach ($users as $user) {
    $tmp1[$user['gender']][] = date('Y') - $user['dob'];// calculating age 
    $tmp[$user['country']][] = $user;
}

$male_avg = array_sum($tmp1['M']) / count($tmp1['M']);
     
$female_avg = array_sum($tmp1['F']) / count($tmp1['F']);

How can I find the gender averages per country?


Solution

  • You can use array_reduce to Summarize the country and gender

    $users = ..... //Your array here
    
    //Summarize the data
    $summarize = array_reduce($users, function($c,$v){
        $key = $v['country'] . '_' . $v['gender'];
        if ( !isset( $c[ $key ] ) ) $c[ $key ] = array( 'sum' => 0, 'count' => 0 );
    
        $c[ $key ]['sum'] += ( date('Y') - $v['dob'] );
        $c[ $key ]['count']++;
    
        return $c;
    }, array());
    
    $avegage = array();
    foreach( $summarize as $key => $val ) {
        $avegage[ $key ] = $val['sum'] / $val['count'];
    }
    
    echo "<pre>";
    print_r( $avegage );
    echo "</pre>";
    

    This will result to:

    Array
    (
        [IN_M] => 16.75
        [US_M] => 29
        [UK_F] => 25
        [IN_F] => 21
        [UK_M] => 27
        [JP_F] => 22
        [US_F] => 48
    )
    

    Using Loop:

    $users = .......
    
    //Summarize the data
    $summarize = array();
    foreach( $users as $user ) {
        $skey = $user['country'] . '_' . $user['gender'];
        if ( !isset( $summarize[ $skey ] ) ) $summarize[ $skey ] = array( 'sum' => 0, 'count' => 0 );
    
        $summarize[ $skey ]['sum'] += ( date('Y') - $user['dob'] );
        $summarize[ $skey ]['count']++;
    }
    
    $avegage = array();
    foreach( $summarize as $key => $val ) {
        $avegage[ $key ] = $val['sum'] / $val['count'];
    }