вычислите средний и различие с одним повторением

У меня есть итератор чисел, например, объект файла:

f = open("datafile.dat")

теперь я хочу вычислить:

mean = get_mean(f)
sigma = get_sigma(f, mean)

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

15
задан Ruggero Turra 12 January 2014 в 23:01
поделиться

6 ответов

Если вы хотите выполнить итерацию один раз, вы можете написать свою функцию sum:

def mysum(l):
    s2 = 0
    s = 0
    for e in l:
        s += e
        s2 += e * e
    return (s, s2)

и использовать результат в своей функции sigma.

Edit: теперь вы можете вычислить дисперсию так: (s2 - (s*s) / N) / N

Принимая во внимание комментарий @Adam Bowen,
, имейте в виду, что если мы используем математические уловки и преобразуем исходные формулы
мы можем ухудшить результаты.

12
ответ дан 1 December 2019 в 03:14
поделиться

У вас есть два решения

  1. Составьте список из своего итератора и повторяйте его столько раз, сколько хотите. Недостатком является то, что все будет в памяти, поэтому не подходит, если ваш файл большой. Простое использование itertools.tee также не спасет вас

  2. Нет другого решения, кроме , вам не нужно передавать вывод get_mean в get_sigma, потому что в этом случае они могут быть только последовательно , но если вы удалите это ограничение, вы можете запускать обе функции параллельно, используя потоки, и использовать itertools.tee, чтобы иметь два итератора из одного

0
ответ дан 1 December 2019 в 03:14
поделиться

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

Что-то вроде:

public class LimitedPBQ extends PriorityBlockingQueue {

    private int maxItems;
    public LimitedPBQ(int maxItems){
        this.maxItems = maxItems;
    }

    @Override
    public boolean offer(Object e) {
        boolean success = super.offer(e);
        if(!success){
            return false;
        } else if (this.size()>maxItems){
            // Need to drop last item in queue
            // The array is not guaranteed to be in order, 
            // so you should sort it to be sure, even though Sun's Java 6 
            // version will return it in order
            this.remove(this.toArray()[this.size()-1]);
        }
        return true;
    }
}

Edit: Both add and put invoke offer, поэтому переопределения должно быть достаточно

Edit 2: Should now remove the last element if over maxItems. Возможно, есть более элегантный способ сделать это.

-121--2348266-

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

Прежде всего, возьмите все содержимое абзаца и убедитесь, что все это может быть в нескольких узлах в DOM. ( Read This ) Тогда потребуется создать синтаксический анализатор, который будет искать разделенные символы, игнорируя их, пока они находятся в объектах HTML.

В качестве примера. в атрибуте href следует игнорировать и не разделять. Во время синтаксического анализа можно сохранить число слов, а также разбить работу над местами. Сделайте каждое предложение объектом, содержащим все предложение и число слов. Таким образом, эти объекты можно переместить в массив, представляющий абзац. После этого можно выполнить итерацию в массиве и обернуть любое предложение в диапазон для выделения с помощью CSS, если число слов достигает порогового значения.

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

I'm typing <b> in bold. NOW!</b>

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

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

-121--4501428-

Я думаю, что Ник D имеет правильный ответ.

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

Есть некоторые проблемы с числовой стабильностью, но идея в

http://en.wikipedia.org/wiki/Computational_formula_for_the_variance

является основным ингредиентом, который вам нужен. Некоторые дополнительные детали находятся на

http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance

, где я предлагаю вам прочитать «Наивный алгоритм».

Надеюсь, что это поможет,

Массимо

5
ответ дан 1 December 2019 в 03:14
поделиться

Составьте список из итерируемого объекта или используйте itertools.tee () .

2
ответ дан 1 December 2019 в 03:14
поделиться

Поскольку я чувствую, что в нескольких ответах есть хорошие элементы, я хотел бы подвести итог:

  • Если ваш файл слишком большой, чтобы удобно поместиться в памяти, и если вы хотите получить хорошую точность дисперсии, вам нужно прочитать файл дважды (при одном проходе дисперсия будет разницей между двумя большими числами, что не является точным из-за ограничений плавающей точки). Обратите внимание, что ваша операционная система, скорее всего, обеспечит некоторое автоматическое ускорение при втором чтении файла, поскольку он может все еще находиться в оперативной памяти во время второго прохода.

  • Если вам не важна точность дисперсии, вы можете просто просмотреть файл один раз и вычислить величины, предложенные Nick D, с подробностями, приведенными в комментарии Адама Боуэна.

1
ответ дан 1 December 2019 в 03:14
поделиться

Я не уверен, что есть большой выбор.

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

Если у вас достаточно памяти, вы можете получить доступ к вводу-выводу, загрузив файл в память во время первой итерации, но это все, IMO.

1
ответ дан 1 December 2019 в 03:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: