5

次のような値を持つ配列があるとします。

$values = array(48,30,97,61,34,40,51,33,1);

そして、値が次のような箱ひげ図をプロットできるようにしたい:

$box_plot_values = array(
    'lower_outlier'  => 1,
    'min'            => 8,
    'q1'             => 32,
    'median'         => 40,
    'q3'             => 56,
    'max'            => 80,
    'higher_outlier' => 97,
);

PHPでこれを行うにはどうすればよいですか?

4

3 に答える 3

8
function box_plot_values($array)
{
    $return = array(
        'lower_outlier'  => 0,
        'min'            => 0,
        'q1'             => 0,
        'median'         => 0,
        'q3'             => 0,
        'max'            => 0,
        'higher_outlier' => 0,
    );

    $array_count = count($array);
    sort($array, SORT_NUMERIC);

    $return['min']            = $array[0];
    $return['lower_outlier']  = $return['min'];
    $return['max']            = $array[$array_count - 1];
    $return['higher_outlier'] = $return['max'];
    $middle_index             = floor($array_count / 2);
    $return['median']         = $array[$middle_index]; // Assume an odd # of items
    $lower_values             = array();
    $higher_values            = array();

    // If we have an even number of values, we need some special rules
    if ($array_count % 2 == 0)
    {
        // Handle the even case by averaging the middle 2 items
        $return['median'] = round(($return['median'] + $array[$middle_index - 1]) / 2);

        foreach ($array as $idx => $value)
        {
            if ($idx < ($middle_index - 1)) $lower_values[]  = $value; // We need to remove both of the values we used for the median from the lower values
            elseif ($idx > $middle_index)   $higher_values[] = $value;
        }
    }
    else
    {
        foreach ($array as $idx => $value)
        {
            if ($idx < $middle_index)     $lower_values[]  = $value;
            elseif ($idx > $middle_index) $higher_values[] = $value;
        }
    }

    $lower_values_count = count($lower_values);
    $lower_middle_index = floor($lower_values_count / 2);
    $return['q1']       = $lower_values[$lower_middle_index];
    if ($lower_values_count % 2 == 0)
        $return['q1'] = round(($return['q1'] + $lower_values[$lower_middle_index - 1]) / 2);

    $higher_values_count = count($higher_values);
    $higher_middle_index = floor($higher_values_count / 2);
    $return['q3']        = $higher_values[$higher_middle_index];
    if ($higher_values_count % 2 == 0)
        $return['q3'] = round(($return['q3'] + $higher_values[$higher_middle_index - 1]) / 2);

    // Check if min and max should be capped
    $iqr = $return['q3'] - $return['q1']; // Calculate the Inner Quartile Range (iqr)
    if ($return['q1'] > $iqr)                  $return['min'] = $return['q1'] - $iqr;
    if ($return['max'] - $return['q3'] > $iqr) $return['max'] = $return['q3'] + $iqr;

    return $return;
}
于 2013-10-06T14:42:30.133 に答える
0

より低いウィスカーとより高いウィスカーを計算するための別の解決策があります。ShaoE のソリューションと同様に、下限 (Q1 - 1.5 * IQR) 以上の最小値を見つけ、上限に対してはその逆を見つけます。

whichを使用array_filterして配列を反復処理し、値をコールバック関数に渡し、コールバックが true を返す値のみを含む配列を返します ( php.net の array_filter マニュアルを参照)。この場合、下限より大きい値が返され、minそれ自体が最小値を返す入力として使用されます。

// get lower whisker
$whiskerMin = min(array_filter($array, function($value) use($quartile1, $iqr) {
        return $value >= $quartile1 - 1.5 * $iqr;
    } ));
// get higher whisker vice versa
$whiskerMax = max(array_filter($array, function($value) use($quartile3, $iqr) {
        return $value <= $quartile3 + 1.5 * $iqr;
    } ));

外れ値は無視され、正の値でのみテストしたことに注意してください。

于 2016-11-23T01:23:23.557 に答える