Анализ данных с помощью pandas. Часть 5: ищем самый снежный месяц
Мы уже видели, что pandas хорошо умеет обращаться с датами. Но он также хорошо умеет работать со строками! Возьмём наши данные из предыдущей части.
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'
weather_2012 = pd.read_csv('data/weather_2012.csv', parse_dates=True, index_col='Date/Time')
weather_2012[:5]
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 |
Операции над строками в pandas
Мы видим, что столбец 'Weather' содержит текстовое описание погоды за час. Предположим, что снежная погода в описании содержит "Snow".
pandas позволяет векторизовать операции над строками, позволяя эффективно обрабатывать столбцы. В документации есть много хороших примеров.
In [3]:weather_description = weather_2012['Weather']
is_snowing = weather_description.str.contains('Snow')
Этот код даёт нам бинарный вектор, который не очень красиво выглядит, поэтому мы построим график.
In [4]:is_snowing[:5]
Date/Time 2012-01-01 00:00:00 False 2012-01-01 01:00:00 False 2012-01-01 02:00:00 False 2012-01-01 03:00:00 False 2012-01-01 04:00:00 False Name: Weather, dtype: boolIn [5]:
is_snowing.plot()
Находим снежные месяцы
Если мы хотим медианную температуру за каждый месяц, нужно использовать метод resample()
, как в примере:
weather_2012['Temp (C)'].resample('M').median().plot(kind='bar')
Внезапно, июль и август оказались самыми тёплыми.
Что касается снега, можно считать, что мы имеем дело с векторами из нулей и единиц, вместо True
и False
:
is_snowing.astype(int)[:10]
Date/Time 2012-01-01 00:00:00 0 2012-01-01 01:00:00 0 2012-01-01 02:00:00 0 .. 2012-01-01 07:00:00 0 2012-01-01 08:00:00 0 2012-01-01 09:00:00 0 Name: Weather, dtype: int64
а затем использовать resample
, чтобы найти процент времени, когда шёл снег.
is_snowing.astype(int).resample('M').mean()
Date/Time 2012-01-31 0.240591 2012-02-29 0.162356 2012-03-31 0.087366 ... 2012-10-31 0.000000 2012-11-30 0.038889 2012-12-31 0.251344 Freq: M, Name: Weather, dtype: float64In [9]:
is_snowing.astype(int).resample('M').mean().plot(kind='bar')
Теперь мы знаем! В 2012, декабрь был самым снежным месяцем.
Строим графики температур и снежности вместе
Также можно объединить эти 2 статистики в один DataFrame и построить их графики вместе:
In [10]:temperature = weather_2012['Temp (C)'].resample('M').median()
is_snowing = weather_2012['Weather'].str.contains('Snow')
snowiness = is_snowing.astype(int).resample('M').mean()
# Name the columns
temperature.name = "Temperature"
snowiness.name = "Snowiness"
Снова используем concat
, чтобы объединить колонки в один DataFrame.
stats = pd.concat([temperature, snowiness], axis=1)
stats
Temperature | Snowiness | |
---|---|---|
Date/Time | ||
2012-01-31 | -7.05 | 0.240591 |
2012-02-29 | -4.10 | 0.162356 |
2012-03-31 | 2.60 | 0.087366 |
... | ... | ... |
2012-10-31 | 11.30 | 0.000000 |
2012-11-30 | 1.05 | 0.038889 |
2012-12-31 | -2.85 | 0.251344 |
12 rows × 2 columns
stats.plot(kind='bar')
Ох, это не работает, потому что масштаб выбран неправильно. Лучше построим их на двух разных графиках:
In [13]:stats.plot(kind='bar', subplots=True, figsize=(15, 10))
array([