<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 <center>
<img src="../img/ods_stickers.jpg">
Открытый курс по машинному обучению
</center>
Автор материала
Step1:  Основными структурами данных в Pandas являются классы Series и DataFrame. Первый из них представляет собой одномерный индексированный массив данных некоторого фиксированного типа. Второй - это двухмерная структура данных, представляющая собой таблицу, каждый столбец которой содержит данные одного типа. Можно представлять её как словарь объектов типа Series. Структура DataFrame отлично подходит для представления реальных данных
Step2:  Индексирование возможно в виде s.Name или s['Name'].
Step3:  Series поддерживает пропуски в данных.
Step4:  Объекты Series похожи на ndarray и могут быть переданы в качестве аргументов большинству функций из Numpy.
Step5:  DataFrame
Создание и изменение
Перейдём к рассмотрению объектов типа DataFrame. Такой объект можно создать из массива numpy, указав названия строк и столбцов.
Step6:  Альтернативным способом является создание DataFrame из словаря numpy массивов или списков.
Step7:  Обращение к элементам (или целым кускам фрейма)
Step8:  Изменение элементов и добавление новых
Step9:  Обработка пропущенных значений
Step10:  Булева маска для пропущенных значений (True - там, где был пропуск, иначе - False)
Step11:  Можно удалить все строки, где есть хотя бы один пропуск.
Step12:  Пропуски можно заменить каким-то значением.
Step13:  Пример первичного анализа данных с Pandas
Чтение из файла и первичный анализ
Однако на практике DataFrame, с которым нам предстоит работать, необходимо считать из некоторого файла. Рассмотрим работу с DataFrame на примере следующего набора данных. Для каждрого опрошенного имеется следующая информация
Step14:  Посмотрим на размер данных и названия признаков.
Step15:  При работе с большими объёмами данных бывает удобно посмотреть только на небольшие части фрейма (например, начало).
Step16:  Метод describe показывает основные статистические характеристики данных по каждому признаку
Step17:  DataFrame можно отсортировать по значению какого-нибудь из признаков. В нашем случае, например, по размеру заработной платы.
Step18:  Индексация и извлечение данных
DataFrame можно индексировать по-разному. В связи с этим рассмотрим различные способы индексации и извлечения нужных нам данных из DataFrame на примере простых вопросов.
Для извлечения отдельного столбца можно использовать конструкцию вида DataFrame['Name']. Воспользуемся этим для ответа на вопрос
Step19:  Очень удобной является логическая индексация DataFrame по одному столбцу. Выглядит она следующим образом
Step20:  Какова максимальная заработная плата среди мужчин, имеющих членство в профсоюзе, и с опытом работы до 10 лет?
Step21:  Применение функции к каждому столбцу
Step22:  Группирование данных в зависимости от значения признака looks и подсчет среднего значения по каждому столбцу в каждой группе.
Step23:  Обращение к конкретной группе
Step24:  Визуализация в Pandas
Метод scatter_matrix позволяет визуализировать попарные зависимости между признаками (а также распределение каждого признака на диагонали). Проделаем это для небинарных признаков.
Step25:  Для каждого признака можно построить отдельную гистограмму
Step26:  Или сразу для всех
Step27:  Полезным также является график типа box plot ("ящик с усами"). Он позволяет компактно визуализировать основные характеристики (медиану, нижний и верхний квартили, минимальное и максимальное значение, выбросы) распределения признаков.
Step28:  Можно сделать это, сгруппировав данные по какому-либо другому признаку
<ASSISTANT_TASK:>
Python Code:
# Python 2 and 3 compatibility
# pip install future
from __future__ import (absolute_import, division,
                        print_function, unicode_literals)
# отключим предупреждения Anaconda
import warnings
warnings.simplefilter('ignore')
import pandas as pd
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
Explanation: <center>
<img src="../img/ods_stickers.jpg">
Открытый курс по машинному обучению
</center>
Автор материала: программист-исследователь Mail.ru Group, старший преподаватель Факультета Компьютерных Наук ВШЭ Юрий Кашницкий
<center>Тема 1. Первичный анализ данных с Pandas</center>
<center>Часть 1. Обзор библиотеки Pandas</center>
Pandas - это библиотека Python, предоставляющая широкие возможности для анализа данных. С ее помощью очень удобно загружать, обрабатывать и анализировать табличные данные с помощью SQL-подобных запросов. В связке с библиотеками Matplotlib и Seaborn появляется возможность удобного визуального анализа табличных данных.
End of explanation
salaries = pd.Series([400, 300, 200, 250], 
              index = ['Andrew', 'Bob', 
                       'Charles', 'Ann']) 
print(salaries)                                                                 
salaries[salaries > 250]
Explanation: Основными структурами данных в Pandas являются классы Series и DataFrame. Первый из них представляет собой одномерный индексированный массив данных некоторого фиксированного типа. Второй - это двухмерная структура данных, представляющая собой таблицу, каждый столбец которой содержит данные одного типа. Можно представлять её как словарь объектов типа Series. Структура DataFrame отлично подходит для представления реальных данных: строки соответствуют признаковым описаниям отдельных объектов, а столбцы соответствуют признакам.
Для начала рассмотрим простые примеры создания таких объектов и возможных операций над ними.
Series
 Создание объекта Series из 5 элементов, индексированных буквами:
End of explanation
print(salaries.Andrew == salaries['Andrew']) 
salaries['Carl'] = np.nan
salaries.fillna(salaries.median(), inplace=True)
salaries
Explanation: Индексирование возможно в виде s.Name или s['Name'].
End of explanation
salaries.c = np.nan # Series can contain missing values
print(salaries)
Explanation: Series поддерживает пропуски в данных.
End of explanation
print('Second element of salaries is', salaries[1], '\n')
# Smart indexing
print(salaries[:3], '\n')
print('There are', len(salaries[salaries > 0]), 'positive elements in salaries\n')
# Series obects can be the arguments for Numpy functions
print(np.exp(salaries))
Explanation: Объекты Series похожи на ndarray и могут быть переданы в качестве аргументов большинству функций из Numpy.
End of explanation
df1 = pd.DataFrame(np.random.randn(5, 3), 
                   index=['o1', 'o2', 'o3', 'o4', 'o5'], 
                   columns=['f1', 'f2', 'f3'])
df1
Explanation: DataFrame
Создание и изменение
Перейдём к рассмотрению объектов типа DataFrame. Такой объект можно создать из массива numpy, указав названия строк и столбцов.
End of explanation
df2 = pd.DataFrame({'A': np.random.random(5), 
                    'B': ['a', 'b', 'c', 'd', 'e'], 
                    'C': np.arange(5) > 2})
df2
Explanation: Альтернативным способом является создание DataFrame из словаря numpy массивов или списков.
End of explanation
print('The element in position 3, B is', df2.at[3, 'B'], '\n')
print(df2.loc[[1, 4], ['A', 'B']])
Explanation: Обращение к элементам (или целым кускам фрейма):
End of explanation
df2.at[2, 'B'] = 'f'
df2
df2.loc[5] = [3.1415, 'c', False]
df2
df1.columns = ['A', 'B', 'C']
df3 = df1.append(df2)
df3
Explanation: Изменение элементов и добавление новых:
End of explanation
df1.at['o2', 'A'] = np.nan
df1.at['o4', 'C'] = np.nan
df1
Explanation: Обработка пропущенных значений
End of explanation
pd.isnull(df1)
Explanation: Булева маска для пропущенных значений (True - там, где был пропуск, иначе - False):
End of explanation
df1.dropna(how='any')
Explanation: Можно удалить все строки, где есть хотя бы один пропуск.
End of explanation
df1.fillna(0)
Explanation: Пропуски можно заменить каким-то значением.
End of explanation
df = pd.read_csv('../data/beauty.csv', sep = ';')
Explanation: Пример первичного анализа данных с Pandas
Чтение из файла и первичный анализ
Однако на практике DataFrame, с которым нам предстоит работать, необходимо считать из некоторого файла. Рассмотрим работу с DataFrame на примере следующего набора данных. Для каждрого опрошенного имеется следующая информация: заработная плата за час работы, опыт работы, образование, внешняя привлекательность (в баллах от 1 до 5), бинарные признаки: пол, семейное положение, состояние здоровья (хорошее/плохое), членство в профсоюзе, цвет кожи (белый/чёрный), занятость в сфере обслуживания (да/нет).
End of explanation
print(df.shape)
print(df.columns.values)
df.head(10)
Explanation: Посмотрим на размер данных и названия признаков.
End of explanation
df.head(4)
Explanation: При работе с большими объёмами данных бывает удобно посмотреть только на небольшие части фрейма (например, начало).
End of explanation
df.describe()
Explanation: Метод describe показывает основные статистические характеристики данных по каждому признаку: число непропущенных значений, среднее, стандартное отклонение, диапазон, медиану, 0.25 и 0.75 квартили.
End of explanation
df.sort_values(by='wage', ascending = False).head()
df.sort_values(by=['female', 'wage'],
        ascending=[True, False]).head()
Explanation: DataFrame можно отсортировать по значению какого-нибудь из признаков. В нашем случае, например, по размеру заработной платы.
End of explanation
df['goodhlth'].mean()
Explanation: Индексация и извлечение данных
DataFrame можно индексировать по-разному. В связи с этим рассмотрим различные способы индексации и извлечения нужных нам данных из DataFrame на примере простых вопросов.
Для извлечения отдельного столбца можно использовать конструкцию вида DataFrame['Name']. Воспользуемся этим для ответа на вопрос: какова доля людей с хорошим здоровьем среди опрошенных?
End of explanation
df[df['female'] == 1].head()
df[(df['goodhlth'] == 1) & 
   (df['female'] == 1)].head()
df[(df['female'] == 0)]['wage'].mean() - \
df[(df['female'] == 1)]['wage'].mean()
Explanation: Очень удобной является логическая индексация DataFrame по одному столбцу. Выглядит она следующим образом: df[P(df['Name'])], где P - это некоторое логическое условие, проверяемое для каждого элемента столбца Name. Итогом такой индексации является DataFrame, состоящий только из строк, удовлетворяющих условию P по столбцу Name. Воспользуемся этим для ответа на вопрос: какова средняя заработная плата среди женщин?
End of explanation
df[(df['female'] == 0) & (df['union'] == 1)  
   & (df['exper'] < 10)]['wage'].max()
Explanation: Какова максимальная заработная плата среди мужчин, имеющих членство в профсоюзе, и с опытом работы до 10 лет?
End of explanation
df.apply(np.mean) 
Explanation: Применение функции к каждому столбцу:
End of explanation
df['looks'].describe()
g = df.groupby('looks') 
for (i, sub_df) in g:
    print(sub_df['wage'].mean(), sub_df['looks'].mean())
Explanation: Группирование данных в зависимости от значения признака looks и подсчет среднего значения по каждому столбцу в каждой группе.
End of explanation
d1 = g.get_group(1)
d1
Explanation: Обращение к конкретной группе:
End of explanation
pd.scatter_matrix(df[['wage', 'exper', 'educ', 'looks']], 
                  figsize=(15, 15), diagonal='kde')
plt.show()
Explanation: Визуализация в Pandas
Метод scatter_matrix позволяет визуализировать попарные зависимости между признаками (а также распределение каждого признака на диагонали). Проделаем это для небинарных признаков.
End of explanation
df['looks'].hist()
Explanation: Для каждого признака можно построить отдельную гистограмму:
End of explanation
df.hist(color = 'k', bins = 30, figsize=(15,10))
plt.show()
Explanation: Или сразу для всех:
End of explanation
df.boxplot(column='exper', by='looks')
plt.show()
Explanation: Полезным также является график типа box plot ("ящик с усами"). Он позволяет компактно визуализировать основные характеристики (медиану, нижний и верхний квартили, минимальное и максимальное значение, выбросы) распределения признаков.
End of explanation
df.boxplot(column='exper',  by=['female', 'black'], 
           figsize=(10,10))
plt.show()
Explanation: Можно сделать это, сгруппировав данные по какому-либо другому признаку:
End of explanation
<END_TASK>