{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Исследование данных с помощью Pandas и Seaborn\n", "Шестаков А.В. Майнор по анализу данных - 19/01/2016" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Модуль [Pandas](http://pandas.pydata.org/) существенно упрощает работу с табличными данными в Python. Работа в нем во многом напоминает работу с таблицами в SQL с тем отличием, что в Pandas ~~тебе не хочется рвать волосы на голове~~ это делать гораздо проще, и в нем заложены некоторые дополнительные инструменты по работе с данными.\n", "\n", "Как уже было оговорено на предыдущем семинаре, помимо стандартной библиотеки matplotlib, для \"рисования\" в Python можно использовать достойную альтернативу, чем сейчас и займемся." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import pandas as pd\n", "\n", "plt.style.use('ggplot')\n", "\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Основные структуры" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Основными структурами являются Series и DataFrame.
\n", "Series – это проиндексированный одномерный массив значений. Он похож на простой словарь типа dict, где имя элемента будет соответствовать индексу, а значение – значению записи." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "ser = pd.Series(np.random.rand(5), index=['a', 'b', 'c', 'd', 'e'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В Pandas предусмотрены разные способы индексирования" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "ser.index" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "ser['a']" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "ser[['a', 'b']]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "ser.loc['a']" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "ser[0]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# ser.iloc['a']\n", "ser.iloc[0]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "idx = ser>0.5\n", "ser[idx]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Автоматическое выравнивание по индексу\n", "print ser + ser[1:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "DataFrame — это проиндексированный многомерный массив значений, соответственно каждый столбец DataFrame, является структурой Series. Индексирование в DataFrame ровно тоже, что и в Series, с тем отличием, что добавляется второе измерение." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "df = pd.DataFrame(np.random.randn(10, 3),\n", " index=range(10),\n", " columns=['A', 'B', 'C'])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print df.index\n", "print df.columns" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df[['A', 'B']]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.loc[1:3, ['A', 'B']]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.iloc[1:3, 0:2]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.ix[1:3, ['A', 'B']]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "idx = df>0\n", "idx" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Есть некоторые нюансы с форматом индексов, а так же нюансы, возникающие при присваивании значений в DataFrame.\n", "С ними вы встретитесь на практике. В общем [RTFM](http://pandas.pydata.org/pandas-docs/stable/indexing.html)!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Достаточно полезная команда, позволяющая \"мельком\" взглянуть на вашу таблицу с данными" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Краткая описательная статистика" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.describe()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Перевод данных в нужный тип" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.dtypes" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.A = df.A.astype(int)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.dtypes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Важно контролировать какой тип данных содержится в колонке. Иногда это можно сэкономить уйму времени при отлове багов в работе программы.**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В DataFrame можно хранить данные разной природы" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.loc[0, 'A'] = 'lalaley'\n", "df.head()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.dtypes" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.iloc[0:4, 0].values" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Удаление\\добавление строк" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.drop(0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.loc[0] = [1,2,3] " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Продолжим обучение на реальных \"данных\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В 1968 году была [опубликована](http://www.ncbi.nlm.nih.gov/pubmed/5676802) статья под интригующем названием Correlation of Performance Test Scores with Tissue Concentration of Lysergic Acid Diethylamide in Human Subjects.\n", "\n", "К статье приложен небольшой набор [данных](https://www.dropbox.com/s/z9m3fpq39nmhumy/drugs-and-math.csv?dl=0), состоящий из 7 наблюдений" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "data_types = {'Drugs': float,\n", " 'Score': float}\n", "df = pd.read_csv('drugs-and-math.csv', index_col=0, sep=',', dtype=data_types)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print df.shape\n", "print df.columns\n", "print df.index" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Таблица уже отсортирована по колонке Drugs, сделаем сортировку по Score" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.sort_values('Score', \n", " ascending=False, \n", " inplace=True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.describe().T # Иногда так лучше" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Рисунки" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.plot(kind='box')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.plot(x='Drugs', y='Score', kind='bar')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# df.plot(x='Drugs', y='Score')\n", "df.plot(x='Drugs', y='Score', kind='scatter')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Мы явно видим тенденцию.." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.corr(method='pearson')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ну и напоследок графичек от seaborn!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import seaborn as sns" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# sns.regplot(x='Drugs', y='Score', data=df)\n", "sns.jointplot(x='Drugs', y='Score', \n", " data=df, kind='reg')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Еще больше данных!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Давайте рассмотрим какой-нибудь большой датасет.\n", "Скачайте и распакуте следующий [архив](http://stat-computing.org/dataexpo/2009/2008.csv.bz2). Описание полей таблицы дано [здесь](http://www.transtats.bts.gov/Fields.asp?Table_ID=236).\n", "\n", "Данные должны содержать перелеты между аэропортами США в 2008 году." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "df = pd.read_csv('2008.csv', parse_dates=4)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print df.shape\n", "print df.columns" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.head().T" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.describe().T" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Посмотрим, сколько уникальных рейсов у нас представлено\n", "df['FlightNum'].nunique()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Мы можем выполнять какую-нибудь группировку, что того, чтобы расчитывать различные аггрегированные статистики." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Например, найдите топ-3 рейсов, совершивших самые длинные перелеты за 2008 год?\n", "df.groupby('FlightNum')['Distance']\\\n", " .sum().sort_values(ascending=False)\\\n", " .iloc[0:3]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Можно так:\n", "df.groupby('FlightNum')\\\n", " .agg({'Distance': [np.mean, np.sum, 'count'],\n", " 'Cancelled': {'_total': np.sum}})\\\n", " .sort_values(('Distance', 'sum'), ascending=False)\\\n", " .iloc[0:3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Еще полезная функция - построение сводной таблицы" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "pd.crosstab(df.Month, df.DayOfWeek)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Иногда на такого рода таблицы проще смотреть так\n", "plt.imshow(pd.crosstab(df.Month, df.DayOfWeek),\n", " cmap='seismic',interpolation='none')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Гистограммы!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df.hist('Distance', bins=20)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Смотрим на даты!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "df['Date'] = pd.to_datetime(df.Year*10000 + df.Month*100 + df.DayofMonth, \n", " format='%Y%m%d')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "res = df.groupby('Date')['FlightNum'].agg('count')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ничего не заметили?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "res.plot()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "pd.rolling_mean(res, 7).plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Задачи\n", "1. Рассчитать топ-10 массовых перевозчиков.\n", "2. Построить распределение причин отмены рейсов\n", "3. Найти самый популярный маршрут, выдать статистику по данному маршруту.\n", "4. Найти топ-5 рейсов по каждому из типов delay. Каким перевозчикам они принадлежат?\n", "5. Определить, как распределено количество рейсов от времени дня?\n", "6. Определить \"сезонность\" во временных рядах по количеству вылетов на каждый день." ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.11" } }, "nbformat": 4, "nbformat_minor": 0 }