Анализ данных с помощью pandas. Часть 3: объединение и группировка данных
Эта часть показывает способы группировки, объединения и дополнения данных.
In [1]:%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('ggplot')
plt.rcParams['figure.figsize'] = (10, 5)
Вернемся к нашему набору данных о велосипедистах. Допустим, я живу в Монреале, и мне любопытно, используется ли велосипед для пригородных поездок, или для развлечения - люди больше катаются на велосипеде в выходные дни или в будние?
Добавляем столбец "день недели"
Загрузим данные
In [2]:bikes = pd.read_csv('data/bikes.csv', sep=';', encoding='latin1', parse_dates=['Date'], dayfirst=True, index_col='Date')
bikes['Berri 1'].plot()
Посмотрим на велодорожку Berri. Это улица в Монреале, с довольно важной велодорожкой.
Создадим dataframe только с велодорожкой Berri.
In [3]:berri_bikes = bikes[['Berri 1']].copy()
berri_bikes[:5]
Berri 1 | |
---|---|
Date | |
2012-01-01 | 35 |
2012-01-02 | 83 |
2012-01-03 | 135 |
2012-01-04 | 144 |
2012-01-05 | 197 |
Далее, нужно добавить колонку "день недели". Во-первых, мы получим его из первого столбца (индекс). Мы не говорили об индексах ранее, но индекс - это то, что находится левее всего dataframe, под 'Date'. Сейчас это все дни в году.
In [5]:berri_bikes.index
DatetimeIndex(['2012-01-01', '2012-01-02', '2012-01-03', '2012-01-04', '2012-01-05', '2012-01-06', '2012-01-07', '2012-01-08', '2012-01-09', '2012-01-10', ... '2012-10-27', '2012-10-28', '2012-10-29', '2012-10-30', '2012-10-31', '2012-11-01', '2012-11-02', '2012-11-03', '2012-11-04', '2012-11-05'], dtype='datetime64[ns]', name='Date', length=310, freq=None)
Некоторые дни пропущены -- здесь только 310 дней.
Pandas имеет набор функционала для работы с промежутками времени, поэтому если мы, например, хотим получить день месяца для каждой строки, то мы можем написать:
In [6]:berri_bikes.index.day
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5], dtype=int32)
Мы хотим день недели, так что:
In [7]:berri_bikes.index.weekday
array([6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0], dtype=int32)
Это дни недели, 0 - понедельник. Теперь, когда мы знаем, как получить день недели, мы можем добавить его как столбец в dataframe.
In [8]:berri_bikes.loc[:,'weekday'] = berri_bikes.index.weekday
berri_bikes[:5]
Berri 1 | weekday | |
---|---|---|
Date | ||
2012-01-01 | 35 | 6 |
2012-01-02 | 83 | 0 |
2012-01-03 | 135 | 1 |
2012-01-04 | 144 | 2 |
2012-01-05 | 197 | 3 |
Добавляем велосипедистов
Это очень просто! Dataframe имеет метод .groupby()
, который группирует по одному или нескольким столбцам. Подробнее можно прочесть в документации.
В нашем случае, berri_bikes.groupby('weekday').aggregate(sum)
означает "Сгруппировать строки по дню недели и затем сложить все значения с одинаковым днём недели".
weekday_counts = berri_bikes.groupby('weekday').aggregate(sum)
# weekday_counts = berri_bikes.groupby('weekday').sum() - можно и так. Даже проще.
weekday_counts
Berri 1 | |
---|---|
weekday | |
0 | 134298 |
1 | 135305 |
2 | 152972 |
3 | 160131 |
4 | 141771 |
5 | 101578 |
6 | 99310 |
Теперь переименуем 0, 1, 2, 3, 4, 5, 6, чтобы понимать, что они означают:
In [10]:weekday_counts.index = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
weekday_counts
Berri 1 | |
---|---|
Monday | 134298 |
Tuesday | 135305 |
Wednesday | 152972 |
Thursday | 160131 |
Friday | 141771 |
Saturday | 101578 |
Sunday | 99310 |
weekday_counts.plot(kind='bar')
В Монреале чаще катаются по будням - здорово!
Соединяем вместе
Соединим все вместе. Всего 6 строк кода!
Если хотите поиграться, попробуйте поменять sum
на max
, numpy.median
, или любую другую функцию на ваш выбор.
bikes = pd.read_csv('data/bikes.csv',
sep=';', encoding='latin1',
parse_dates=['Date'], dayfirst=True,
index_col='Date')
# Add the weekday column
berri_bikes = bikes[['Berri 1']].copy()
berri_bikes.loc[:,'weekday'] = berri_bikes.index.weekday
# Add up the number of cyclists by weekday, and plot!
weekday_counts = berri_bikes.groupby('weekday').aggregate(sum)
weekday_counts.index = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
weekday_counts.plot(kind='bar')