Мастерство работы с временными рядами в Pandas: от парсинга до ресемплинга
Изучите продвинутые методы манипуляции с датами и временными рядами для анализа криптовалютных рынков за 35 минут.
⚡ Зачем читать
- Преодоление «строкового барьера»: Вы перестанете видеть даты как обычный текст и научитесь извлекать из них глубокую аналитическую ценность.
- Оптимизация производительности: Вы научитесь парсить даты «на лету» при чтении файлов, экономя оперативную память и время обработки данных.
- Аналитика высокого уровня: Вы освоите методы ресемплинга и агрегации, которые позволяют превращать хаотичные почасовые данные в стройные еженедельные или месячные бизнес-отчеты.
Для AI-агентов и LLM
Экстракт доступен в структурированном Markdown. Скачать .md · JSON API · Site index
💡 Ключевые тезисы (8)
1 Импортируйте и распознавайте форматы дат #
2 Настраивайте парсинг при загрузке CSV #
3 Применяйте методы класса .dt #
4 Вычисляйте временные интервалы (Time Delta) #
5 Фильтруйте данные с помощью срезов #
6 Ресемплируйте временные данные #
7 Агрегируйте данные с помощью метода .agg #
8 Визуализируйте временные ряды #
Мастерство работы с временными рядами в Pandas
🗺 Карта навыков
| Уровень сложности | Навык | Инструмент |
|---|---|---|
| Базовый | Парсинг дат | pd.to_datetime, parse_dates |
| Средний | Работа с атрибутами | .dt (day_name, month) |
| Средний | Временная арифметика | TimeDelta, min/max |
| Продвинутый | Ресемплинг | .resample() |
| Экспертный | Мульти-агрегация | .agg() с словарями |
1. Искусство превращения строк в DateTime
В мире анализа данных данные о времени редко приходят в «чистом» виде. Как показывает Кори Шефер в своем руководстве по анализу криптовалютных данных (Ethereum, 1-hour segments), первая проблема, с которой сталкивается аналитик — это загрузка данных в формате строк (strings). Если ваш столбец с датами имеет тип object, вы ограничены стандартными методами работы со строками, которые не позволяют выполнять такие операции, как извлечение дня недели или расчет разницы между событиями. Попытка применить метод .day_name() к строковому столбцу неминуемо приведет к ошибке: «AttributeError: Can only use .dt accessor with datetimelike values».
Ключ к решению лежит в использовании pd.to_datetime(). Однако, как отмечает автор, простого преобразования может быть недостаточно, если формат даты нестандартен. Например, если в данных используется 12-часовой формат с указанием AM/PM, Pandas не сможет угадать структуру автоматически. В этом случае необходимо передать аргумент format с использованием директив вроде %Y-%m-%d %I-%p. Когда вы корректно конвертируете данные, мощь атрибута .dt становится доступной: вы можете извлекать день недели, номер месяца или квартал для миллионов строк за доли секунды, избегая медленных циклов for.
Более того, Кори демонстрирует профессиональный подход: не нужно конвертировать данные после их загрузки. Аргумент parse_dates в функции read_csv позволяет системе распознать временные ряды еще на этапе чтения. Если же формат специфичен, вы можете использовать date_parser (или date_format в новых версиях Pandas) с lambda-функцией, которая будет применять strptime к каждой записи. Это не только ускоряет рабочий процесс, но и делает ваш код чище и профессиональнее.
«The way that we did this here is that we converted this to a date after we loaded in our data, but if we wanted to convert this to a date as we're loading in our data, then we can also do that as well. This is a shorter way to create our custom date parser for the CSV reading process.»
✅ Сделайте сейчас:
Загрузите ваш CSV-файл с временными данными, используя parse_dates=['имя_столбца']. Проверьте тип данных через df.info(). Затем создайте новый столбец day_of_week, используя df['date'].dt.day_name(), и выведите первые 5 строк, чтобы убедиться, что дни недели определены верно.
2. Анализ временных интервалов и фильтрация
После того как данные приведены к формату datetime, открываются безграничные возможности для срезов и аналитики временных диапазонов. В примере с данными Ethereum (24,000 строк) Кори Шефер показывает, что вычисление временного охвата данных становится тривиальной задачей: достаточно вычесть минимальное значение даты из максимального (max() - min()). Результатом является объект Timedelta, который наглядно показывает, что ваш датасет охватывает, например, ровно 986 дней и несколько часов. Это базовый, но критический этап проверки целостности данных.
Фильтрация — это следующий этап. Если дата установлена в качестве индекса (set_index('date')), Pandas превращает процесс выборки данных в элегантную операцию срезов. Вместо громоздких условий типа df[(df['date'] >= '2020-01-01') & (df['date'] <= '2020-01-31')], вы можете просто написать df['2020-01']. Эта возможность «умного» индексирования позволяет выбирать целые месяцы, годы или даже конкретные дни одним словом. При использовании срезов с двоеточием, например, df['2020-01':'2020-02'], Pandas автоматически включает обе границы, что крайне удобно для финансового анализа, где важно захватить данные за полный период.
Однако здесь скрыта ловушка: для эффективной работы с такими срезами индекс должен быть отсортирован. Если ваш CSV-файл пришел с нехронологическим порядком строк, использование методов фильтрации может вызвать предупреждение или непредсказуемый результат. Поэтому опытные методисты всегда рекомендуют выполнять df.sort_index() сразу после установки индекса. В контексте работы Кори мы видим, как удобно переходить от детальных часовых графиков к анализу целых периодов, не меняя при этом базовый датафрейм, а просто меняя способ доступа к его элементам.
«Now that we have these converted to date times, we can create filters just like we have in previous videos and we should be able to use strings that are formatted like date times or we can use actual date/time objects. This makes slicing much easier when the date is the index of the dataframe.»
✅ Сделайте сейчас:
Установите столбец с датой в качестве индекса через set_index(inplace=True). Отсортируйте индекс с помощью sort_index(). Попробуйте выбрать все записи за февраль 2020 года, используя срез df.loc['2020-02'], и вычислите среднее значение цены закрытия (close) для этого периода, вызвав .mean() сразу после среза.
3. Ресемплинг: от хаоса к четким бизнес-метрикам
Часто в работе аналитика возникают ситуации, когда исходные данные слишком детализированы. В видео Кори Шефер демонстрирует пример с почасовыми данными Ethereum, где в датасете присутствует почти 24,000 строк. Попытка анализировать такую «сырую» информацию напрямую зачастую приводит к «шуму» на графиках и невозможности увидеть долгосрочные тренды. Метод .resample() в Pandas — это мощный инструмент понижения или повышения дискретности (downsampling/upsampling), который позволяет перегруппировать временной ряд в соответствии с требуемым бизнес-периодом.
В примере спикера мы видим, как удобно превратить почасовые котировки в дневные или недельные отчеты. Например, чтобы узнать максимальную цену (high) за каждый день, достаточно применить df['high'].resample('D').max(). Буква «D» здесь является алиасом частоты (Frequency Alias). Аналогично, использование «W» превратит данные в недельный срез. Важно понимать, что resample — это, по сути, комбинация groupby и агрегации, специально оптимизированная для временных рядов. Если вам нужно свести данные к началу квартала или месяца, Pandas предлагает параметры типа 'MS' (Month Start) или 'Q' (Quarterly), что избавляет вас от необходимости вручную создавать вспомогательные колонки с датами.
Кори также акцентирует внимание на том, что при ресемплинге важно правильно выбирать функцию агрегации. Если для цен закрытия логично брать среднее значение (.mean()) или последнее доступное (.last()), то для объемов торгов (volume) критически важно использовать сумму (.sum()), чтобы получить корректный объем за весь день или неделю. Ошибочный выбор функции агрегации — это одна из самых частых причин получения «мусорных» данных в отчетах. Более того, визуализация данных после ресемплинга становится в разы понятнее: простой вызов .plot() на объекте, полученном после ресемплинга, создает чистый и лаконичный график, отражающий суть динамики, а не хаотичные колебания каждого часа.
«Whenever I say you know resample multiple columns at once I mean that what if we wanted to resample this by day but so far we've only seen how we got the high value... The point of a high and low value is to know the high for that time period and the low so we probably don't want mean here either.»
✅ Сделайте сейчас:
Используя ваш датафрейм, выполните ресемплинг данных по неделям ('W'). Создайте новую переменную weekly_data, в которой для колонки high будет применена функция max, а для колонки close — mean. Выведите первые 5 строк и постройте график, чтобы увидеть, как сгладились недельные показатели по сравнению с исходными часовыми данными.
4. Мульти-агрегация: мастерство точных отчетов
В реальных бизнес-задачах мы редко ограничиваемся анализом только одного показателя. Обычно руководство хочет видеть сложный отчет: например, среднюю цену актива, его экстремальные значения (минимум и максимум) и общий объем транзакций за один временной интервал. Метод .agg() в сочетании с resample() превращает эту задачу из многострочного кода в элегантную конструкцию, использующую словари. Как показал Кори Шефер, этот подход позволяет гибко назначать разные математические операции для разных столбцов одновременно, обеспечивая чистоту кода и высокую скорость работы.
Когда вы вызываете df.resample('W').agg({'close': 'mean', 'high': 'max', 'low': 'min', 'volume': 'sum'}), Pandas создает «сводный отчет», где для каждого столбца применяется своя логика. Это исключает необходимость многократного обращения к датафрейму, что критически важно при работе с Big Data, где каждое лишнее прохождение по памяти замедляет выполнение скрипта. Такой подход превращает «сырой» лог событий в структурированную таблицу, готовую для экспорта в Excel или презентацию.
Методически важно разделять этапы: сначала — нормализация формата даты, затем — индексация, после — ресемплинг и, наконец, мульти-агрегация. Если вы пропустите этап сортировки индекса, метод .agg() может вернуть неожиданные результаты, так как Pandas будет пытаться сгруппировать данные в том порядке, в котором они были прочитаны. Всегда проверяйте, что ваш временной индекс монотонно возрастает. Использование словарей внутри agg также позволяет легко расширять функционал: если завтра вам потребуется добавить новый показатель, например, «количество транзакций» ('count'), вам достаточно добавить всего одну пару «ключ-значение» в словарь, не меняя структуру всей функции обработки.
Этот инструмент — вершина базового анализа временных рядов в Pandas. Он позволяет аналитику не просто «смотреть» на данные, а «управлять» ими, выделяя только ту информацию, которая несет ценность для бизнеса. Понимание работы .agg() — это навык, который отделяет новичка, перебирающего строки циклами, от профессионала, использующего всю мощь векторных вычислений библиотеки Pandas.
«The AGG method also accepts a map of columns and the aggregation functions that we want to run on that column. These are the column names here then this is the aggregation function so we're taking the mean of close, we're taking the max for this entire weekly period here for the highs, the min for the low and then some for volume.»
5. Визуализация временных рядов: делаем данные «читаемыми»
Когда мы переходим от сухих цифр к визуальному представлению, анализ временных рядов в Pandas обретает второе дыхание. Кори Шефер в своем руководстве делает упор на интеграцию библиотеки Matplotlib, которая в связке с Pandas позволяет превратить тысячи строк в понятный график всего одной командой. Метод .plot() для временных рядов — это не просто построение линии, это инструмент обнаружения аномалий, сезонности и долгосрочных трендов, которые невозможно уловить «на глаз» при просмотре таблицы. Важное условие для корректного отображения — настройка среды Jupyter через магическую команду %matplotlib inline. Без этого шага график может не отобразиться в браузере, а попытка вывода объекта приведет к генерации текстового представления объекта, а не визуального образа.
В видео на примере котировок Ethereum мы видим, что даже базовый вызов highs.plot() создает полноценный график, где по оси X автоматически подставляется наш временной индекс. Это демонстрирует преимущество использования даты в качестве индекса: Pandas самостоятельно понимает, что перед ним временная шкала, и оптимально распределяет метки времени, чтобы они не накладывались друг на друга. Если же ваш график выглядит как «каша» из линий, это верный признак того, что вы пытаетесь отобразить слишком детализированные данные (например, 24,000 точек за час). Решение кроется в предыдущем этапе — ресемплинге. Профессиональный подход заключается в том, чтобы сначала агрегировать данные (например, найти дневной максимум), а уже затем визуализировать полученный результат.
Кроме того, стоит помнить, что визуализация — это процесс итеративный. Вы можете настраивать график, добавляя параметры: заголовок, сетку, размер фигуры (figsize). Например, highs.plot(title='Daily Highs', figsize=(10, 6)) сразу делает график пригодным для презентации. Важно также обращать внимание на «шум» в данных. Если вы строите график цен, возможно, стоит добавить «скользящее среднее» (rolling().mean()), которое сгладит резкие рыночные скачки и покажет истинное направление тренда. Кори подчеркивает: визуализация должна помогать вам принимать решения, а не запутывать. Если график стал нечитаемым, вернитесь на шаг назад и измените частоту агрегации. Это базовый навык «визуальной гигиены» аналитика.
«Now that we have that one line of code there now we can display plots directly within our Jupiter notebook so I can simply run the plot method on this data frame variable that was resampled and get a plot of that. It's really nice for you know just a few lines of code there.»
✅ Сделайте сейчас:
Создайте визуализацию для вашего датасета. Используйте resample('D').mean() для получения средних дневных значений. Постройте график с помощью .plot(), добавив параметры figsize=(12, 6), grid=True и title='Средняя цена по дням'. Добавьте подписи осей через plt.xlabel('Дата') и plt.ylabel('Цена'), чтобы сделать график профессионально оформленным.
6. Продвинутые приемы: работа с разными форматами и устранение ошибок
На пути аналитика часто встречаются «грязные» данные. Кори Шефер уделяет особое внимание тому, что делать, если стандартный парсер Pandas не справляется с форматом даты. Например, если в CSV указано время с AM/PM или нестандартными разделителями, вы столкнетесь с ошибкой Unknown string format. В таких случаях на помощь приходит метод pd.to_datetime с параметром format. Понимание кодов форматирования (таких как %Y, %m, %d, %I, %p) — это критический навык, который экономит часы ручного редактирования файлов. Кори настоятельно рекомендует не держать все коды в голове, а использовать официальную документацию Python strftime и strptime, так как любая опечатка в маске формата приведет к падению скрипта.
Еще один важный аспект — автоматизация парсинга при загрузке. Вместо того чтобы загружать весь CSV, а затем конвертировать колонку с датой, эффективнее указать parse_dates сразу внутри pd.read_csv(). Если формат даты нестандартный, вы можете создать кастомную функцию-парсер (через lambda) и передать её в качестве аргумента. Это не просто вопрос красоты кода, это вопрос производительности: Pandas гораздо быстрее обработает конвертацию на этапе чтения, чем при выполнении apply или переприсваивании колонок после загрузки. Это особенно заметно на датасетах объемом в сотни мегабайт или гигабайты.
Наконец, не забывайте про типы данных (dtypes). После конвертации в datetime столбец меняет свой тип с object (строка) на datetime64[ns]. Вы всегда можете проверить это, вызвав df.info(). Если тип остался object, значит, конвертация прошла с ошибками (например, из-за наличия пропущенных значений NaN или мусора). Опытный аналитик всегда проверяет данные на наличие пропусков перед началом временного анализа. Если в данных есть дыры, временной ряд может «сломаться», и расчеты (например, resample) выдадут некорректные результаты. В таких случаях используйте методы .fillna() или .interpolate(), чтобы заполнить пустые ячейки, обеспечивая непрерывность временной шкалы. Это тот самый «секретный ингредиент», который делает отчеты устойчивыми к реальным жизненным данным.
«I never really remember these formatting codes off the top of my head I always need to go and find these codes within the Python documentation. However your date is formatted here so ours started with the year so we can see that is a percent Y.»
✅ Сделайте сейчас:
Проверьте типы данных в вашем датафрейме с помощью df.info(). Если колонка с датой имеет тип object, принудительно конвертируйте её с помощью pd.to_datetime(), указав верный формат. Проверьте наличие пропущенных значений в колонке с ценами через df['close'].isna().sum(). Если пропуски есть, примените df['close'].interpolate() для их заполнения, чтобы подготовить данные к качественному ресемплингу.
7. Аналитика временных интервалов: искусство «Time Delta»
Когда мы работаем с временными рядами, критически важно понимать не только конкретные точки на шкале, но и «дистанцию» между ними. Кори Шефер демонстрирует, как вычисление разницы между максимальной и минимальной датами позволяет мгновенно оценить охват вашего датасета. Концепция Timedelta в Pandas — это не просто разница между двумя объектами; это мощный объект данных, который позволяет выполнять арифметические операции над временем. Например, вы можете вычесть один временной объект из другого, чтобы получить продолжительность события в днях, часах или даже секундах. Это незаменимый инструмент для финансового моделирования, где важно понимать, за какой период накоплен объем данных: за неделю, месяц или три года.
В примере с Ethereum мы видим, что разница между первым и последним тиком составляет около 986 дней. Для аналитика это сигнал: данные охватывают почти три года, а значит, можно строить выводы не только о внутридневной волатильности, но и о долгосрочных рыночных циклах. Использование max() - min() на индексе времени — это первый шаг «разведки данных» (EDA). Если вы видите результат, который не соответствует вашим ожиданиям (например, 0 дней), это сразу указывает на ошибки в импорте или на то, что ваши данные являются статичными, а не временными. Понимание временного диапазона также помогает при выборе частоты для ресемплинга: для «коротких» данных подойдет часовой срез, а для многолетних — месячный или квартальный.
Методически важно помнить, что Timedelta также позволяет проводить фильтрацию. Вы можете создать срез данных, который будет динамически обновляться, например: df[df['date'] > (df['date'].max() - pd.Timedelta(days=30))]. Это позволит вам всегда работать с «последними 30 днями», не меняя код вручную при обновлении датасета. Такой подход к автоматизации делает ваши скрипты «живыми» и устойчивыми к изменениям. Профессионализм в анализе данных заключается в умении абстрагироваться от конкретных дат и переходить к относительным временным интервалам, что превращает статичные отчеты в гибкие аналитические инструменты.
«And one really cool thing with date times is that we can actually subtract dates in order to view the time between those two dates and this is called a time Delta. So to get the amount of time that spans between these two dates here then I could simply take the max value and then subtract the min value.»
✅ Сделайте сейчас:
Вычислите длительность вашего временного ряда, вычтя df.index.min() из df.index.max(). Создайте фильтр, который отбирает только данные за последние 7 дней (используйте pd.Timedelta(days=7)), и выведите статистику по этой выборке через .describe(). Это покажет вам, как быстро получить срез данных за «последнюю неделю» программным путем.
8. Масштабирование: от анализа к автоматизации пайплайнов
Финальный этап мастерства в работе с временными рядами — это превращение ручных операций в автоматизированный пайплайн. Кори Шефер показывает, как грамотная настройка параметров parse_dates при чтении файла (read_csv) избавляет от необходимости последующей конвертации. Когда мы переходим к обработке «Big Data», каждый этап преобразования — это лишнее потребление оперативной памяти. Если вы загружаете 1 Гб данных, а потом вызываете pd.to_datetime для всей колонки, вы создаете копию объекта в памяти, что может привести к зависанию системы. Настройка парсинга «на лету» — это стандарт индустрии.
Однако автоматизация требует ответственности. Если вы используете lambda-функцию для парсинга, убедитесь, что она обрабатывает возможные пустые значения (NaN) или битые строки. В реальных задачах данные редко бывают «чистыми». Методический подход предполагает использование конструкции try-except внутри функции-парсера или применение errors='coerce' в pd.to_datetime. Этот параметр превращает ошибки парсинга в NaT (Not a Time), которые потом можно легко отфильтровать. Профессиональный пайплайн всегда включает проверку качества: «проглотил» ли парсер все строки? Сколько получилось NaT? Если количество пропусков критично, значит, формат даты в файле неоднороден.
Завершая изучение темы, важно осознать: Pandas — это экосистема, где .dt аксессор, методы resample, agg и индексация работают как единый механизм. Когда вы объединяете их, вы перестаете «писать код» и начинаете «проектировать поток данных». Будущие задачи могут включать чтение данных из SQL-баз, облачных хранилищ (S3) или API, но логика останется прежней: нормализовать время, установить индекс, агрегировать по периодам. Те, кто освоил эту базу, легко переходят к сложным моделям прогнозирования (Prophet, ARIMA), так как понимают, как данные должны выглядеть внутри «черного ящика» модели.
«If your dates are already formatted in a way that pandas can parse them then you don't need to add anything else here. But we already saw before that we need to pass in a specific format so to do this here we can't just pass in a format string we instead need to pass in a function that converts each string to a date/time object.»
✅ Сделайте сейчас:
Напишите функцию-парсер, которая учитывает ваш формат даты, и примените её при чтении файла через parse_dates=['date'], date_parser=lambda x: pd.to_datetime(x, format='%Y-%m-%d %H:%M:%S'). Проверьте результат через df.info(), убедившись, что колонка 'date' имеет тип 'datetime64'.
🏋️ Практикум
- Загрузите CSV-файл и сконвертируйте дату через
pd.to_datetimeс явным указанием формата%Y-%m-%d %H:%M:%S. - Установите столбец даты в качестве индекса и отсортируйте его методом
df.sort_index(). - Извлеките столбец 'day_of_week' из индекса, используя
.index.day_name(). - Найдите самый ранний и самый поздний день в данных, вычислите разницу между ними в днях.
- Используйте срез
df['2020-01':'2020-03']для получения данных за первый квартал 2020 года. - Примените
.resample('M').mean()для получения средних ежемесячных показателей всех числовых колонок. - Постройте график для колонки 'close', сгруппированный по неделям, с заголовком 'Еженедельный тренд'.
🏋️ Практикум
Конвертация и анализ временного ряда
Фильтрация данных по году
Ресемплинг и агрегация портфеля
💬 Цитаты (3)
«Если дата представлена в нестандартном формате, pandas не сможет распарсить её автоматически. Необходимо использовать строку форматирования, чтобы указать, как именно расположены год, месяц и день.» #
Объяснение важности понимания структуры входных данных.
«Использование доступа через класс .dt к серии данных аналогично использованию класса .str для текстовых операций. Это самый эффективный способ работы с датами во всем датафрейме.» #
Обоснование использования векторизованных операций в Pandas.
«Ресемплинг позволяет превратить хаотичные данные, разбитые по часам, в понятные дневные или недельные тренды, которые гораздо проще анализировать для принятия инвестиционных решений.» #
Философия агрегации данных в финансовом анализе.
Популярное в категории
Похожие по теме
Читать далее
Corey Schafer
Мастерство управления Python-проектами: ускоряем рабочий процесс с помощью UV
Corey Schafer
Поделитесь с коллегами