Скользящее среднее для расчета интенсивности осадков - PullRequest
2 голосов
/ 28 ноября 2011

У меня есть некоторые реальные данные об осадках, записанные в виде даты и времени, и накопленное количество наконечников на измерителе дождя с опрокидывающимся ковшом.Опрокидывающееся ведро соответствует 0,5 мм осадков.Я хочу циклически просмотреть файл и определить изменение интенсивности (количество осадков / время). Поэтому мне нужно скользящее среднее значение за несколько фиксированных периодов времени: поэтому я хочу накапливать количество осадков до тех пор, пока не будет накоплено 5 минут дождя, и определить интенсивность в мм /час.Таким образом, если 3 мм записывается за 5 минут, это равно 3/5 * 60 = 36 мм / час.то же количество осадков в течение 10 минут составит 18 мм / ч ...

Так что, если у меня выпадет дождь в течение нескольких часов, мне может потребоваться пересмотреть несколько стандартных интервалов, скажем: 5, 10,15,20,25,30,45,60 минут и т. Д. Кроме того, данные записываются в обратном порядке в необработанном файле, поэтому самое раннее время находится в конце файла, а последний и последний временной шаг появляется первым после заголовка: Похоже... (здесь 975 - 961 = 14 наконечников = 7 мм осадков) средняя интенсивность 1,4 мм / ч. Но между 16:27 и 16:34 967-961 = 6 наконечников = 3 мм за 7 мин = 27,71 мм / час

7424 Figtree (O'Briens Rd)
DATE     :hh:mm Accum Tips
8/11/2011 20:33     975
8/11/2011 20:14     974
8/11/2011 20:04     973
8/11/2011 20:00     972
8/11/2011 19:35     971
8/11/2011 18:29     969
8/11/2011 16:44     968
8/11/2011 16:34     967
8/11/2011 16:33     966
8/11/2011 16:32     965
8/11/2011 16:28     963
8/11/2011 16:27     962
8/11/2011 15:30     961

Есть предложения?

Ответы [ 2 ]

1 голос
/ 28 ноября 2011

Я не совсем уверен, о чем у вас есть вопрос.

Вы знаете, как прочитать файл?Вы можете сделать что-то вроде:

data = [] # Empty list of counts

# Skip the header
lines = [line.strip() for line in open('data.txt')][2::]

for line in lines:
    print line
    date, hour, count = line.split()
    h,m = hour.split(':')
    t = int(h) * 60 + int(m)      # Compute total minutes
    data.append( (t, int(count) ) ) # Append as tuple

data.reverse()

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

data = [(t1, d2 - d1) for ((t1,d1), (t2, d2)) in zip(data, data[1:])]
print data

Теперь мынужно просмотреть и посмотреть, сколько записей за последние x минут.

timewindow = 10
for i, (t, count) in enumerate(data):
    # Find the entries that happened within the last [...] minutes
    withinwindow = filter( lambda x: x[0] > t - timewindow, data )
    # now you can print out any kind of stats about this "within window" entries
    print sum( count for (t, count) in withinwindow )
0 голосов
/ 28 ноября 2011

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

from time import strptime, mktime

totime = lambda x: int(mktime(strptime(x, "%d/%m/%Y %H:%M")))
with open("my_file.txt", "r") as myfile:
    # Skip header
    for line in myfile:
        if line.startswith("DATE"):
            break
    times = []
    values = []
    for line in myfile:
        date, time, value = line.split()
        times.append(totime(" ".join((date, time))))
        values.append(int(value))
times.reverse()
values.reverse()
i = Interpolate(times, values)

Теперь нужно просто выбрать интервалы и вычислить разницу между конечными точками каждого интервала. Давайте создадим функцию генератора для этого:

def rolling_avg(cumulative_lookup, start, stop, step_size, window_size):
    for t in range(start + window_size, stop, step_size):
        total = cumulative_lookup[t] - cumulative_lookup[t - window_size]
        yield total / window_size

Ниже я печатаю количество подсказок в час за предыдущий час с 10-минутными интервалами:

start = totime("8/11/2011 15:30")
stop = totime("8/11/2011 20:33")
for avg in rolling_avg(i, start, stop, 600, 3600):
    print avg * 3600

РЕДАКТИРОВАТЬ: Сделано totime вернуть int и создал генератор rolling_avg.

...