Подтвердить что ты не робот

Усреднение углов... Снова

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

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

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

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

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

Изменить 2014:

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

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

Ответ 1

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

Я нашел то, что искал. Он называется метод Mitsuta​​strong > .

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

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

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

Вот код С++:

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

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

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

Ответ 2

[ Примечание вопрос OP (но не заголовок), похоже, изменился на довольно специализированный вопрос ( "... среднее значение SEQUENCE углов, где каждое последующее сложение не отличается от пробел означает более чем определенное количество." ) - см. комментарий @MaR и мой. Мой следующий ответ касается названия OP и основной части обсуждения и ответов, связанных с ним.]

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

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

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

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

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 arctangent, или

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

Ответ 3

Что вы пытаетесь выполнить?

Нет смысла в среднем градусах. Один пример для всех:

Каково среднее значение 0 и 180? Это 90? 270? Или что-то еще?

Я бы просто подвел итоги векторам и вычислил угол от результата.

Ответ 4

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

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

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

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

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

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

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

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

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

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

Ответ 5

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

В моем сознании правильный ответ - угол с касательной, равный 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

false, но

0 + 0 = 0

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

Ответ 6

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

  • разделите углы на 2 группы, [0-180) и [180-360]
  • числовая средняя обе группы
  • средние средние 2 группы при правильном взвешивании
  • если произошло повреждение, исправьте на 180 °

Это работает, потому что числовое усреднение работает "логически", если все углы находятся в одном и том же полукруге. Затем мы задерживаем получение обходной ошибки до самого последнего шага, где она легко обнаруживается и исправляется. Я также бросил некоторый код для обработки случаев с противоположным углом. Если средние значения противоположны, мы предпочитаем полушарие, у которого в нем больше углов, а в случае равных углов в обоих полушариях мы возвращаем 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

Здесь немного наивный алгоритм:

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

некоторый код 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

Забастовкa >

Ответ 7

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

Ответ 8

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

Как вы вычисляете среднее значение набора данных кругов?

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

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

Ответ 9

Что случилось с принятием набора углов как реальных значений и просто вычислением среднего арифметического этих чисел? Затем вы получите интуитивный (0 + 0 + 90)/3 = 30 град.

Изменить. Спасибо за полезные комментарии и указав, что углы могут превышать 360. Я считаю, что ответ может быть нормальным средним арифметическим уменьшением "по модулю" 360: мы суммируем все значения, делим на количество углов, а затем вычесть/добавить кратное 360, чтобы результат находился в интервале [0..360].

Ответ 10

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

Ответ 11

Я думаю, что проблема связана с тем, как вы обрабатываете углы больше 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);
}

Ответ 12

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

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

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