Мир, в котором R и Python живут вместе
За последние годы я познакомился с Python и очень ценю широту процессов обработки данных, которые я могу с ним делать. Я считаю, что Python действительно прост в использовании, и благодаря множеству доступных сегодня библиотек я могу делать практически все, от веб-скрейпинга до разработки моделей глубокого обучения. Я начал с Python, так как все, кого я знал, работали с ним, и они сказали, что это правильный путь.
Однако недавно я начал работать с R, поскольку один из моих проектов требует использования ggplot и leaflet для разработки интерактивных визуализаций. Мой подход был прост - скорее практический, чем теоретический. Итак, я начал проходить курс по R, который мне очень понравился, чтобы понять, что такое R, а также начал возиться с уже существующим кодом этого проекта. Я люблю это! Мы так много можем сделать с R, и он отлично подходит для статистики, потому что он прост и имеет множество встроенных функций.
Итак, я начал думать, что, если бы я мог использовать как Python, так и R для создания работоспособных решений. В этой статье я сначала расскажу о R и Python и о том, как выглядит эта тенденция в наши дни, а затем я использовал два языка вместе, чтобы предсказать, придут ли люди на их встречу или нет, с точностью до 88%. После работы над собственным кодом я также обратился к нескольким онлайн-ядрам Kaggle и нашел несколько действительно полезных идей.
Репозиторий доступен ниже:
Если вы хотите пройти курс R, вот тот, который я беру прямо сейчас. Воспользуйтесь ссылкой ниже, чтобы получить специальную скидку:
Когда я начал Python, я начал изучать следующий курс по Python (Udemy обычно также имеет скидки на этот курс):
R против Python
По-прежнему ведутся многовековые дебаты о том, что кто-то может предпочесть R, а другие - Python, и это полностью ваш собственный выбор. Однако, поскольку сейчас я работаю с обоими языками, я могу лучше сказать, что оба они хороши.
R добавляет в таблицу встроенные статистические функции, и нет ничего лучше удивительной ggplot библиотеки для рисования графиков. У Python есть хорошие библиотеки машинного и глубокого обучения, которые намного проще использовать.

Если посмотреть на количество поисковых запросов, отслеживаемых Google Trends за последние 12 месяцев, можно увидеть, что и R, и Python справедливо ищут во всем мире. Хотя тенденция показывает, что поиск языка R увеличивается, согласно индексу TIOBE, Python намного опережает R, как это видно на изображении ниже:

Цифры показывают, что, хотя Python сегодня более популярен, результаты поиска Google показывают, что многие результаты поиска часто более смещены в сторону R, чем Python. Таким образом, хорошее сочетание навыков владения обоими языками не только подготовит вас к сегодняшним вызовам, но и сделает вас будущим.
Теперь давайте посмотрим, как мы можем работать с обоими языками!
Исследовательский анализ данных с использованием R
Импортировать пакеты
Вы можете загружать пакеты в R, используя install.packages(), а затем импортировать их в файл записной книжки .Rmd, используя library(). Я использую ggplot2 для работы с графиками, gridExtra для работы с сетками графиков и lubridate для работы с датами.
Импортировать набор данных
Я взял из Kaggle набор данных о различных приемах у врача и о том, приходили пациенты или нет. У него 13 функций и 1 целевая переменная. Функция read.csv() позволяет импортировать набор данных.


Исследование набора данных
Давайте сначала посмотрим на количество строк и столбцов и названия этих столбцов. Функция nrow() возвращает количество строк, ncol() возвращает количество столбцов, а names() возвращает список имен столбцов. Метод paste() объединяет различные строки в одну строку.
Набор данных состоит из 110527 строк и 14 столбцов. Целевая переменная No.show и находится в форме отрицания, поэтому я хотел бы изменить ее в более удобочитаемой форме. Мне также придется перевернуть значения столбцов с No на TRUE и с Yes на FALSE, когда я изменю No.show на Showed_up.
У нас есть 13 функций, давайте рассмотрим их подробнее:
- «PatientId»: это уникальный идентификатор для каждого пациента, но он не может быть полезен для каких-либо прогнозов.
- «AppointmentId: это уникальный идентификатор для каждой встречи.
- «Пол»: является ли человек женщиной, обозначенной буквой F, или мужчиной, обозначенной буквой М.
- «ScheduleDay»: день, на который была назначена встреча.
- «AppointmentDay»: день встречи.
- «Возраст»: Возраст человека.
- «Район»: район, к которому принадлежит человек.
- Стипендия: имел ли человек стипендию (определяется Википедией).
- «Гипертония»: есть ли у человека гипертония.
- «Diabeletes»: есть ли у человека диабет.
- «Алкоголизм»: является ли человек алкоголиком.
- «Handcap»: наличие у человека физических недостатков.
- «SMS_received»: получил ли человек текстовое сообщение о встрече.
Целевая переменная:
- «Showed_up»: показывает, явился ли человек на встречу.
Затем давайте посмотрим сводку набора данных.

Более пристальный взгляд на набор данных показывает, что такие функции, как Alcoholism, Handcap и т. Д., Которые считаются непрерывными значениями, скорее являются категориальными переменными. Даты не считаются датами, и минимум Age = -1, что является данными об ошибках, поэтому я отброшу эти строки.
Визуализации
Целевой класс
Давайте посмотрим, сколько человек пришло на встречу и сколько не пришло. Я использую ggplot, который принимает аргумент как набор данных, а затем значение x внутри aes(). geom_bar() определяет, что нам нужен столбчатый график с цветом заливки каждого столбца как белый, линия, определенная как color оранжевый, и width каждого столбца как 0.4. Заголовок определяется с помощью ggtitle(), а с помощью labs() я определил метки осей x и y.

Людей, пришедших на прием, больше, чем тех, кто не пришел. Нам обязательно нужно поработать, чтобы модель не была предвзятой.
Гендерное распределение
Посмотрим, существует ли в наборе данных какое-либо распределение между мужчинами и женщинами. Я создам гистограмму и переименую значения столбцов как Female для F и Male для M. Как и на гистограмме выше, я использовал все функции и переименовал метку x, используя scale_x_discrete.

Женщин, записавшихся на прием, больше, чем мужчин.
Распределение двоичных классов
Поскольку существует множество двоичных классов, определенных с помощью TRUE и FALSE, я построю их все на основе цвета файла целевого класса. Функция aes() принимает аргумент fill, который в основном позволяет нам строить данные на основе другого класса, в нашем случае целевой переменной. Функция grid.arrange() помогает нам построить серию графиков в виде строк и столбцов. Аргумент ncol = 2 утверждает, что мне нужны 2 столбца и строки в зависимости от количества графиков, которые я хочу.

Все графики показывают, что распределение между целевыми классами практически постоянно для любого логического значения. Данные распределены достаточно равномерно.
Разница между назначением и днем расписания
Я заметил, что разница между временем, когда кто-то назначает встречу, и датой фактической встречи также может быть полезной. Таким образом, я решил создать новый столбец Date.diff в наборе данных, который по сути представляет собой разницу между двумя днями. Поскольку разница заключается в количестве дней, я преобразовал его в числовые значения после исключения из списка с помощью as.numeric(unlist(date.diff)).

По сюжету видно, что очень много встреч на тот день, который был назначен. Давайте удалим этот огромный всплеск и посмотрим, сможем ли мы найти что-нибудь кроме него. Итак, на графике выше я добавлю xlim(1,200), чтобы начать с 1.

Обратите внимание, что по мере увеличения разницы между днями количество встреч уменьшается. Назначений с разницей в 50 дней и более действительно меньше. Похоже, что корреляции нет, поскольку счетчики до 50 дней растут и падают без какой-либо закономерности.
Настроено время встречи
Время часа или месяца встречи также может повлиять на то, явится ли кто-то на встречу или нет. Итак, давайте создадим эти данные и посмотрим, есть ли такой эффект. Хотя часовые данные были бы полезны, я заметил, что часовые данные для каждой встречи одинаковы, поэтому мы не можем их использовать. Давайте просто поработаем с данными за месяц.
Используя функцию month, я смог получить месяц из AppointmentDay. Затем я использовал его для построения гистограммы.

В апреле очень мало приемов, а в мае - максимальное.
prop.table() приводит к симметричному распределению на основе маржи. Как видно из данных, месяц практически не влияет на показы, так как соотношение ложных и истинных значений практически одинаково. Таким образом, мы можем отбросить сам столбец.
Мы можем получить подмножество набора данных с помощью метода subset(), а затем, определив аргумент select как -Month, мы выберем все, кроме месяца.
Окрестности
Если смотреть шире, можно заметить, что есть много разных районов. Давайте рассмотрим их с помощью гистограмм.

Данные по районам весьма разнообразны. Jabour имеет очень большое количество встреч, в то время как в некоторых районах назначено менее 10 встреч. Мы должны сохранить данные, но мы создадим фиктивные переменные для размещения каждого значения в этом столбце во время обучения модели.
Возраст
Наконец, давайте посмотрим, как возрастные изменения имеют место в наборе данных. Мы уже удалили выбросы из набора данных. Теперь я воспользуюсь двумя диаграммами разброса, одна перекрывающая другую, для двух классов целевой переменной.
Сначала я выбираю записи с Showed_up как TRUE, а затем использую table и as.data.frame для создания таблицы частот с именем age.show. Аналогичным образом я создаю фрейм данных age.no_show для Showed_up как FALSE. Используя два раза geom_point, я создаю две перекрывающиеся диаграммы рассеяния.

Сюжет показывает, что количество встреч сильно различается в зависимости от возраста. Максимальное количество посещений - для младенцев. Примерно к 50 годам наблюдается спад, а затем всплеск. Наконец, с возрастом все меньше и меньше людей назначают встречи. Таким образом, возраст может также влиять на целевую переменную.
Теперь, когда у нас есть довольно хорошее представление о наборе данных, давайте сохраним его в измененном виде, а затем будем использовать библиотеки Python для прогнозирования. Я буду использовать write.csv(), чтобы сохранить набор данных в файл dataset_modified.csv. row.names as FALSE гарантирует, что индексы строк не будут сохранены.
Классификация с использованием Python
Я разработаю искусственную нейронную сеть для обучения на данных данных после надлежащей инженерии данных для классификации.
Импортировать библиотеки
Я импортирую необходимые библиотеки, включая pandas для работы с CSV, sklearn для работы с обработкой данных и keras & tensorflow для создания искусственной нейронной сети.
Импортировать набор данных
Я воспользуюсь функцией read_csv(), чтобы импортировать файл набора данных dataset_modified.csv. Затем я воспользуюсь методом head(), чтобы просмотреть первые 5 строк.


Инженерия данных
Перед тем, как набор данных будет готов к фактическому использованию, я выполню ряд шагов по инженерии данных.
Пропущенная встреча
Kaggle всегда меня многому учит. Даже после стольких шагов, которые я решил сделать, я нашел еще один, действительно полезный. Очень вдохновленный этим ядром Kaggle, я решил увидеть эффект, если кто-то пропустил встречу раньше на цели.
Как мы видим, значение корреляции действительно велико (~ 0,61) и, следовательно, будет важным фактором для классификации целевой переменной.
Удалите лишние столбцы
, поскольку столбцы PatientId, AppointmentID, ScheduleDay и AppointmentDay не будут иметь прямого влияния на целевую переменную, поэтому я удалю их с помощью drop().
Фиктивные столбцы
Я конвертирую столбец Neighbourhood в набор фиктивных столбцов. Я отброшу исходный столбец с помощью drop(), а затем с помощью get_dummies() создам столбцы, которые будут добавлены в исходный набор данных с помощью concat().
Сопоставление столбцов
Поскольку мы знаем, что столбец Gender относится к категориям F или M, я воспользуюсь функцией карты, чтобы преобразовать их в числовые значения, понятные ИНС.
Разделение тестовых данных поезда
Следующим шагом является разделение функций и столбцов, а затем создание 33% тестовых данных и 67% данных поезда с использованием train_test_split().
Итоговые данные поезда содержат 91 столбец.
Масштабирование данных
Нейронные сети лучше всего работают с масштабированными данными, поэтому я буду использовать StandardScaler() для масштабирования данных и обучения нейронной сети. При использовании X_train мы используем fit_transform, поскольку он обеспечивает соответствие этим значениям, а также преобразует их. Для X_test мы просто используем transform, поскольку он гарантирует, что функция масштабирования использует знания из X_train для преобразования тестовых данных.
Генерация модели
Набор данных готов к использованию, поэтому я создам искусственную нейронную сеть, используя метод Sequence(). Я добавляю четыре плотных слоя с 512, 1024, 2048 и 1 нейроном соответственно. Я также включаю Dropout() после каждого слоя, чтобы нейронная сеть не переборщила с данными. Для первого плотного слоя нам также нужно указать input_dim, который равен количеству столбцов в наших данных (91).
В нашей сети 2 673 665 различных параметров, которые необходимо обучить.
Теперь я обучу модель с разбивкой по валидации 0,1, что означает, что из всех данных в обучающих данных модель будет обучаться на 90% данных и проверять свое обучение на 10% данных.
Прогноз модели
Теперь я протестирую модель на тестовых данных и выведу матрицу неточности и точность.
Хотя модель достигла точности около 88%, матрица неточностей показывает, что модель способна правильно предсказать, когда кто-то придет на встречу, но приблизительно в 50% случаев она не появится.
Мы можем улучшить модель, изучив больше функций данных и проведя инжиниринг данных для выявления других факторов. Но пока 88% - это достаточно хорошая точность для этой модели.
Заключение
В этой статье мы работали с искусственной нейронной сетью и исследованием данных с использованием R и Python для разработки рабочих процессов с данными, которые включают оба языка.
Если у вас есть мысли или идеи, поделитесь ими. Также вы можете связаться со мной в LinkedIn. Если вам понравилась эта статья, вам также могут понравиться: