Как отфильтровать поток данных - PullRequest
0 голосов
/ 14 января 2020

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

Генерация случайных данных

# generate random integer values, Filename: Rangen.py
from random import seed
from random import randint
from time import sleep
# seed random number generator
seed(1)
# generate some integers
def rangen():
    value = randint(0, 100)
    return value

while True:
    data = rangen()
    sleep(0.1)

и вот фильтр

from time import sleep
from statistics import mean
from Rangen import data

def AplhaTrimmedfilter(windowsize,alpha, sensordata):
    data_list = []
    Flag = True
    while Flag:
        if len(data_list)<windowsize:
            data_list.append(sensordata)
            print("data added")
            sleep(0.0010)
            break
    if len(data_list)==windowsize:
        sorted_data = data_list.sort()     
        sliced_data = sorted_data[(windowsize/2):windowsize-alpha+(alpha/2)]
        alphamean = statistics.mean(sliced_data) #sum(a) / len(a)
        data_list = []
        print(data_list)
    return alphamean

AlphaTrimmedfilter(5,2,data)

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

Редактировать: как предложил MisterMiyagi, я использовал генераторы для решения проблемы с фильтрацией и перебрал объект-генератор, используя [[item] для item в Filter_data], но теперь у меня есть странный объект TypeError 'Float' не повторяется. Как бы я исправить эту проблему? Я думаю, что это может быть связано с типом данных, которые я передаю в фильтр (который в основном является плавающим). Вот код для модифицированного фильтра, основанный на ответе MisterMiyagi:

def alpha_mean(window, alpha):
    cut = alpha//2
    data = sorted(window)[cut:-cut]
    result = sum(data)/len(data)
    return result

def alphatrimmer(window_size, alpha, sensor_stream):
    window = []
    for item in sensor_stream:
        window.append(item)
        if len(window) >= window_size:
            break
    yield alpha_mean(window, alpha)

    for item in sensor_stream:
        window.pop(0)
        window.append(item)
        yield alpha_mean(window,alpha)

1 Ответ

1 голос
/ 14 января 2020

Python Собственный эквивалент потоков - итераторы. Вы можете создать свой собственный итератор, написав генератор. Например, мы можем превратить вашу функцию rangen с одним значением в функцию генератора с большим количеством значений .

# stream.py
import random

random.seed(1)

def random_stream():
    """Generator producing a stream of random numbers"""
    while True:      # generators can produce values indefinitely...
        value = random.randint(0, 100)
        yield value  # ... by yield'ing them

Среди прочего, итераторы / генераторы может потребляться for заявлениями. Вы можете проверить это на консоли Python:

>>> from stream import random_stream
>>> data = random_stream()   # note: the generator is called using ()
>>> for idx, item in enumerate(data):
...     if idx >= 3: break
...     print(idx, ':', item)
0 : 17
1 : 72
2 : 97

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

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

def alpha_mean(window, alpha):
    """Compute the mean for a given window and alpha"""
    size = len(window)
    data = sorted(window)[size//2:size - (alpha // 2)]
    return sum(data) / len(data)


def alpha_trim(window_size, alpha, sensor_stream):
    """Produce a trimmed stream based on the ``sensor_stream`` data"""
    window = []  # note: a collections.deque is more efficient for very large windows
    # fill the first window
    for item in sensor_stream:
        window.append(item)
        if len(window) >= window_size:
            break
    yield alpha_mean(window, alpha)
    # advance the window as new data comes in
    for item in sensor_stream:
        # "move" the window by discarding the oldest value
        window.pop(0)
        window.append(item)
        yield alpha_mean(window, alpha)

alpha_trim - это генератор, который также принимает генератор. Вы можете проверить это снова в консоли Python:

>>> data = alpha_trim(5, 2, rangen())
>>> for idx, item in enumerate(data):
...     if idx >= 5: break
...     print(idx, ':', item)
0 : 52.0
1 : 52.0
2 : 47.5
3 : 47.5
4 : 60.0
...