Один алгоритм прохождения для нахождения интересная информация процентов наименований


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

Алгоритм у меня до сих пор, чтобы сохранить отсортированный список-интересная информация предметы, которые я видел до сих пор. Так как поток продолжает мне дополнять этот список по мере необходимости. Затем я использую bisect_left , чтобы найти точку вставки, если это необходимо.

Ниже приводится алгоритм у меня до сих пор:

from bisect import bisect_left
from random import uniform
from itertools import islice


def data_gen(num):
    for _ in xrange(num):
        yield uniform(0,1)

def get_top_X_percent(iterable, percent = 0.01, min_guess = 1000):

    top_nums = sorted(list(islice(iterable, int(percent*min_guess)))) #get an initial guess

    for ind, val in enumerate(iterable, len(top_nums)):
        if int(percent*ind) > len(top_nums):
            top_nums.insert(0,None)
        newind = bisect_left(top_nums, val)
        if newind > 0:
            top_nums.insert(newind, val)
            top_nums.pop(0)

    return top_nums

if __name__ == '__main__':

    num = 1000000
    all_data = sorted(data_gen(num))
    result = get_top_X_percent(all_data)
    assert result[0] == all_data[-int(num*0.01)], 'Too far off, lowest num:%f' % result[0] 
    print result[0]

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

Любые предложения будут оценены.



1644
3
задан 14 июля 2011 в 12:07 Источник Поделиться
Комментарии
2 ответа

top_nums = sorted(list(islice(iterable, int(percent*min_guess)))) #get an initial guess

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

for ind, val in enumerate(iterable, len(top_nums))

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

   all_data = sorted(data_gen(num))

Зачем вам сортировка тестовых данных?

Как я понимаю вашу проблему, ваш код неверен. Он работает только в тестовом случае, поскольку вы сортировать поступающие данные.

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

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

Вы могли бы рассмотреть, используя кучу. В Python есть модуль heapq, включая heapq функции.nlargest, который делает очень многое, что вы делаете, (но использует count, а затем в процентах) куча довольно много полу-отсортированный список и позволяет вам делать вещи, как найти/удалить/заменить низкой стоимости без затрат на собственно сортировки.

4
ответ дан 14 июля 2011 в 04:07 Источник Поделиться

Это не может работать, если только вы не оговорили конкретный размер раздела и не вырастить его.

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

Рассмотрим немного надуманный пример, где Х = 0.25. Начальное состояние-это процесс 1/х элементов (4 в данном случае) из которых 1 является максимальной и 3 отбрасываются. Значения 100, 99, 98 и 97. Вы держите 100 как 25% максимум и отбросить 99, 98, 97.

(Вы можете попробовать, чтобы держать все 4 или даже первые 25 значений. Неважно, сколько вы держите изначально с логикой проблемы все равно будут возникать, как только вы поп значение. Я думаю, что надуманный пример, логика недостаток, легче увидеть.)

В какой-то момент, Вы видели 7 значений. Максимумы подмножество имеет значение 1 (100); остальные значения (99, 98, 96, 95, 94 и 93) были отброшены как не входят в набор максимумов.

Вы получаете значение 8, это 92. Вы должны добавить это к топ-сет. Но, к сожалению, ты сбросила больше, чем это.

Когда Вы дойдете до значения 12, вам снова нужно расширить подмножество Максима. Тем не менее, вы отказались значения, которые могут быть больше, чем 12-го значения в последовательности.

Вы не можете сделать поп() от Maxima подмножество, если вы можете доказать, что выскочил должна быть не менее всех будущих значений, которые могут приехать.

1
ответ дан 20 июля 2011 в 01:07 Источник Поделиться