|
Работа с временными рядами в Pandas
ОП.09 Обработка и анализ данных
Практическая работа №6
Тема: Работа с временными рядами в Pandas
Цель работы: Научиться работать с датами и временными рядами: парсить даты, задавать индексы, ресемплировать, скользящее среднее.
Время выполнения: 2 академических часа
Инструменты: Python + Jupyter Notebook, библиотеки pandas, matplotlib, numpy
ЗАДАНИЕ ДЛЯ СТУДЕНТА
Этап 1. Создание временного ряда (10 минут)
Создадим датафрейм с ежедневными продажами:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Создаём диапазон дат
dates = pd.date_range(start='2025-01-01', end='2025-03-31', freq='D')
print(f"Первые 5 дат: {dates[:5]}")
print(f"Последние 5 дат: {dates[-5:]}")
# Создаём датафрейм с продажами
np.random.seed(42)
sales = np.random.randint(100, 500, size=len(dates))
df = pd.DataFrame({
'date': dates,
'sales': sales,
'customers': np.random.randint(10, 60, size=len(dates))
})
print("Первые 5 строк:")
print(df.head())
Вопрос: Какой тип данных у колонки 'date'? Что такое pandas.Timestamp?
Этап 2. Установка даты как индекса (10 минут)
Преобразуем колонку date в индекс для удобства:
# Устанавливаем date как индекс
df.set_index('date', inplace=True)
print("После установки индекса:")
print(df.head())
# Доступ к данным по дате
print("Продажи за 2025-01-15:")
print(df.loc['2025-01-15'])
print("Продажи за январь 2025:")
print(df.loc['2025-01'])
Вопрос: Как получить данные за весь январь? А за период с 10 по 20 января?
Этап 3. Ресемплинг (агрегация по периодам) (20 минут)
Выполните ресемплинг для разных периодов:
# Недельные данные (средние)
weekly = df.resample('W').mean()
print("Недельные средние продажи:")
print(weekly.head())
# Месячные данные (суммы)
monthly = df.resample('ME').sum()
print("Месячные суммы продаж:")
print(monthly)
# Квартальные данные
quarterly = df.resample('QE').agg({
'sales': 'sum',
'customers': 'mean'
})
print("Квартальные данные:")
print(quarterly)
# Разные агрегации
weekly_agg = df.resample('W').agg({
'sales': ['mean', 'min', 'max'],
'customers': 'mean'
})
print("Недельная статистика:")
print(weekly_agg.head())
Вопросы:
• В чём разница между 'W', 'ME' и 'QE'?
• Какой метод лучше для сглаживания дневных шумов?
Этап 4. Скользящее среднее (15 минут)
Добавьте скользящее среднее для сглаживания:
# Скользящее среднее за 7 дней
df['sales_ma7'] = df['sales'].rolling(window=7).mean()
# Скользящее среднее за 14 дней
df['sales_ma14'] = df['sales'].rolling(window=14).mean()
# Скользящая сумма за 7 дней
df['sales_sum7'] = df['sales'].rolling(window=7).sum()
print("Первые 10 строк со скользящими средними:")
print(df.head(10))
# Визуализация
plt.figure(figsize=(12, 6))
plt.plot(df.index, df['sales'], label='Исходные продажи', alpha=0.5)
plt.plot(df.index, df['sales_ma7'], label='Скользящее среднее (7 дней)', linewidth=2)
plt.plot(df.index, df['sales_ma14'], label='Скользящее среднее (14 дней)', linewidth=2)
plt.title('Продажи со скользящим средним')
plt.xlabel('Дата')
plt.ylabel('Продажи')
plt.legend()
plt.show()
Вопрос: Как окно скользящего среднего влияет на гладкость графика?
Этап 5. Сдвиги и разности (15 минут)
Используйте shift() и diff() для анализа изменений:
# Сдвиг на 1 день (продажи вчера)
df['sales_yesterday'] = df['sales'].shift(1)
# Сдвиг на 7 дней (продажи неделю назад)
df['sales_last_week'] = df['sales'].shift(7)
# Изменение за день (разность)
df['sales_change'] = df['sales'] - df['sales_yesterday']
# Изменение в процентах
df['sales_pct_change'] = df['sales'].pct_change() * 100
print("Данные со сдвигами и разностями:")
print(df[['sales', 'sales_yesterday', 'sales_change', 'sales_pct_change']].head(10))
# Анализ: когда были максимальные изменения
max_increase = df.loc[df['sales_change'].idxmax()]
print(f"Максимальный рост продаж: {max_increase['sales_change']} в {max_increase.name}")
Вопрос: Что показывают shift() и diff()? Где они могут пригодиться?
Этап 6. Практическое задание: анализ данных о погоде (25 минут)
Загрузим данные о температуре за год и проведём анализ:
# Создаём данные о температуре за год
dates_full = pd.date_range(start='2024-01-01', end='2024-12-31', freq='D')
np.random.seed(123)
# Симуляция температуры: синусоида + шум
temp_base = 15 + 15 * np.sin(2 * np.pi * (dates_full.dayofyear - 80) / 365)
temp_noise = np.random.normal(0, 3, size=len(dates_full))
temperature = temp_base + temp_noise
weather = pd.DataFrame({
'date': dates_full,
'temp': temperature
})
weather.set_index('date', inplace=True)
print("Данные о температуре:")
print(weather.head())
print(weather.tail())
Выполните анализ:
# 1. Месячные средние температуры
monthly_temp = weather.resample('ME').mean()
print("Средняя температура по месяцам:")
print(monthly_temp)
# 2. Скользящее среднее за 30 дней
weather['temp_ma30'] = weather['temp'].rolling(window=30).mean()
# 3. Самый холодный и самый тёплый день
coldest = weather.loc[weather['temp'].idxmin()]
warmest = weather.loc[weather['temp'].idxmax()]
print(f"Самый холодный день: {coldest.name} ({coldest['temp']:.1f}°C)")
print(f"Самый тёплый день: {warmest.name} ({warmest['temp']:.1f}°C)")
# 4. Визуализация
plt.figure(figsize=(12, 6))
plt.plot(weather.index, weather['temp'], label='Ежедневная температура', alpha=0.5)
plt.plot(weather.index, weather['temp_ma30'], label='Скользящее среднее (30 дней)', linewidth=2)
plt.title('Температура в течение года')
plt.xlabel('Дата')
plt.ylabel('Температура (°C)')
plt.legend()
plt.show()
Вопрос: Какой месяц оказался самым холодным? А самым тёплым? Совпадает ли это с реальностью?
Этап 7. Выводы (10 минут)
Напишите развёрнутый вывод по работе:
1. Зачем нужен ресемплинг временных рядов? Приведите примеры.
2. Что такое скользящее среднее и как оно помогает в анализе?
3. Какие задачи можно решать с помощью shift() и diff()?
КРИТЕРИИ ОЦЕНКИ
| Критерий | Макс. балл |
|---|
| Все этапы выполнены (1-6) | 3 | | Корректное использование resample, rolling, shift, diff | 3 | | Анализ погоды выполнен верно | 2 | | Выводы осмысленные, примеры из работы | 2 | | Итого | 10 |
ОТВЕТ ДЛЯ ПРЕПОДАВАТЕЛЯ (эталонный результат)
Нажмите, чтобы увидеть ответы
Этап 1. Тип данных:
• date — pandas.Timestamp, это специальный тип для работы с датами и временем.
Этап 2. Доступ по дате:
• df.loc['2025-01'] — весь январь.
• df.loc['2025-01-10':'2025-01-20'] — период с 10 по 20 января.
Этап 3. Ресемплинг:
• 'W' — неделя, 'ME' — месяц (конец месяца), 'QE' — квартал (конец квартала).
• Ресемплинг лучше сглаживает дневные шумы, показывая тренд.
Этап 4. Скользящее среднее:
• Чем больше окно, тем глаже график, но больше задержка.
Этап 5. Shift и diff:
• shift() — сдвигает данные (вчера, неделю назад).
• diff() — считает разницу между текущим и предыдущим значением.
• Полезны для расчёта изменений и сравнения с прошлыми периодами.
Этап 6. Погода:
• Самый холодный месяц: январь или февраль (≈ -5°C).
• Самый тёплый месяц: июль (≈ 30°C).
• Результат зависит от симуляции, но в целом соответствует сезонности.
Этап 7. Выводы (пример):
1. Ресемплинг нужен для перехода на другой временной уровень (день → неделя → месяц) и устранения шума.
2. Скользящее среднее сглаживает случайные колебания, выделяя тренд.
3. shift/diff помогают анализировать динамику: рост/падение, сравнение с прошлым периодом.
Автор: УМК СПО
Лицензия: Бесплатное использование с указанием источника
|
|
|