Каждый раз, когда я езжу на своем велосипеде, собирайте второй по второй информации по ряду показателей. Для простоты сделаем вид, что у меня есть файл csv, который выглядит примерно так:
secs, watts,
1,150
2,151
3,149
4,135
.
.
.
7000,160
Таким образом, каждая секунда моей езды имеет связанную с ней мощность, в ваттах.
Я хочу знать: "Если я разорву свою поездку на N вторых блоков, которые блокируют реализовать в высшей средней мощности?"
Я использую pandas dataframe для управления моими данными, и это код, который я использовал для ответа на мой вопрос:
def bestEffort(ride_data,
metric='watts',
interval_length=5,
sort_descending=True):
seconds_in_ride = len(ride_data[metric])
average_interval_list = [[i+1,
np.average(
[ride_data[metric][i+j]
for j in range(interval_length)])
]
for i in range(0,
seconds_in_ride -
interval_length)]
average_interval_list.sort(key=lambda x: x[1], reverse=sort_descending)
return average_interval_list
Кажется просто? Правильно? С учетом индекса вычислите среднее значение последующих интервалов interval_length. Следите за этим в списке формы
[[second 1, avg val of metric over the interval starting that second],
[second 2, avg val of metric over the interval starting that second],
[second 3, avg val of metric over the interval starting that second],
.
.
.
[second 7000-interval_length, avg val of metric over the interval starting that second]]
Затем я сортирую полученный список по средним значениям. Итак, первая запись имеет вид
[second_n, avg val of metric over the interval starting in second n]
сказав мне, что мои самые сильные усилия по заданной длине интервала начались со второго раза в моей тренировке.
Проблема в том, что если я устанавливаю "interval_length" на что-либо выше 30, это вычисление длится вечно (читайте: более двух минут на приличной машине). Пожалуйста, помогите мне найти, где мой код попадает в узкое место, похоже, что он должен быть быстрее.
Если вы поместите свои данные в массив numpy, скажем, watts
, вы можете вычислить среднюю мощность, используя convolve:
mean_power = np.convolve(watts, np.ones(interval_length)/interval_length, mode='valid')
Как вы можете видеть в ссылке np.convolve, эта функция вычисляет локальное среднее первого аргумента, сглаженное с помощью окна, определяемого вторым аргументом. Здесь мы сглаживаем функцию "верхняя шляпа", т.е. Функция "вкл./Выкл.", Которая является постоянной на интервале длины interval_length
и в противном случае равна нулю. Это рудиментарно, но дает первую оценку.
Тогда время ваших самых сильных усилий:
time_strongest_effort = np.argmax(mean_power)
Здесь используется решение pure-pandas с использованием DataFrame.rolling
. Это немного медленнее, чем метод свертывания numpy by @BenBoulderite, но это удобная идиома:
df.rolling(interval_length).mean().shift(-(interval_length - 1))
Для выравнивания средних значений скользящей средней необходим .shift()
чтобы результаты были выровнены по левому краю окна качения, а не по правую сторону по умолчанию (документы в DataFrame.rolling).