<jupyter_start><jupyter_text>Введение в анализ данных, ИАД-1 НИУ ВШЭ, 2018-19 учебный год  Домашнее задание №1 Задание выполнил(а): <NAME>  Общая информация __Дата выдачи:__ 03.02.2019__Дедлайн:__ 23:59 12.02.2019  О задании В данном домашнем задании вы попрактикуетесь в работе с библиотеками numpy, pandas и matplotlib.  Оценивание и штрафыКаждая задача $p_i$ оценивается в 1 балл; Оценка за ДЗ = $\frac{10}{24}\sum_{i}p_i $За сдачу задания позже срока на итоговую оценку за задание накладывается штраф в размере 1 балл в день, но получить отрицательную оценку нельзя. __Внимание!__ Домашнее задание выполняется самостоятельно. «Похожие» решения считаются плагиатом и все задействованные студенты (в том числе те, у кого списали) не могут получить за него больше 0 баллов.  Формат сдачи Загрузка файлов с решениями происходит в системе [Anytask](https://anytask.org/).Формат названия файла: homework_01_Фамилия_Имя.ipynb  Часть 1. Numpy<jupyter_code>import numpy as np<jupyter_output><empty_output><jupyter_text>Во всех задачах необходимо написать код решения внутри функции и проверить его работу, вызвав функцию для данных из условия.При решении задач запрещается использовать циклы (`for`, `while`) и оператор `if`.Везде, где встречаются массивы или матрицы, подразумевается, что это `numpy.array`.   1 Напишите функцию, возвращающую округленную взвешенную сумму оценок по данным оценкам и весам. Можете посчитать свою оценку за курс :) В нашем случае вес экзамена равен 0.3, вес домашек - 0.42, вес контрольной - 0.14, вес самостоятельных - 0.14. Например, если за экзамен у вас 7, за домашки 10, за контрольную 8, а за самостоятельные 6, то вы получите отличную оценку 8!<jupyter_code>def result_mark(weights, marks):
    return (weights * marks).sum().round().astype(int)
weights = np.array([0.3, 0.42, 0.14, 0.14])
marks = np.array([7, 10, 8, 6])
result_mark(weights, marks)<jupyter_output><empty_output><jupyter_text>2 Напишите функцию, меняющую все каждое третье (начиная с 0) значение массива целых чисел на заданное число. Например, если на вход поступает массив `array([3, 5, 1, 0, -3, 22, 213436])` и число `-111`, то на выходе должен получиться массив `array([-111, 5, 1, -111, -3, 22, -111])`.<jupyter_code>def change_array(array, number):
    array[::3] = number
    return array
array = np.array([3, 5, 1, 0, -3, 22, 213436])
number = -111
change_array(array, number)<jupyter_output><empty_output><jupyter_text>3 Напишите функцию, выдающую индексы «близких» элементов заданных массивов, а именно тех пар элементов, чей модуль разницы не превосходит заданного значения. Например, если на вход поступают массив `array([1.5, 0.5, 2, -4.1, -3, 6, -1])`, массив `array([1.2, 0.5, 1, -4, 3, 0, -1.2])` и число `0.5`, то на выходе должен получиться массив `array([0, 1, 3, 6])` (_**важно: не `tuple`, а одномерный массив типа `numpy.ndarray` (то есть `.ndim` от него равно 1)!**_).<jupyter_code>def find_close(array1, array2, precision):
    return np.arange(array1.size)[abs(array1 - array2) <= precision]
array1 = np.array([1.5, 0.5, 2, -4.1, -3, 6, -1])
array2 = np.array([1.2, 0.5, 1, -4, 3, 0, -1.2])
precision = 0.5
find_close(array1, array2, precision)<jupyter_output><empty_output><jupyter_text>4 Напишите функцию, которая составляет блочную матрицу из четырех блоков, где каждый блок - это заданная матрица. Например, если на вход поступает матрица$$\begin{pmatrix}0 & 1 & 2\\3 & 4 & 5\\\end{pmatrix},$$то ответом будет матрица$$\begin{pmatrix}0 & 1 & 2 & 0 & 1 & 2\\3 & 4 & 5 & 3 & 4 & 5\\0 & 1 & 2 & 0 & 1 & 2\\3 & 4 & 5 & 3 & 4 & 5\\\end{pmatrix}$$<jupyter_code>def block_matrix(block):
    block = np.concatenate([block, block])
    return np.hstack([block, block])
block = np.array([[0, 1, 2], [3, 4, 5]])
block_matrix(block)<jupyter_output><empty_output><jupyter_text>5 Напишите функцию, вычисляющую произведение всех ненулевых диагональных элементов на диагонали данной квадратной матрицы. Например, если на вход поступает матрица$$\begin{pmatrix}0 & 1 & 2\\3 & 4 & 5\\6 & 7 & 8\\\end{pmatrix},$$то ответом будет 32.<jupyter_code>def diag_prod(matrix):
    diag = matrix.diagonal()
    return diag[diag != 0].prod()
matrix = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
diag_prod(matrix)<jupyter_output><empty_output><jupyter_text>6 Для улучшения качества работы некоторых алгоритмов машинного обучения может быть полезно использовать [нормализацию данных](https://vk.cc/8xmfQk), чтобы привести признаки в выборке к одному масштабу — а именно, из каждого столбца вычесть среднее его значений и поделить на их стандартное отклонение. Напишите функцию, нормализующую входящую матрицу (по столбцам). Например, если на вход подается матрица $$\begin{pmatrix}1 & 4 & 4200\\0 & 10 & 5000\\1 & 2 & 1000\\\end{pmatrix},$$то результатом с точностью до сотых будет матрица$$\begin{pmatrix}0.71 & -0.39 & 0.46\\-1.41 & 1.37 & 0.93\\0.71 & -0.98 & -1.39\\\end{pmatrix}$$Учтите, что в вашей матрице не должно получаться никаких nan. Подумайте, в каком случае они могут возникнуть и как обойти эту проблему._Подсказка. Казалось бы, при чем тут деление на ноль._<jupyter_code>def normalize(matrix):
    dividend = matrix - np.mean(matrix,axis=0)
    divider = np.std(matrix, axis = 0)
    return np.divide(dividend, divider, out=np.zeros(matrix.shape), where=divider!=0)
matrix = np.array([[1, 4, 4200], [0, 10, 5000], [1, 2, 1000]])
normalize(matrix)<jupyter_output><empty_output><jupyter_text>7 Напишите функцию, вычисляющую какую-нибудь первообразную данного полинома (в качестве константы возьмите ваше любимое число). Например, если на вход поступает массив коэффициентов `array([4, 6, 0, 1])`, что соответствует полиному $4x^3 + 6x^2 + 1$, на выходе получается массив коэффициентов `array([1, 2, 0, 1, -2])`, соответствующий полиному $x^4 + 2x^3 + x - 2$.<jupyter_code>def antiderivative(coefs):
    return np.polyint(coefs)
coefs = np.array([4, 6, 0, 1])
antiderivative(coefs)<jupyter_output><empty_output><jupyter_text>8 Напишите функцию, делающую данную [треугольную матрицу](https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B5%D1%83%D0%B3%D0%BE%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D0%B0) симметричной. Например, если на вход поступает матрица$$\begin{pmatrix}1 & 2 & 3 & 4\\0 & 5 & 6 & 7\\0 & 0 & 8 & 9\\0 & 0 & 0 & 10\\\end{pmatrix},$$то на выходе должна быть матрица$$\begin{pmatrix}1 & 2 & 3 & 4\\2 & 5 & 6 & 7\\3 & 6 & 8 & 9\\4 & 7 & 9 & 10\\\end{pmatrix}.$$<jupyter_code>def make_symmetric(matrix):
    sub = matrix.transpose()
    return np.tril(sub, -1) + matrix
matrix = np.array([[1, 2, 3, 4], [0, 5, 6, 7], [0, 0, 8, 9], [0, 0, 0, 10]])
make_symmetric(matrix)<jupyter_output><empty_output><jupyter_text>9 Напишите функцию, создающую прямоугольную матрицу из m одинаковых строк, заполненных последовательными натуральными числами от a до b включительно в возрастающем порядке. Например, если m = 5, a = 3, b = 10, то на выходе будет матрица$$\begin{pmatrix}3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\\end{pmatrix}$$<jupyter_code>def construct_matrix(m, a, b):
    sub = np.zeros((m, b - a + 1), np.int32)
    return np.arange(a, b + 1) + sub
m = 5
a = 3
b = 10
construct_matrix(m, a, b)<jupyter_output><empty_output><jupyter_text>10 Напишите функцию, вычисляющую [косинусную близость](https://en.wikipedia.org/wiki/Cosine_similarity) двух векторов. Например, если на вход поступают вектора `array([-2, 1, 0, -5, 4, 3, -3])` и `array([0, 2, -2, 10, 6, 0, 0])`, ответом будет -0.25.<jupyter_code>def cosine_similarity(vec1, vec2):
    return np.dot(vec1, vec2)/(np.linalg.norm(vec2)*np.linalg.norm(vec1))
vec1 = np.array([-2, 1, 0, -5, 4, 3, -3])
vec2 = np.array([0, 2, -2, 10, 6, 0, 0])
cosine_similarity(vec1, vec2)<jupyter_output><empty_output><jupyter_text>Часть 2. Pandas и Matplotlib<jupyter_code>import matplotlib.pyplot as plt
import pandas as pd

%matplotlib inline<jupyter_output><empty_output><jupyter_text>В этой части домашнего задания вы поработаете с данными о пассажирах с затонувшего «Титаника». Описание данных:https://www.kaggle.com/c/titanic/dataКаждый построенный график необходимо красиво оформить - для этого требуется как минимум указать его название, а также отметить, что изображено по каждой из осей.*Функции, которые могут пригодиться при оформлении графиков: `.show()`, `.title()`, `.xlabel()`, `.ylabel()`*  11 Откройте в ноутбуке файл с данными ("train.csv"). Какой размер имеет таблица? Выведите первые 5 и последние 5 строк.<jupyter_code>data = pd.read_csv('data.csv', delimiter=',')
data.shape<jupyter_output><empty_output><jupyter_text>891 записей и 12 признаков<jupyter_code>pd.concat([data.head(5), data.tail(5)])<jupyter_output><empty_output><jupyter_text>12 Для каждого из признаков укажите его тип (вещественный, категориальный, порядковый, другое). Придумайте три задачи, которые можно было бы решать для данного датасета — задачу регрессии, задачу классификации и задачу кластеризации. - PassengerId - другое- Survived - Бинарный- Pclass - Порядковый- Name - другое- Sex - Бинарный- Age - вещественный- SibSp - вещественный- Parch - вещественный- Ticket - другое- Fare - вещественный- Cabin - категориальный (возможна корреляция между номером кабины и статусом выжившего)- Embarked - категориальныйЗадача регрессии - определение стоимости тарифа (Fare)Задача классификации - определение, выжил пассажир или нет по входным параметрамЗадача кластеризации - группировка пассажиров по возрастным категориям в зависимости от статуса выжившего, тарифа и др. параметров  13 Какова доля выживших после крушения пассажиров? Какова доля мужчин и женщин среди выживших?<jupyter_code>data["Survived"].mean()
survived = data[data["Survived"] == 1]
sex_filter = survived["Sex"] == "male"
survived[sex_filter].shape[0] / survived.shape[0], survived[~sex_filter].shape[0] / survived.shape[0]<jupyter_output><empty_output><jupyter_text>14 Сколько пассажиров ехало в каждом классе? Кого было больше в самом многолюдном классе — мужчин или женщин?<jupyter_code>data_pass_per_class = data.groupby("Pclass")["Pclass"].describe()["count"]
data_pass_per_class
data[data["Pclass"] == data_pass_per_class[data_pass_per_class == data_pass_per_class.max()].index[0]]["Sex"].max()<jupyter_output><empty_output><jupyter_text>15 Выведите минимальную, среднюю и максимальную сумму, которую заплатили пассажиры за проезд. Проделайте то же самое только для тех пассажиров, которые сели на корабль в Саутгемптоне. Выведите гистограммы, показывающие распределения стоимостей билетов в зависимости от места посадки.<jupyter_code>data["Fare"].describe()[["min", "mean", "max"]]
data[data["Embarked"] == "S"]["Fare"].describe()[["min", "mean", "max"]]
bins = np.linspace(0, data["Fare"].max(), 50)
alpha=0.6
plt.figure(figsize=(20,10))
plt.grid(True)
plt.title('Распределения стоимостей билетов в зависимости от направления')
plt.hist(data[data["Embarked"] == "C"]["Fare"], bins, alpha=alpha)
plt.hist(data[data["Embarked"] == "Q"]["Fare"], bins, alpha=alpha)
plt.hist(data[data["Embarked"] == "S"]["Fare"], bins, alpha=alpha)
plt.xlabel('Стоимость')
plt.ylabel('Количество')
plt.legend(['Cherbourg', 'Queenstown', 'Southampton'])
plt.show()<jupyter_output><empty_output><jupyter_text>16 Все ли признаки несут в себе полезную информацию? Почему? Избавьтесь от ненужных столбцов. Номер билета не несут полезную информацию. Pandas сам нумерует записи, идентификатор в данном случае так же не нужен<jupyter_code>data = data.drop(columns=['Ticket', 'PassengerId'])
data.head()<jupyter_output><empty_output><jupyter_text>17 Есть ли в данных пропуски? Если да, то в каких столбцах? Сколько пропусков в каждом из них?<jupyter_code>data.isnull().sum(axis=0)<jupyter_output><empty_output><jupyter_text>18 Подумайте, как стоит заполнить пропуски в каждом столбце в зависимости от его типа, и сделайте это. Проверьте, что пропусков нигде не осталось.<jupyter_code>data["Age"].fillna(data["Age"].mean(), inplace=True)
data["Cabin"].fillna('Unknown', inplace=True)
data["Embarked"].fillna('S', inplace=True)
data.isnull().sum(axis=0)<jupyter_output><empty_output><jupyter_text>19 Посчитайте, насколько сильно коррелируют друг с другом цена за билет и возраст пассажиров. Также проверьте наличие этой зависимости визуально (в этом вам поможет построение [диаграммы рассеяния](https://ru.wikipedia.org/wiki/%D0%94%D0%B8%D0%B0%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0_%D1%80%D0%B0%D1%81%D1%81%D0%B5%D1%8F%D0%BD%D0%B8%D1%8F)).<jupyter_code>data["Age"].corr(data["Fare"])
plt.figure(figsize=(10,6))
plt.grid(True)
plt.title('Зависимость цены билета от возраста пассажира')
plt.xlabel('Возраст')
plt.ylabel('Цена')
plt.scatter(data["Age"], data["Fare"])
plt.show()<jupyter_output><empty_output><jupyter_text>20 Правда ли, что чаще выживали пассажиры с более дорогими билетами? А есть ли зависимость выживаемости от класса?<jupyter_code>data["Survived"].corr(data["Fare"])
data[data["Survived"] == 1]["Fare"].mean()
data[data["Survived"] == 0]["Fare"].mean()<jupyter_output><empty_output><jupyter_text>Чаще выживали пассажиры с дорогими билетами<jupyter_code>data["Survived"].corr(data["Pclass"])
data.groupby("Pclass")["Survived"].mean()
data[data["Survived"] == 1].groupby("Pclass").count()
data[data["Survived"] == 0].groupby("Pclass").count()<jupyter_output><empty_output><jupyter_text>Зависимость выживаемости от класса так же присутствует. Больше людей, в процентном и количественном отношении, выжило в 1 классе  21 Создание новых признаков (feature engineering) является одним из основных средств улучшения качества работы алгоритмов машинного обучения на этапе обработки данных. Добавьте в таблицу столбец, который будет показывать, сколько родных плыло вместе с пассажиром на корабле, включая его самого. Затем придумайте свой признак, который может быть полезен для алгоритма (несет в себе какую-то информацию), и добавьте его в таблицу.<jupyter_code>data['Relatives'] = 1 + data['SibSp'] +  data['Parch']
# Стоимость километра пути. Дистанция из Википедии
data.loc[data["Embarked"] == "S", "PricePerKm"] = data["Fare"] / 5867 
data.loc[data["Embarked"] == "C", "PricePerKm"] = data["Fare"] / 5720 
data.loc[data["Embarked"] == "Q", "PricePerKm"] = data["Fare"] / 5147 
data.head()<jupyter_output><empty_output><jupyter_text>22 Придумайте какое-нибудь интересное задание на анализ предлагаемых данных и решите его. Например, какая фамилия была самой популярной на корабле?<jupyter_code>data["Name"].str.split(",").str.get(0).describe()["top"]<jupyter_output><empty_output><jupyter_text>23 Постройте гистограммы распределения вещественных признаков. Есть ли в них разница? Чем это может быть плохо с точки зрения машинного обучения? Отнормируйте вещественные признаки и посмотрите, как изменилась ситуация.<jupyter_code>def custom_hist(data, title,  xlabel, ylabel='Количество', bins=None):
    figsize = (20,6)
    plt.figure(figsize=figsize)
    plt.grid(True)
    plt.title(title)
    plt.hist(data, data.max().astype(int) if bins is None else bins)
    plt.xlabel(xlabel)
    plt.ylabel(ylabel)
    plt.show()
custom_hist(data["Age"], 'Распределения пассажиров по возрасту', 'Возраст')
custom_hist(data["SibSp"], 'Распределения пассажиров по количеству братьев/сестер или супругов', 'Число братьев/сестер или супругов')
custom_hist(data["Parch"], 'Распределения пассажиров по количеству родителей или детей', 'Число родителей или детей')
custom_hist(data["Fare"], 'Распределения пассажиров по стоимости билета', 'Стоимость билета', bins=20)
custom_hist(data["Relatives"], 'Распределения пассажиров по числу родственников', 'Число родственников')
custom_hist(data["PricePerKm"], 'Распределения пассажиров стоимости км пути', 'Стоимость км пути', bins=20)
data["Age_norm"] = (data["Age"]-data["Age"].mean())/data["Age"].std()
data["SibSp_norm"] = (data["SibSp"]-data["SibSp"].mean())/data["SibSp"].std()
data["Parch_norm"] = (data["Parch"]-data["Parch"].mean())/data["Parch"].std()
data["Fare_norm"] = (data["Fare"]-data["Fare"].mean())/data["Fare"].std()
data["Relatives_norm"] = (data["Relatives"]-data["Relatives"].mean())/data["Relatives"].std()
data["PricePerKm_norm"] = (data["PricePerKm"]-data["PricePerKm"].mean())/data["PricePerKm"].std()
data.head()
custom_hist(data["Age_norm"], 'Распределения пассажиров по возрасту', 'Возраст', bins=80)
custom_hist(data["SibSp_norm"], 'Распределения пассажиров по количеству братьев/сестер или супругов', 'Число братьев/сестер или супругов', bins=7)
custom_hist(data["Parch_norm"], 'Распределения пассажиров по количеству родителей или детей', 'Число родителей или детей', bins=5)
custom_hist(data["Fare_norm"], 'Распределения пассажиров по стоимости билета', 'Стоимость билета', bins=20)
custom_hist(data["Relatives_norm"], 'Распределения пассажиров по числу родственников', 'Число родственников', bins=12)
custom_hist(data["PricePerKm_norm"], 'Распределения пассажиров стоимости км пути', 'Стоимость км пути', bins=20)<jupyter_output><empty_output><jupyter_text>24 Есть ли в данных категориальные признаки, которые принимают значения строк, а не чисел? Если да, то для многих алгоритмов машинного обучения это может стать серьезным препятствием, поэтому закодируйте категориальные признаки так, чтобы к данным можно было применить любые алгоритмы машинного обучения.<jupyter_code>data.loc[data["Sex"] == "male", "Sex"] = 0
data.loc[data["Sex"] == "female", "Sex"] = 1

data.loc[data["Embarked"] == "S", "Embarked"] = 0
data.loc[data["Embarked"] == "C", "Embarked"] = 1
data.loc[data["Embarked"] == "Q", "Embarked"] = 2

data['Cabin']=pd.factorize(data['Cabin'])[0]
data.head()
data.info()<jupyter_output><class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 18 columns):
Survived           891 non-null int64
Pclass             891 non-null int64
Name               891 non-null object
Sex                891 non-null int64
Age                891 non-null float64
SibSp              891 non-null int64
Parch              891 non-null int64
Fare               891 non-null float64
Cabin              891 non-null int64
Embarked           891 non-null int64
Relatives          891 non-null int64
PricePerKm         891 non-null float64
Age_norm           891 non-null float64
SibSp_norm         891 non-null float64
Parch_norm         891 non-null float64
Fare_norm          891 non-null float64
Relatives_norm     891 non-null float64
PricePerKm_norm    891 non-null float64
dtypes: float64(9), int64(8), object(1)
memory usage: 125.4+ KB
{'fraction_non_alphanumeric': 0.1387311374330683, 'fraction_numerical': 0.04170047055005679, 'mean_word_length': 5.641522988505747, 'pattern_counts': {'":': 0, '<': 111, '<?xml version=': 0, '>': 110, 'https://': 6, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '27', 'dir': 'jupyter-structured-clean-dedup', 'id': '372236', 'license': 'Apache-2.0', 'n_tokens_mistral': 8106, 'n_tokens_neox': 8456, 'n_words': 1803, 'path': 'introduction_to_machine_learning/hw_01.ipynb', 'repo_name': 'AsciiShell/hse_ida', 'size': '18502'}