company_banner

Заметки Дата Сайентиста: как измерить время забега марафона лежа на диване


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

    Например, помимо Data Science, я давно увлекаюсь атлетикой и одной из целей в беге для меня, конечно, является марафон. А где марафон там и вопрос — за сколько же бежать? Часто ответ на этот вопрос дается на глаз — «ну в среднем бегут» или «вот Х хорошее время»!

    И сегодня мы займемся важным делом — применим Data Science в реальной жизни и ответим на вопрос:

    А что нам говорят данные о московском марафоне?

    Точнее, как уже понятно по таблице в начале — мы соберем данные, разберемся, кто и как бежал. А заодно это поможет понять, стоит ли нам соваться и позволит здраво оценить свои силы!

    TL;DR: Я собрал данные по забегам московского марафона за 2018/2019, проанализиворовал время и показатели участников, а код и данные выложил в открытый доступ.

    Сбор данных


    Путем шустрого гугления мы обнаружили результаты прошлых пары лет, 2019 и 2018 годов.



    Внимательно посмотрел на веб страницу, стало понятно, что данные довольно просто достать — нужно лишь разобраться, какие классы за что отвечают, например, класс “results-table__col-result”, понятное дело, за результат и тд.

    Осталось понять — как достать все данные оттуда.



    И это, оказывается, несложно, ибо тут есть прямая пагинация и собственно мы итерируем по всему отрезку чисел. Бинго, выкладываю собранные данные за 2019 и 2018 год здесь, если кому-то интересно для последующего анализа, то сами данные можно скачать здесь: здесь и здесь.

    С чем тут пришлось повозиться


    • Страница не отдает ошибок — если что-то идет не так, никто не посигналит, сайт просто отдает какие-то данные (например, повторяет прошлую страницу с результатами).
    • В какой-то момент сервер решает, что он устал и перестает отдавать данные и виснет — проблема решается с помощью «поспать и продолжить сбор с прошлой точки».
    • Url-магия — сайт что-то мудрит со ссылками, и нельзя просто поменять год в url и получить результаты другой гонки — приходится ручками через поиск искать и перепроверять, что мы действительно получаем свежие данные — иначе отгружает молча данные последнего года.
    • В какой момент я собирал данные и параметризовал скрипт сбора данных годом — запустил и стал собирать — через час другой у меня было четыре датасета за 2016, 2017… и оказалось, что страница молча отдавала данные за 2019 год — потому что в том месте год вообще игнорировался, что было совершенно неожиданно — вывод стоит всегда проверять такие вещами руками, а не только постфактум — хотя и постфактум, конечно, надо проверять данные.
    • Здесь есть несколько типов NA: DNF, DQ, "-" — придется проводить анализ и перепроверять, и чистить данные, иначе на выходе мусор.
    • Типы данных: время здесь — это timedelta, но из-за перезапусков и невалидных значений приходится поработать с фильтрами и очисткой временных значений, чтобы мы оперировали над чистыми временными результатами для подсчета средних значений — все результаты здесь — это усреднение по тем, кто финишировал и у кого зафиксировано валидное время.

    А вот и код спойлера, если кто-то решит продолжить собирать интересные беговые данные.

    Код парсера
    from bs4 import BeautifulSoup
    import requests
    from tqdm import tqdm
    
    def main():
        for year in [2018]:
            print(f"processing year: {year}")
            crawl_year(year)
    
    
    def crawl_year(year):
        outfilename = f"results_{year}.txt"
        with open(outfilename, "a") as fout:
            print("name,result,place,country,category", file=fout)
        # parametorize year
        for i in tqdm(range(1, 1100)):
            url = f"https://results.runc.run/event/absolute_moscow_marathon_2018/finishers/distance/1/page/{i}/"
            html = requests.get(url)
            soup = BeautifulSoup(html.text)
            names = list(
                map(
                    lambda x: x.text.strip(),
                    soup.find_all("div", {"class": "results-table__values-item-name"}),
                )
            )
            results = list(
                map(
                    lambda x: x.text.strip(),
                    soup.find_all("div", {"class": "results-table__col-result"}),
                )
            )[1:]
            categories = list(
                map(
                    lambda x: x.text.strip().replace(" ",""),
                    soup.find_all("div", {"class": "results-table__values-item-country"}),
                )
            )
            places = list(
                map(
                    lambda x: x.text.strip(),
                    soup.find_all("div", {"class": "results-table__col-place"}),
                )
            )[1:]
            for name, result, place, category in zip(names, results, places, categories):
                with open(outfilename, "a") as fout:
                    print(name, result, place, category, sep=",", file=fout)
    
    
    if __name__ == "__main__":
        main()
    ```
    

    Анализ времени и результатов


    Перейдем к анализу данных и собственно результатов забега. 
    Использовались pandas, numpy, matplotlib и seaborn — все по классике.

    Помимо средних значений по всем массивам, мы отдельно рассмотрим следующие группы:

    • Мужчины — так как я вхожу в эту группу мне интересны именно эти результаты.
    • Женщины — для симметрии.
    • Мужчины до 35 — это условно одна из самых «соревновательных» групп и понятно, что сравнивать мне стоит именно с ними — так как я в этой группе.
    • Отдельно посмотрим на 2018 и 2019 годы — а вдруг что поменялось?.

    Сначала бегло глянем на таблицу ниже — здесь еще раз, чтобы не скроллить: участников стало больше, 95% в среднем добегает до финиша и большая часть участников мужчины. Хорошо, это значит, что в среднем я в основной группе и данные в среднем должно хорошо отображать среднее время для меня. Продолжаем.





    Как мы видим средние показатели за 2018 и 2019 практически не изменились — примерно 1.5 минуты стали быстрее бегуны в 2019 году. Разница между интересующими меня группами незначительна.

    Перейдем к распределениям целиком. И сначала к общему времени забега.


    Как мы видим пик прямо перед 4 часами — это условная отметка для любителей «пробежать хорошо» = «выбежать из 4-х часов», данные подтверждают народную молву.

    Далее, посмотрим, как в среднем изменилась ситуация за год.



    Как мы видим фактически вообще ничего не поменялось — распределения выглядят фактически идентичными.

    Далее рассмотрим распределения по полу:





    В целом оба распределения нормальные с чуть разным центром — мы видим, что пик на мужском так же проявляет себя на основном (общем) распределении.

    Отдельно перейдем к самой интересной для меня группе:



    Как мы видим принципиально картина такая же, как и в целом в мужской группе.
    Отсюда делаем вывод, что 4 часа для меня тоже являются хорошим средним временем.

    Изучаем улучшения участников 2018 → 2019


    Из интересностей: я почему-то думал, что сейчас быстренько соберу данных и можно углубиться в анализ, искать там закономерности часами и тд. Оказалось все наоборот, сбор данных оказался сложнее самого анализа — по классике работа с сетью, сырыми данными, очисткой, форматирование, приведение типов и тд заняло куда больше времени — чем анализ и визуализация. Не стоит забывать, что мелочи отнимают немного времени — но их [мелочей] совсем не мало и в конце они-то и скушают весь ваш вечер.

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

    • 14 человек участвовали оба года и ни разу не финишировали
    • 89 человека добежали в 18 м, но не смогли в 19
    • 124 наоборот
    • Те, кто смогли добежать оба раза в среднем улучшили на 4 минуты свой результат

    Но тут оказалось довольно интересно все:



    То есть в среднем люди чуть чуть улучшают результаты — но вообще разброс невероятный и в обе стороны — то есть хорошо надеяться, что будет лучше — но судя по данным, получается вообще как угодно!

    Выводы


    Я сделал для себя следующие выводы из проанализированных данных

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

    RUVDS.com
    RUVDS – хостинг VDS/VPS серверов

    Комментарии 10

      +1
      Красивая визуализация для 2017 года moscowmarathon2017.datalaboratory.ru/results?runners=1,18
        +2
        «данные подтверждают народную молву» — я бы скорее сказал народная молва определяет данные. Четырехчасовой пик обусловлен исключительно социальными причинами.

        Механизм такой: мне нравится бегать, но соревноваться уже давно неинтересно.
        Чтобы случайно не забить на бег я планирую себе марафон раз в полгода и бегу его на максимальном расслабоне и без нормальной подготовки, целясь на чуть быстрее четырех чтобы было не совсем стыдно. И таких как я — очень много среди регулярных бегунов.

        Ну то есть этот график не говорит о том что в среднем хорошо пробежать из 4х. Этот график говорит о том что средний бегун думает что не стыдно пробежать из 4х.

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

        Ну и в заключение хочу подчеркнуть что цель на забег до которого месяц надо выбирать исходя из времени контрольных стартов, а не из статистики. Но я думаю Вы это итак понимаете :)
          +1
          Теперь про «невероятный» разброс в обе стороны — тут тоже ничего странного и он легко объясним. Самая частая ситуация драматического ухудшения результата — это не травмы с болезнями. Это когда в одном сезоне у тебя этот старт целевой, а в следующем ты его уже бежишь как длительную. Отсюда и ситуации «в 18м добежал, в 19м нет» или «оба раза не добежал». Бежишь до 30го и сходишь, потому что цели финишировать и не стояло.

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

          Ситуации «что-то пошло совсем не так и я финишировал на 40 минут медленнее» разумеется тоже случаются но я предполагаю что их относительно мало
            –1

            Марафон за 4 часа — это просто пробежка на расслабоне с низким темпом. Ну как обычная длительная тренировка, только, для большинства, чуть длинее.

              +2
              Вы как-то совсем забыли про роль пейсмейкеров. Эти ребята собирают вокруг себя толпу и бегут на «ровный» результат, а пейсер на 4 часа — вообще суперзвезда марафона. Но и вокруг других «ровных» времен должны быть свои пики. И у меня есть ощущение, что в категории >4 часов то ли разные времена для пейсмейкеров были в разные годы, то ли кто-то из пейсов перестарался/наоборот отстал.
              Можно посмотреть, за счет каких половозрастных групп прибавилось число участников от года к году.
              На средний темп также очень влияет погода. Каждый градус, минимальная разница в облачности и осадках.
              Марафон вообще ни на что не похож, если вы, конечно, не бегаете 30+км регулярно.
              По всем прикидкам я должен был пробежать свой марафон из 4 часов легко, но было жарко, а опыта столь длинного бега не было. И в итоге первая 20-ка за 1:54, 30-ка за 2:55, а следующие 10км уже за 1:10. Последние 2км скорость была 8-9км/ч, чаще шел чем бежал. Итого 4:20.
              На последней десятке работают те мышцы, о которых просто не знаешь. Например, жутко болел пресс, потому что спина отболела и перестала держать еще после 30км. Плюс очень непонятно, что делать с водой и едой.
                +1
                Плюс очень непонятно, что делать с водой и едой.
                Так есть же пункты питания и гели углеводные.
                  +1
                  Пункты есть. Есть или не есть непонятно :) С какого-то момента есть уже неохота совсем. А вот надо или не надо — загадка. С гелями вроде как советуют быть осторожным и тоже тренировать организм на них, если начать их принимать уже в гонке возможны сюрпризы. С водой тоже советуют не перебарщивать, бывали случаи, что бегуны перебирали с водой и в обморок грохались. Сколько для этого ее надо выпить не сообщается.
                    +2
                    Скажу как марафонец-любитель со стажем.
                    Все сказанное ниже опробовано на себе и более опытных товарищах.

                    Есть или не есть, вот в чем вопрос.
                    Есть! Однозначно. Можно конечно и пренебречь едой, но бежать будет тяжелее и восстановление будет дольше. Тело человека во время марафона испытывает огромные нагрузки и теряется много энергии. Поэтому ему нужна углеводная подпитка. Гели штука специфическая, жкт некоторых людей их не принимает. Поэтому перед серьезным забегом можно потренироваться с ними на длительной тренировке. Но гели дико удобнее долек апельсина, банана на пунктах питания. А на некоторых трейлах, вас и вовсе не пустят на старт без них. Плюс есть выбор вкусов.

                    Пить или не пить.
                    Пить! Без этого вам грозит обезвоживание, последствия будут даже хуже, чем при отказе от еды. Но пить не вволю, а просто чтобы слегка приглушить жажду. Если хлебать как конь, то можно и вовсе, что называется «коней двинуть». Потребность каждого человека в воде — сугубо индивидуальна, просто слушайте свой организм и ориентируйтесь на ощущения.
                +1
                Мои попытки анализа данных с Московского марафона — github.com/ligurio/notebooks/tree/master/running/race-analytics
                  0
                  -del-

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

                  Самое читаемое