Поиск по сайту:

Анализ и визуализация данных с помощью pandas и Jupyter Notebook в Python 3


Введение

Пакет Python pandas используется для манипулирования и анализа данных и позволяет работать с размеченными или реляционными данными интуитивно понятным способом.

Пакет pandas предлагает функциональность электронных таблиц, но, поскольку вы работаете с Python, он намного быстрее и эффективнее, чем традиционная программа для работы с электронными таблицами.

В этом руководстве мы рассмотрим настройку большого набора данных для работы с функциями groupby() и pivot_table() pandas и, наконец, как визуализировать данные.

Чтобы получить некоторое представление о пакете pandas, вы можете прочитать наш учебник Введение в пакет pandas и его структуры данных в Python 3.

Предпосылки

В этом руководстве рассказывается, как работать с данными в pandas на локальном рабочем столе или на удаленном сервере. Работа с большими наборами данных может потребовать большого объема памяти, поэтому в любом случае компьютеру потребуется не менее 2 ГБ памяти для выполнения некоторых расчетов в этом руководстве.

В этом уроке мы будем использовать Jupyter Notebook для работы с данными. Если у вас его еще нет, вы должны следовать нашему руководству, чтобы установить и настроить Jupyter Notebook для Python 3.

Настройка данных

В этом руководстве мы будем работать с данными социального обеспечения США об именах детей, которые доступны на веб-сайте социального обеспечения в виде 8-мегабайтного zip-файла.

Давайте активируем нашу среду программирования Python 3 на нашем сервере из правильного каталога:

  1. cd environments
  1. . my_env/bin/activate

Теперь давайте создадим новый каталог для нашего проекта. Мы можем назвать его names и затем перейти в каталог:

  1. mkdir names
  2. cd names

В этом каталоге мы можем извлечь zip-файл с веб-сайта Social Security с помощью команды curl:

  1. curl -O https://www.ssa.gov/oact/babynames/names.zip

После загрузки файла давайте проверим, что у нас установлены все пакеты, которые мы будем использовать:

  • numpy для поддержки многомерных массивов
  • matplotlib для визуализации данных
  • панды для нашего анализа данных
  • seaborn, чтобы сделать нашу статистическую графику matplotlib более эстетичной

Если у вас еще нет установленных пакетов, установите их с помощью pip, например:

  1. pip install pandas
  2. pip install matplotlib
  3. pip install seaborn

Пакет numpy также будет установлен, если у вас его еще нет.

Теперь мы можем запустить Jupyter Notebook:

  1. jupyter notebook

Как только вы окажетесь в веб-интерфейсе Jupyter Notebook, вы увидите там файл names.zip.

Чтобы создать новый файл записной книжки, выберите «Создать» > «Python 3» в правом верхнем раскрывающемся меню:

Это откроет блокнот.

Начнем с импорта пакетов, которые мы будем использовать. В верхней части нашего блокнота мы должны написать следующее:

import numpy as np
import matplotlib.pyplot as pp
import pandas as pd
import seaborn

Мы можем запустить этот код и перейти к новому блоку кода, набрав ALT + ENTER.

Давайте также скажем Python Notebook, чтобы наши графики оставались встроенными:

matplotlib inline

Давайте запустим код и продолжим, набрав ALT + ENTER.

Отсюда мы перейдем к распаковке zip-архива, загрузке набора данных CSV в pandas, а затем объединению pandas DataFrames.

Распаковать Zip-архив

Чтобы распаковать zip-архив в текущий каталог, мы импортируем модуль zipfile, а затем вызовем функцию ZipFile с именем файла (в нашем случае имена.zip):

import zipfile
zipfile.ZipFile('names.zip').extractall('.')

Мы можем запустить код и продолжить, набрав ALT + ENTER.

Теперь, если вы заглянете в свой каталог names, у вас будут файлы .txt с данными об именах в формате CSV. Эти файлы будут соответствовать годам данных в файле, с 1881 по 2015 год. Каждый из этих файлов соответствует аналогичному соглашению об именах. Например, файл 2015 года называется yob2015.txt, а файл 1927 года — yob1927.txt.

Чтобы посмотреть формат одного из этих файлов, давайте воспользуемся Python, чтобы открыть его и отобразить 5 верхних строк:

open('yob2015.txt','r').readlines()[:5]

Запустите код и продолжите, нажав ALT + ENTER.

Output
['Emma,F,20355\n', 'Olivia,F,19553\n', 'Sophia,F,17327\n', 'Ava,F,16286\n', 'Isabella,F,15504\n']

Данные форматируются следующим образом: сначала имя (как в Эмма или Оливия), затем пол (как в F для женского имени и M для мужского имени), а затем количество детей, родившихся в этом году с этим именем (в 2015 году было 20 355 детей с именем Эмма).

С помощью этой информации мы можем загрузить данные в pandas.

Загрузите данные CSV в панды

Чтобы загрузить данные значений, разделенных запятыми, в pandas, мы будем использовать функцию pd.read_csv(), передав имя текстового файла, а также имена столбцов, которые мы решили на. Мы назначим это переменной, в данном случае names2015, так как мы используем данные из файла 2015 года рождения.

names2015 = pd.read_csv('yob2015.txt', names = ['Name', 'Sex', 'Babies'])

Введите ALT + ENTER, чтобы запустить код и продолжить.

Чтобы убедиться, что это сработало, давайте отобразим верхнюю часть таблицы:

names2015.head()

Когда мы запустим код и продолжим с ALT + ENTER, мы увидим вывод, который выглядит следующим образом:

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

Объединить объекты pandas

Объединение объектов pandas позволит нам работать со всеми отдельными текстовыми файлами в каталоге names.

Чтобы объединить их, нам сначала нужно инициализировать список, назначив переменную незаполненному типу данных списка:

all_years = []

Как только мы это сделаем, мы будем использовать цикл for для перебора всех файлов по годам, которые варьируются от 1880 до 2015. Мы добавим +1 в конец 2015 года, чтобы 2015 год был включен в цикл.

all_years = []

for year in range(1880, 2015+1):

В цикле мы добавим в список каждое из значений текстового файла, используя средство форматирования строк для обработки разных имен каждого из этих файлов. Мы передадим эти значения в переменную year. Опять же, мы укажем столбцы для Name, Sex и количества Baby:

all_years = []

for year in range(1880, 2015+1):
    all_years.append(pd.read_csv('yob{}.txt'.format(year),
                                 names = ['Name', 'Sex', 'Babies']))

Кроме того, мы создадим столбец для каждого года, чтобы сохранить порядок. Это мы можем делать после каждой итерации, используя индекс -1, чтобы указывать на них по мере выполнения цикла.

all_years = []

for year in range(1880, 2015+1):
    all_years.append(pd.read_csv('yob{}.txt'.format(year),
                                 names = ['Name', 'Sex', 'Babies']))
    all_years[-1]['Year'] = year

Наконец, мы добавим его в объект pandas с конкатенацией, используя функцию pd.concat(). Мы будем использовать переменную all_names для хранения этой информации.

all_years = []

for year in range(1880, 2015+1):
    all_years.append(pd.read_csv('yob{}.txt'.format(year),
                                 names = ['Name', 'Sex', 'Babies']))
    all_years[-1]['Year'] = year

all_names = pd.concat(all_years)

Теперь мы можем запустить цикл с помощью ALT + ENTER, а затем проверить вывод, вызвав хвост (самые нижние строки) результирующей таблицы:

all_names.tail()

Теперь наш набор данных завершен и готов к дополнительной работе с ним в pandas.

Группировка данных

С помощью pandas вы можете группировать данные по столбцам с помощью функции .groupby(). Используя нашу переменную all_names для нашего полного набора данных, мы можем использовать groupby() для разделения данных на разные сегменты.

Давайте сгруппируем набор данных по полу и году. Мы можем настроить это так:

group_name = all_names.groupby(['Sex', 'Year'])

Мы можем запустить код и продолжить с ALT + ENTER.

На этом этапе, если мы просто вызовем переменную group_name, мы получим следующий вывод:

Output
<pandas.core.groupby.DataFrameGroupBy object at 0x1187b82e8>

Это показывает нам, что это объект DataFrameGroupBy. Этот объект содержит инструкции о том, как сгруппировать данные, но не дает инструкций о том, как отображать значения.

Для отображения значений нам нужно будет дать инструкции. Мы можем вычислить .size(), .mean() и .sum(), например, чтобы вернуть таблицу.

Начнем с .size():

group_name.size()

Когда мы запустим код и продолжим с ALT + ENTER, наш вывод будет выглядеть так:

Output
Sex Year F 1880 942 1881 938 1882 1028 1883 1054 1884 1172 ...

Эти данные выглядят хорошо, но они могли бы быть более читабельными. Мы можем сделать его более читабельным, добавив функцию .unstack:

group_name.size().unstack()

Теперь, когда мы запустим код и продолжим, набрав ALT + ENTER, вывод будет выглядеть так:

Эти данные говорят нам о том, сколько женских и мужских имен было в каждом году. В 1889 году, например, было 1479 женских имен и 1111 мужских имен. В 2015 году было 18 993 женских имени и 13 959 мужских имен. Это показывает, что с течением времени наблюдается большее разнообразие имен.

Если мы хотим получить общее количество рожденных детей, мы можем использовать функцию .sum(). Давайте применим это к меньшему набору данных, набору names2015 из одного файла yob2015.txt, который мы создали ранее:

names2015.groupby(['Sex']).sum()

Давайте наберем ALT + ENTER, чтобы запустить код и продолжить:

Это показывает нам общее количество младенцев мужского и женского пола, родившихся в 2015 году, хотя в наборе данных учитываются только дети, чье имя использовалось не менее 5 раз в этом году.

Функция pandas .groupby() позволяет нам сегментировать наши данные на значимые группы.

Сводная таблица

Сводные таблицы удобны для обобщения данных. Они могут автоматически сортировать, подсчитывать, суммировать или усреднять данные, хранящиеся в одной таблице. Затем они могут показать результаты этих действий в новой таблице этих сводных данных.

В pandas функция pivot_table() используется для создания сводных таблиц.

Чтобы построить сводную таблицу, мы сначала вызовем DataFrame, с которым хотим работать, затем данные, которые хотим показать, и то, как они сгруппированы.

В этом примере мы будем работать с данными all_names и покажем данные о младенцах, сгруппированные по имени в одном измерении и по году в другом:

pd.pivot_table(all_names, 'Babies', 'Name', 'Year')

Когда мы нажимаем ALT + ENTER, чтобы запустить код и продолжить, мы увидим следующий вывод:

Поскольку это показывает много пустых значений, мы можем захотеть сохранить Name и Year в виде столбцов, а не строк в одном случае и столбцов в другом. Мы можем сделать это, сгруппировав данные в квадратных скобках:

pd.pivot_table(all_names, 'Babies', ['Name', 'Year'])

Как только мы нажмем ALT + ENTER, чтобы запустить код и продолжить, в этой таблице теперь будут отображаться данные только за те годы, которые зарегистрированы для каждого имени:

Output
Name Year Aaban 2007 5.0 2009 6.0 2010 9.0 2011 11.0 2012 11.0 2013 14.0 2014 16.0 2015 15.0 Aabha 2011 7.0 2012 5.0 2014 9.0 2015 7.0 Aabid 2003 5.0 Aabriella 2008 5.0 2014 5.0 2015 5.0

Кроме того, мы можем сгруппировать данные, чтобы имя и пол были одним измерением, а год — другим, например:

pd.pivot_table(all_names, 'Babies', ['Name', 'Sex'], 'Year')

Когда мы запустим код и продолжим с помощью ALT + ENTER, мы увидим следующую таблицу:

Сводные таблицы позволяют нам создавать новые таблицы из существующих таблиц, что позволяет нам решить, как мы хотим сгруппировать эти данные.

Визуализируйте данные

Используя pandas с другими пакетами, такими как matplotlib, мы можем визуализировать данные в нашей записной книжке.

Мы будем визуализировать данные о популярности данного имени на протяжении многих лет. Для этого нам нужно установить и отсортировать индексы для обработки данных, которые позволят нам увидеть изменение популярности определенного имени.

Пакет pandas позволяет нам выполнять иерархическую или многоуровневую индексацию, что позволяет нам хранить и обрабатывать данные с произвольным количеством измерений.

Мы собираемся проиндексировать наши данные с информацией о поле, затем имени и годе. Мы также хотим отсортировать индекс:

all_names_index = all_names.set_index(['Sex','Name','Year']).sort_index()

Введите ALT + ENTER для запуска и перейдите к следующей строке, где блокнот отобразит новый индексированный DataFrame:

all_names_index

Запустите код и продолжите с ALT + ENTER, и вывод будет выглядеть следующим образом:

Далее мы напишем функцию, которая будет отображать популярность имени с течением времени. Мы вызовем функцию name_plot и передадим sex и name в качестве ее параметров, которые мы будем вызывать при запуске функции.

def name_plot(sex, name):

Теперь мы настроим переменную с именем data для хранения созданной нами таблицы. Мы также будем использовать pandas DataFrame loc, чтобы выбрать нашу строку по значению индекса. В нашем случае мы хотим, чтобы loc основывался на комбинации полей в MultiIndex, ссылаясь как на данные sex, так и на данные name. .

Запишем эту конструкцию в нашу функцию:

def name_plot(sex, name):
    data = all_names_index.loc[sex, name]

Наконец, нам нужно отобразить значения с помощью matplotlib.pyplot , который мы импортировали как pp. Затем мы сопоставим значения данных пола и имени с индексом, который для наших целей равен годам.

def name_plot(sex, name):
    data = all_names_index.loc[sex, name]
    
    pp.plot(data.index, data.values)

Введите ALT + ENTER, чтобы запустить и перейти в следующую ячейку. Теперь мы можем вызвать функцию с полом и именем по нашему выбору, например, F для женского имени с заданным именем Danica.

name_plot('F', 'Danica')

Когда вы сейчас наберете ALT + ENTER, вы получите следующий вывод:

Обратите внимание, что в зависимости от того, какую систему вы используете, у вас может появиться предупреждение о замене шрифта, но данные все равно будут отображаться правильно.

Глядя на визуализацию, мы можем видеть, что популярность женского имени Даника немного выросла примерно в 1990 году и достигла пика незадолго до 2010 года.

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

Давайте начнем с того, что немного увеличим наш график:

pp.figure(figsize = (18, 8))

Далее давайте создадим список со всеми именами, которые мы хотели бы отобразить:

pp.figure(figsize = (18, 8))

names = ['Sammy', 'Jesse', 'Drew', 'Jamie']

Теперь мы можем перебирать список с помощью цикла for и отображать данные для каждого имени. Во-первых, мы попробуем эти гендерно-нейтральные имена в качестве женских имен:

pp.figure(figsize = (18, 8))

names = ['Sammy', 'Jesse', 'Drew', 'Jamie']

for name in names:
    name_plot('F', name)

Чтобы упростить понимание этих данных, давайте добавим легенду:

pp.figure(figsize = (18, 8))

names = ['Sammy', 'Jesse', 'Drew', 'Jamie']

for name in names:
    name_plot('F', name)
    
pp.legend(names)

Мы наберем ALT + ENTER, чтобы запустить код и продолжить, а затем получим следующий вывод:

В то время как каждое из имен постепенно набирало популярность как женские имена, имя Джейми было чрезвычайно популярным как женское имя примерно в 1980-х годах.

Давайте нанесем те же имена, но на этот раз как мужские имена:

pp.figure(figsize = (18, 8))

names = ['Sammy', 'Jesse', 'Drew', 'Jamie']

for name in names:
    name_plot('M', name)
    
pp.legend(names)

Снова нажмите ALT + ENTER, чтобы запустить код и продолжить. График будет выглядеть так:

Эти данные показывают большую популярность имен, причем Джесси, как правило, является самым популярным выбором и особенно популярен в 1980-х и 1990-х годах.

Отсюда вы можете продолжать играть с данными об именах, создавать визуализации различных имен и их популярности, а также создавать другие сценарии для просмотра различных данных для визуализации.

Заключение

В этом руководстве вы познакомились со способами работы с большими наборами данных, от настройки данных до группировки данных с помощью groupby() и pivot_table(), индексирования данных с помощью MultiIndex и визуализация данных pandas с помощью пакета matplotlib.

Многие организации и учреждения предоставляют наборы данных, с которыми вы можете работать, чтобы продолжать изучать pandas и визуализацию данных. Например, правительство США предоставляет данные через data.gov.

Вы можете узнать больше о визуализации данных с помощью matplotlib, следуя нашим руководствам о том, как построить график частот слов с помощью matplotlib с Python 3.