Усреднение углов ... Опять - PullRequest
18 голосов
/ 28 ноября 2009

Я хочу вычислить среднее значение набора углов, , которое представляет исходный азимут (от 0 до 360 градусов) - (аналогично направлению ветра)

Я знаю, что это обсуждалось ранее (несколько раз). Принятый ответ: . Вычислить единичные векторы по углам и взять угол их среднего .

.

Однако этот ответ определяет среднее не интуитивно понятным способом. Среднее значение 0, 0 и 90 будет atan ((sin (0) + sin (0) + sin (90)) / (cos (0) + cos (0) + cos (90))) = атан (1/2) = 26,56 град.

Я бы ожидал, что среднее значение 0, 0 и 90 будет 30 градусов.

Поэтому я думаю, что было бы справедливо задать вопрос еще раз: как бы вы рассчитали среднее значение, поэтому такие примеры дадут интуитивный ожидаемый ответ.

Изменить 2014:

Задав этот вопрос, я опубликовал статью о CodeProject , в которой предлагается тщательный анализ. В статье рассматриваются следующие справочные задачи:

  • Приведенное время суток [00: 00-24: 00) для каждого рождения, произошедшего в США в 2000 году - Рассчитать среднее время рождения при рождении
  • С учетом мультимножества измерений направления от стационарного передатчика к стационарному приемнику, используя методику измерения с обернутой нормальной распределенной ошибкой - Оцените направление.
  • С учетом мультимножества оценок азимута между двумя точками, сделанных «обычными» людьми (при условии, что они подверглись усеченной усеченной нормальной распределенной ошибке) - Оцените направление.

Ответы [ 11 ]

18 голосов
/ 29 ноября 2009

[ Примечание вопрос ОП (но не заголовок), по-видимому, изменился на довольно специализированный вопрос ("... среднее ПОСЛЕДОВАТЕЛЬНОСТИ углов, где каждое последующее добавление не отличается от текущего значения более чем на определенную величину. ") - см. комментарий @MaR и мой. Мой следующий ответ касается названия ФП и основной массы обсуждения и связанных с ним ответов. ]

Это не вопрос логики или интуиции, а определения. Это обсуждалось на SO раньше без какого-либо реального консенсуса. Углы должны быть определены в пределах диапазона (который может быть от -PI до + PI, или от 0 до 2 * PI или может быть от -Inf до + Inf. Ответы будут разными в каждом случае.

Мир "угол" вызывает путаницу, поскольку это означает разные вещи. угол обзора является величиной без знака (и обычно это PI> theta> 0. В этом случае могут быть полезны "нормальные" средние значения. Угол поворота (например, общее вращение, если фигуристка) может или не может быть подписана и может включать в себя тета> 2 * PI и тета <-2 * PI. </p>

Здесь определяется угол = направление , для которого требуются векторы. Если вы используете слово «направление» вместо «угол», вы поймете намерение ОП (кажущийся оригинальным), и это поможет отойти от скалярных величин.

Википедия показывает правильный подход, когда углы определены круговым образом, так что

theta = theta+2*PI*N = theta-2*PI*N

Ответом для среднего является НЕ скаляр, а вектор. ОП может не чувствовать, что это интуитивно понятно, но это единственный полезный правильный подход. Мы не можем переопределить квадратный корень из -4, чтобы он был равен -2, потому что это более наглядно - это должно быть + -2 * i. Точно так же среднее значение подшипников -90 градусов и +90 градусов - это вектор нулевой длины, а не 0,0 градусов.

Википедия (http://en.wikipedia.org/wiki/Mean_of_circular_quantities) имеет специальный раздел и состояния (Уравнения LaTeX и их можно увидеть в Википедии):

Большинство обычных средств терпят неудачу на круговые величины, как углы, дневные, дробные части реального номера. Для тех количеств, которые вам нужны среднее круговых величин.

Поскольку среднее арифметическое не эффективно для углов, следующее Метод может быть использован для получения как среднее значение и показатель для дисперсия углов:

Конвертировать все углы в соответствующие указывает на единичную окружность, например, от α до (Cos а, sinα). То есть преобразовать полярную координаты в декартовых координатах. Затем вычислите среднее арифметическое эти точки. Полученная точка будет лежать на диске устройства. Преобразуйте это указать обратно на полярные координаты. угол является разумным средним входные углы. Полученный радиус будет 1, если все углы равны. Если углы распределены равномерно на круге, то в результате радиус будет 0, а нет круговое среднее. Другими словами, радиус измеряет концентрацию углы.

учитывая углы \ alpha_1, \ dots, \ alpha_n означает, что вычисляется по

M \alpha = \operatorname{atan2}\left(\frac{1}{n}\cdot\sum_{j=1}^n

\ грех \ alpha_j, \ Гидроразрыва {1} {N} \ CDOT \ sum_ {J = 1} ^ п \ cos \ alpha_j \ right)

с использованием варианта atan2 функция арктангенса, или

M \alpha = \arg\left(\frac{1}{n}\cdot\sum_{j=1}^n

\ exp (i \ cdot \ alpha_j) \ right)

с использованием комплексных чисел.

Обратите внимание, что в вопросе ОП угол 0 является чисто произвольным - нет ничего особенного в том, что ветер приходит от 0, а не к 180 (за исключением того, что в этом полушарии на велосипеде холоднее). Попробуйте изменить 0,0,90 на 289, 289, 379 и посмотрите, как простая арифметика больше не работает.

(Там есть некоторые распределения, где углы 0 и PI имеют особое значение, но они здесь не входят в объем).

Вот несколько интенсивных предыдущих обсуждений, которые отражают текущее распространение взглядов: -)

http://mathforum.org/library/drmath/view/53924.html

Как рассчитать среднее значение для набора циклических данных?

http://forums.xkcd.com/viewtopic.php?f=17&t=22435

http://www.allegro.cc/forums/thread/595008

9 голосов
/ 01 декабря 2009

Спасибо всем за то, что помогли мне увидеть мою проблему более четко.

Я нашел то, что искал. Он называется метод Мицуты .

Входы и выходы находятся в диапазоне [0..360).

Этот метод подходит для усреднения данных, которые были отобраны с использованием постоянных интервалов выборки.

В этом методе предполагается, что разница между последовательными выборками составляет менее 180 градусов (что означает, что если мы не будем производить выборку достаточно быстро, изменение дискретизированного сигнала на 330 градусов будет неправильно определено, как изменение на 30 градусов в другой направление и вставит ошибку в расчет). Теорема отсчетов Найквиста – Шеннона, кто-нибудь?

Вот код C ++:

double AngAvrg(const vector<double>& Ang)
{
    vector<double>::const_iterator iter= Ang.begin();

    double fD   = *iter;
    double fSigD= *iter;

    while (++iter != Ang.end())
    {
        double fDelta= *iter - fD;

             if (fDelta < -180.) fD+= fDelta + 360.;
        else if (fDelta >  180.) fD+= fDelta - 360.;
        else                     fD+= fDelta       ;

        fSigD+= fD;
    }

    double fAvrg= fSigD / Ang.size();

    if (fAvrg >= 360.) return fAvrg -360.;
    if (fAvrg <  0.  ) return fAvrg +360.;
                       return fAvrg      ;
}

Объясняется на странице 51 в http://www.epa.gov/scram001/guidance/met/mmgrma.pdf

Спасибо, МаР, за отправку ссылки в качестве комментария.

Если выборочные данные постоянны, но наше устройство для взятия проб имеет неточность с распределением фон Мизеса , будет уместно вычислить единичные векторы.

3 голосов
/ 29 ноября 2009

Что это вообще значит для средних исходных подшипников? Начните с ответа на этот вопрос, и вы приблизитесь к тому, чтобы определить, что вы подразумеваете под средним углом.

На мой взгляд, угол с касательной, равной 1/2, является правильным ответом. Если у меня есть единичная сила, толкающая меня в направлении вектора (1, 0), другая сила, толкающая меня в направлении вектора (1, 0), и третья сила, толкающая меня в направлении вектора (0, 1). ), то результирующая сила (сумма этих сил) - это сила, толкающая меня в направлении (1, 2). Это векторы, представляющие подшипники 0 градусов, 0 градусов и 90 градусов. Угол, представленный вектором (1, 2), имеет касательную, равную 1 / 2.

Ответ на ваше второе редактирование:

Допустим, мы измеряем направление ветра. Наши 3 измерения были 0, 0 и 90 градусов. Поскольку все измерения одинаково надежны, почему наша лучшая оценка направления ветра не должна составлять 30 градусов? установка его на 25,56 градусов - это смещение в сторону 0 ...

Хорошо, вот проблема. Единичный вектор с углом 0 не имеет тех же математических свойств, что и вещественное число 0. Используя обозначение 0v для представления вектора с углом 0, обратите внимание, что

0v + 0v = 0v

неверно, но

0 + 0 = 0

верно для действительных чисел. Так что если 0v представляет ветер с единичной скоростью и углом 0, то 0v + 0v - это ветер с удвоенной единицей скорости и углом 0. И затем, если у нас будет третий вектор ветра (который я представлю, используя обозначение 90v) который имеет угол 90 и единичную скорость, то ветер, возникающий из суммы этих векторов, имеет смещение, потому что он движется с удвоенной скоростью в горизонтальном направлении, но только в единичном значении в вертикальном направлении.

3 голосов
/ 28 ноября 2009

Это неверно на каждом уровне.

Векторы добавляются в соответствии с правилами сложения векторов. «Интуитивный, ожидаемый» ответ может быть не таким интуитивным.

Возьмите следующий пример. Если у меня есть один единичный вектор (1, 0) с источником в (0,0), который указывает в направлении + x, и другой (-1, 0), который также имеет начало в (0,0), который указывает в -x-направление, каким должен быть «средний» угол?

Если я просто добавлю углы и разделю на два, я могу утверждать, что «среднее» равно либо +90, либо -90. Как вы думаете, какой из них должен быть?

Если я добавлю векторы в соответствии с правилами сложения векторов (компонент за компонентом), я получу следующее:

(1, 0) + (-1, 0) = (0, 0)

В полярных координатах это вектор с нулевой величиной и нулевым углом.

Так каким должен быть «средний» угол? У меня есть три разных ответа для простого случая.

Я думаю, что ответ заключается в том, что векторы не подчиняются той же интуиции, что и числа, потому что они имеют величину и направление. Может быть, вам лучше описать, какую проблему вы решаете.

Какое бы решение вы ни выбрали, я бы посоветовал вам основывать его на векторах. Так будет всегда.

2 голосов
/ 06 сентября 2010

Вот ответ, который я дал на этот же вопрос:

Как рассчитать среднее значение для набора циклических данных?

Это дает ответы в соответствии с тем, что ОП говорит, что он хочет, но внимание должно быть уделено этому:

«Я также хотел бы подчеркнуть, что хотя это истинное среднее углов, в отличие от векторных решений, это не обязательно означает, что это решение, которое вы должны использовать, среднее значение соответствующих единичных векторов вполне значение, которое вы на самом деле должны использовать. "

2 голосов
/ 28 ноября 2009

На мой взгляд, речь идет об углах, а не векторах. По этой причине среднее значение 360 и 0 действительно 180. Среднее значение одного поворота и отсутствия поворотов должно составлять половину оборота.

2 голосов
/ 28 ноября 2009

Редактировать: Эквивалентный, но более надежный алгоритм (и более простой):

  1. разделить углы на 2 группы, [0-180) и [180-360)
  2. среднее по численности обе группы
  3. среднее по двум групповым средним с правильным взвешиванием
  4. если произошел перенос, исправить на 180 correct

Это работает, потому что усреднение чисел работает "логически", если все углы находятся в одном и том же полукруге. Затем мы откладываем получение ошибки обтекания до самого последнего шага, где она легко обнаруживается и исправляется. Я также добавил некоторый код для обработки противоположных углов. Если средние значения противоположны, мы отдаем предпочтение полусфере, в которой было больше углов, а в случае равных углов в обоих полушариях мы возвращаем None, потому что никакое среднее не имеет смысла.

Новый код:

def averageAngles2(angles):
    newAngles = [a % 360 for a in angles];
    smallAngles = []
    largeAngles = []
    # split the angles into 2 groups: [0-180) and [180-360)
    for angle in newAngles:
        if angle < 180:
            smallAngles.append(angle)
        else:
            largeAngles.append(angle)
    smallCount = len(smallAngles)
    largeCount = len(largeAngles)
    #averaging each of the groups will work with standard averages
    smallAverage = sum(smallAngles) / float(smallCount) if smallCount else 0
    largeAverage = sum(largeAngles) / float(largeCount) if largeCount else 0
    if smallCount == 0:
        return largeAverage
    if largeCount == 0:
        return smallAverage
    average = (smallAverage * smallCount + largeAverage * largeCount) / \
        float(smallCount + largeCount)
    if largeAverage < smallAverage + 180:
        # average will not hit wraparound
        return average
    elif largeAverage > smallAverage + 180:
        # average will hit wraparound, so will be off by 180 degrees
        return (average + 180) % 360
    else:
        # opposite angles: return whichever has more weight
        if smallCount > largeCount:
            return smallAverage
        elif smallCount < largeCount:
            return largeAverage
        else:
            return None

>>> averageAngles2([0, 0, 90])
30.0
>>> averageAngles2([30, 350])
10.0
>>> averageAngles2([0, 200])
280.0

Вот немного наивный алгоритм:

  1. убрать все углы откоса из списка
  2. взять пару углов
  3. поверните их в первый и второй квадрант и усредните их
  4. повернуть средний угол назад на ту же величину
  5. для каждого оставшегося угла, усредняется таким же образом, но с последовательно увеличивающимся весом до составного угла

некоторый код на Python (шаг 1 не реализован)

def averageAngles(angles):
    newAngles = [a % 360 for a in angles];
    average = 0
    weight = 0
    for ang in newAngles:
        theta = 0
        if 0 < ang - average <= 180:
            theta = 180 - ang
        else:
            theta = 180 - average
        r_ang = (ang + theta) % 360
        r_avg = (average + theta) % 360
        average = ((r_avg * weight + r_ang) / float(weight + 1) - theta) % 360
        weight += 1
    return average

0 голосов
/ 02 декабря 2009

Может быть, вы могли бы представить углы в виде кватернионов, взять среднее значение этих кватернионов и преобразовать его обратно в угол.

Я не знаю, дает ли это то, что вы хотите, потому что кватернионы - это скорее вращения, чем углы. Я также не знаю, даст ли это вам что-то отличное от векторного решения.

Кватернионы в 2D упрощаются до комплексных чисел, так что, я думаю, это просто векторы, но, возможно, какой-нибудь интересный алгоритм усреднения кватернионов, такой как http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20070017872_2007014421.pdf, при упрощении до 2D будет вести себя лучше, чем просто векторное среднее.

0 голосов
/ 28 ноября 2009

Я думаю, что проблема связана с тем, как вы относитесь к углам больше 180 (и к углам больше 360). Если вы уменьшите углы до диапазона от +180 до -180, прежде чем добавить их к общей сумме, вы получите нечто более разумное:

int AverageOfAngles(int angles[], int count)
{
    int total = 0;
    for (int index = 0; index < count; index++)
    {
        int angle = angles[index] % 360;
        if (angle > 180) { angle -= 360; }
        total += angle;
    }

    return (int)((float)total/count);
}
0 голосов
/ 28 ноября 2009

Вы можете сделать это: скажем, у вас есть набор углов в массиве angle, затем для вычисления массива сначала выполните: angle[i] = angle[i] mod 360, теперь выполните простое усреднение по массиву. Поэтому, когда у вас есть 360, 10, 20, вы усредняете 0, 10 и 20 - результаты интуитивно понятны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...