В завершение этого раздела мы загрузим данные о погоде в Канаде за 2012 год и сохраним их в формате CSV. Это будет сделано поэтапно: сначала загрузим каждый месяц отдельно, а затем объединим все месяцы.

Данные содержат информацию о температуре за каждый час в течение 2012 года!

In [1]:
%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

pd.options.display.max_rows = 7
plt.style.use('ggplot')
plt.rcParams['figure.figsize'] = (15, 3)
plt.rcParams['font.family'] = 'sans-serif'
In [2]:
weather_2012_final = pd.read_csv('data/weather_2012.csv', index_col='Date/Time')
weather_2012_final['Temp (C)'].plot(figsize=(18, 6))
Out[2]:
График загрузки данных за 1 месяц

Загрузка данных за 1 месяц

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

Сначала загружаем данные за 2012 год и удаляем из них ненужную информацию.

Данный URL содержит данные для Монреаля:

In [3]:
url_template = "http://climate.weather.gc.ca/climate_data/bulk_data_e.html?format=csv&stationID=5415&Year={year}&Month={month}&timeframe=1&submit=Download+Data"

Чтобы получить данные за март 2012 года, необходимо форматировать строку с month=3, year=2012.

In [4]:
url = url_template.format(month=3, year=2012)
weather_mar2012 = pd.read_csv(url, skiprows=15, index_col='Date/Time', parse_dates=True, encoding='latin1')

Отлично! Мы можем использовать read_csv для загрузки данных по URL так же, как и с файлами.

Первые 16 строк файла содержат метаданные, но благодаря pandas' read_csv с параметром skiprows, это не проблема. Мы обрабатываем даты и устанавливаем 'Date/Time' в качестве индекса. Вот полученный dataframe:

In [5]:
weather_mar2012
Out[5]:
Year Month Day Time Data Quality Temp (°C) Temp Flag Dew Point Temp (°C) Dew Point Temp Flag Rel Hum (%) ... Wind Spd Flag Visibility (km) Visibility Flag Stn Press (kPa) Stn Press Flag Hmdx Hmdx Flag Wind Chill Wind Chill Flag Weather
Date/Time
2012-03-01 00:00:00 2012 3 1 00:00 -5.5 NaN -9.7 NaN 72 ... NaN 4.0 NaN 100.97 NaN NaN NaN -13.0 NaN Snow
2012-03-01 01:00:00 2012 3 1 01:00 -5.7 NaN -8.7 NaN 79 ... NaN 2.4 NaN 100.87 NaN NaN NaN -13.0 NaN Snow
2012-03-01 02:00:00 2012 3 1 02:00 -5.4 NaN -8.3 NaN 80 ... NaN 4.8 NaN 100.80 NaN NaN NaN -13.0 NaN Snow
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2012-03-31 21:00:00 2012 3 31 21:00 2.6 NaN -6.3 NaN 52 ... NaN 25.0 NaN 100.86 NaN NaN NaN NaN NaN Clear
2012-03-31 22:00:00 2012 3 31 22:00 2.7 NaN -6.7 NaN 50 ... NaN 25.0 NaN 100.82 NaN NaN NaN NaN NaN Clear
2012-03-31 23:00:00 2012 3 31 23:00 1.5 NaN -6.9 NaN 54 ... NaN 25.0 NaN 100.79 NaN NaN NaN NaN NaN Clear

744 rows × 24 columns

Теперь давайте нарисуем график температуры!

In [6]:
weather_mar2012["Temp (°C)"].plot(figsize=(15, 5))
Out[6]:
График температуры

Пора внести изменения в названия некоторых столбцов (столбец "Temp (°C)" не самый удобный).

In [7]:
weather_mar2012.columns = [
    u'Year', u'Month', u'Day', u'Time', u'Data Quality', u'Temp (C)',
    u'Temp Flag', u'Dew Point Temp (C)', u'Dew Point Temp Flag',
    u'Rel Hum (%)', u'Rel Hum Flag', u'Wind Dir (10s deg)', u'Wind Dir Flag',
    u'Wind Spd (km/h)', u'Wind Spd Flag', u'Visibility (km)', u'Visibility Flag',
    u'Stn Press (kPa)', u'Stn Press Flag', u'Hmdx', u'Hmdx Flag', u'Wind Chill',
    u'Wind Chill Flag', u'Weather']

Некоторые колонки почти пустые, поэтому используем функцию dropna для их удаления. Аргумент axis=1 сигнализирует об удалении столбцов, а how='any' удаляет столбец, если в нём есть хотя бы один пустой элемент.

Теперь стало лучше: у нас остались только важные данные.

In [8]:
weather_mar2012 = weather_mar2012.dropna(axis=1, how='any')
weather_mar2012[:5]
Out[8]:
Year Month Day Time Data Quality Temp (C) Dew Point Temp (C) Rel Hum (%) Wind Spd (km/h) Visibility (km) Stn Press (kPa) Weather
Date/Time
2012-03-01 00:00:00 2012 3 1 00:00 -5.5 -9.7 72 24 4.0 100.97 Snow
2012-03-01 01:00:00 2012 3 1 01:00 -5.7 -8.7 79 26 2.4 100.87 Snow
2012-03-01 02:00:00 2012 3 1 02:00 -5.4 -8.3 80 28 4.8 100.80 Snow
2012-03-01 03:00:00 2012 3 1 03:00 -4.7 -7.7 79 28 4.0 100.69 Snow
2012-03-01 04:00:00 2012 3 1 04:00 -5.4 -7.8 83 35 1.6 100.62 Snow

Колонки Year/Month/Day/Time избыточны, а столбец "Data Quality" малоинформативен. Давайте их уберем.

Параметр axis=1 означает удаление колонок, аналогично как раньше dropna и drop обычно удаляют строки, когда используется axis=0.

In [9]:
weather_mar2012 = weather_mar2012.drop(['Year', 'Month', 'Day', 'Time', 'Data Quality'], axis=1)
weather_mar2012[:5]
Out[9]:
Temp (C) Dew Point Temp (C) Rel Hum (%) Wind Spd (km/h) Visibility (km) Stn Press (kPa) Weather
Date/Time
2012-03-01 00:00:00 -5.5 -9.7 72 24 4.0 100.97 Snow
2012-03-01 01:00:00 -5.7 -8.7 79 26 2.4 100.87 Snow
2012-03-01 02:00:00 -5.4 -8.3 80 28 4.8 100.80 Snow
2012-03-01 03:00:00 -4.7 -7.7 79 28 4.0 100.69 Snow
2012-03-01 04:00:00 -5.4 -7.8 83 35 1.6 100.62 Snow

Здорово, теперь работать с этими данными стало намного удобнее.

Дневной график температуры

Это просто, хотя мы уже делали это в предыдущих разделах. Давайте повторим, ведь графики всегда представляют данные информативно и красиво.

In [10]:
temperatures = weather_mar2012[[u'Temp (C)']].copy()
temperatures.loc[:,'Hour'] = weather_mar2012.index.hour
temperatures.groupby('Hour').aggregate(np.median).plot()
Out[10]:
Дневной график температуры

Максимальная температура по медиане наблюдается в 2 часа дня. Отличный результат.

Получаем данные за год

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

Во-первых, у нас имеется функция для загрузки данных за каждый месяц:

In [11]:
def download_weather_month(year, month):
    url = url_template.format(year=year, month=month)
    weather_data = pd.read_csv(url, skiprows=15, index_col='Date/Time', parse_dates=True)
    weather_data = weather_data.dropna(axis=1)
    weather_data.columns = [col.replace('\xb0', '') for col in weather_data.columns]
    weather_data = weather_data.drop(['Year', 'Day', 'Month', 'Time', 'Data Quality'], axis=1)
    return weather_data

Проверим, корректно ли работает функция:

In [12]:
download_weather_month(2012, 1)[:5]
Out[12]:
Temp (C) Dew Point Temp (C) Rel Hum (%) Wind Spd (km/h) Visibility (km) Stn Press (kPa) Weather
Date/Time
2012-01-01 00:00:00 -1.8 -3.9 86 4 8.0 101.24 Fog
2012-01-01 01:00:00 -1.8 -3.7 87 4 8.0 101.24 Fog
2012-01-01 02:00:00 -1.8 -3.4 89 7 4.0 101.26 Freezing Drizzle,Fog
2012-01-01 03:00:00 -1.5 -3.2 88 6 4.0 101.27 Freezing Drizzle,Fog
2012-01-01 04:00:00 -1.5 -3.3 88 7 4.8 101.23 Fog

Приступим к объединению данных всех месяцев. Получим их следующим образом:

In [13]:
data_by_month = [download_weather_month(2012, i) for i in range(1, 13)]

Соединим данные в один dataframe с помощью pd.concat. В итоге у нас будет собрана информация за весь год!

In [14]:
weather_2012 = pd.concat(data_by_month)
weather_2012
Out[14]:
Temp (C) Dew Point Temp (C) Rel Hum (%) Wind Spd (km/h) Visibility (km) Stn Press (kPa) Weather
Date/Time
2012-01-01 00:00:00 -1.8 -3.9 86 4 8.0 101.24 Fog
2012-01-01 01:00:00 -1.8 -3.7 87 4 8.0 101.24 Fog
2012-01-01 02:00:00 -1.8 -3.4 89 7 4.0 101.26 Freezing Drizzle,Fog
... ... ... ... ... ... ... ...
2012-12-31 21:00:00 -0.5 -1.5 93 28 4.8 99.95 Snow
2012-12-31 22:00:00 -0.2 -1.8 89 28 9.7 99.91 Snow
2012-12-31 23:00:00 0.0 -2.1 86 30 11.3 99.89 Snow

8784 rows × 7 columns

Сохранить dataframe в CSV файл

Вы заметили, что функция download_weather_month работает не слишком быстро? Излишне загружать информацию каждый раз, поэтому сохраняем результат в CSV файл для удобного доступа в будущем.

In [15]:
weather_2012.to_csv('data/weather_2012.csv')

Вопросы для самопроверки:

  1. Что означают аргументы axis=1 и how='any' в функции dropna?
  2. Как объединить данные в один DataFrame?
  3. Какой метод используется для сохранения финального DataFrame в CSV файл?