Рисунок заимствован из Wiki |
Для создания таблиц данных с индикаторными переменными в пакете caret имеется функция dummyVars(), работа которой контролируется следующими аргументами:
- formula - формула R, задающая необходимую структуру итоговой таблицы;
- data - таблица данных;
- sep - необязательный параметр, который определяет символ, используемый в именах производных индикаторных переменных для разделения названия исходной качественной переменной и ее уровней (см. пример ниже);
- levelsOnly - логическое значение (TRUE/FALSE), позволяющее включить/отключить добавление имени исходной качественной переменной в имена производных индикаторных переменных;
- fullRank - логическое значение (TRUE/FALSE), определяющее ранг итоговой матрицы с нулями и единицами, которые кодируют уровни того или иного качественного предиктора; при fullRank = TRUE (подход, автоматически реализуемый функциями вроде lm(), glm() и др.) матрица будет иметь полный ранг (т.е. ее корреляция между ее столбцами будет равна нулю; по умолчанию fullRank = FALSE).
Рассмотрим работу функции dummyVars() на примере данных hellung из пакета ISwR. Таблица hellung содержит данные о численности conc (экз./мл) и диаметре diameter особей ресничных инфузорий Tetrahymena, которые выращивались в питательной среде без (glucose = 2) и с добавлением (glucose = 1) глюкозы. Цель эксперимента заключалась в установлении влияния глюкозы на размер инфузорий с учетом того, что этот размер может быть также связан с численностью клеток в культуре (примеры применения ковариационного анализа к этим данным можно найти в книгах Dalgaard 2008 и Мастицкий, Шитиков 2015).
Для удобства переименуем уровни переменной glucose:
Наша задача заключается в преобразовании переменной-фактора glucose в набор индикаторных переменных в соответствии с ее уровнями. Для большинства статистических методов число индикаторных переменных должно составлять \(K - 1\), где \(K\) - это число уровней в исходной качественной переменной (т.е. матрица, кодирующая индикаторные переменные, должна иметь полный ранг). В нашем случае переменная glucose имеет только два уровня (yes/no) и поэтому ее достаточно будет представить только в виде одной индикаторной переменной (т.е \(K - 1 = 2 - 1 = 1\)). Воспользуемся функцией dummyVars() для создания новой таблицы данных с соответствующей индикаторной переменной:
Важно отметить, что созданный нами объект newvar не является новой таблицей данных. Подобно тому, как это работает в случае с функцией preProcess(), результатом работы dummyVars() является создание объекта, в котором хранится информация о способе преобразования данных, содержащих соответствующие переменные. При выводе содержимого объекта newvar на экран, мы видим формулу, определяющую структуру новой таблицы данных, общее число переменных и число качественных переменных среди них (3 variables, 1 factors), узнаём, каким символом будут разделяться имена исходных качественных переменных и названия их уровней в именах индикаторных переменных (здесь - точкой: Variables and levels will be separated by '.'), а также видим, что для кодирования индикаторных переменных будет применяться метод "полный ранг" (A full rank encoding is used). Для выполнения преобразования данных как такового необходимо подать объект newvar на функцию predict():
Новая таблица transformedData, как и раньше, содержит переменные conc и diameter, а также индикаторную переменную glucose.no. Переменная glucose.no представлена двумя значениями - 0 для обозначения наличия глюкозы и 1 для обозначения ее отсутствия в питательной среде. Вместо имени glucose.no мы можем получить только название соответствующего уровня переменной glucose - такой подход (включается аргументом levelsOnly = TRUE) полезен при работе с качественными переменными, чьи уровни имеют вполне описательные названия (например, названия городов), что делает повтор имени исходной переменной ненужным:
Хотя использование метода "полный ранг" при кодировании индикаторных переменных является стандартным в R и необходимо для многих статистических методов, ряд методов (например, деревья принятия решений, кластерный анализ) все же могут сработать лучше при включении всех \(K\) индикаторных переменных в новую таблицу данных. Для реализации этого подхода достаточно воспользоваться аргументом fullRank = FALSE:
Заметьте, что теперь таблица transformedData включает две индикаторные переменные - yes и no.
В заключение отметим, что как и в случае с preProcess(), использование функции dummyVars() в сочетании с predict() позволяет легко создавать таблицы с индикаторными переменными для любых новых наборов данных, включающих соответствующие переменные (например, для контрольной выборки или для выборки, по которой необходимо выполнить предсказание значений некоторого отклика).
Наша задача заключается в преобразовании переменной-фактора glucose в набор индикаторных переменных в соответствии с ее уровнями. Для большинства статистических методов число индикаторных переменных должно составлять \(K - 1\), где \(K\) - это число уровней в исходной качественной переменной (т.е. матрица, кодирующая индикаторные переменные, должна иметь полный ранг). В нашем случае переменная glucose имеет только два уровня (yes/no) и поэтому ее достаточно будет представить только в виде одной индикаторной переменной (т.е \(K - 1 = 2 - 1 = 1\)). Воспользуемся функцией dummyVars() для создания новой таблицы данных с соответствующей индикаторной переменной:
Важно отметить, что созданный нами объект newvar не является новой таблицей данных. Подобно тому, как это работает в случае с функцией preProcess(), результатом работы dummyVars() является создание объекта, в котором хранится информация о способе преобразования данных, содержащих соответствующие переменные. При выводе содержимого объекта newvar на экран, мы видим формулу, определяющую структуру новой таблицы данных, общее число переменных и число качественных переменных среди них (3 variables, 1 factors), узнаём, каким символом будут разделяться имена исходных качественных переменных и названия их уровней в именах индикаторных переменных (здесь - точкой: Variables and levels will be separated by '.'), а также видим, что для кодирования индикаторных переменных будет применяться метод "полный ранг" (A full rank encoding is used). Для выполнения преобразования данных как такового необходимо подать объект newvar на функцию predict():
transformedData = predict(newvar, newdata = hellung) transformedData glucose.no conc diameter 1 0 631000 21.2 2 0 592000 21.5 3 0 563000 21.3 4 0 475000 21.0 5 0 461000 21.5 6 0 416000 21.3 ... 46 1 27000 23.6 47 1 24000 23.5 48 1 22000 23.3 49 1 14000 24.4 50 1 13000 24.3 51 1 11000 24.2
Новая таблица transformedData, как и раньше, содержит переменные conc и diameter, а также индикаторную переменную glucose.no. Переменная glucose.no представлена двумя значениями - 0 для обозначения наличия глюкозы и 1 для обозначения ее отсутствия в питательной среде. Вместо имени glucose.no мы можем получить только название соответствующего уровня переменной glucose - такой подход (включается аргументом levelsOnly = TRUE) полезен при работе с качественными переменными, чьи уровни имеют вполне описательные названия (например, названия городов), что делает повтор имени исходной переменной ненужным:
Хотя использование метода "полный ранг" при кодировании индикаторных переменных является стандартным в R и необходимо для многих статистических методов, ряд методов (например, деревья принятия решений, кластерный анализ) все же могут сработать лучше при включении всех \(K\) индикаторных переменных в новую таблицу данных. Для реализации этого подхода достаточно воспользоваться аргументом fullRank = FALSE:
newvar = dummyVars(~ glucose + conc + diameter, fullRank = FALSE, levelsOnly = TRUE, data = hellung) transformedData = predict(newvar, newdata = hellung) head(transformedData) yes no conc diameter 1 1 0 631000 21.2 2 1 0 592000 21.5 3 1 0 563000 21.3 4 1 0 475000 21.0 5 1 0 461000 21.5 6 1 0 416000 21.3
Заметьте, что теперь таблица transformedData включает две индикаторные переменные - yes и no.
В заключение отметим, что как и в случае с preProcess(), использование функции dummyVars() в сочетании с predict() позволяет легко создавать таблицы с индикаторными переменными для любых новых наборов данных, включающих соответствующие переменные (например, для контрольной выборки или для выборки, по которой необходимо выполнить предсказание значений некоторого отклика).
Скажите, в чём смысл в новой таблице transformedData, переименовывать переменную glucose в индикаторную переменную glucose.no?
Поскольку недавно пришлось также погрузиться в эту тему, хотелось бы дополнить:
1) деревья принятия решений и ряд других популярных алгоритмов машинного обучения способны работать и с категориальными переменными напрямую. Однако преобразования в индикаторные переменные часто все-равно имеют смысл для адекватного сравнения качества предсказания таких моделей как lm/glm (работающих только с фиктивными переменными) и алгоритмов машинного обучения svm, trees, neural networks, etc. (которым все-равно, количественные или категориальные переменные им были поданы на входе)
2) Функция dummyVars работает также и с преобразованием порядковых переменных в количественные, разбирая их по полиномам разной степени. Что тоже очень удобно! :)
Хотя часто оказывается, что модели в среднем имеют более высокую предсказательную силу при использовании порядковых переменных как обычных индикаторных, чем при аккуратном преобразовании по полиному.
Мой вопрос о вашей книге. Можно ли ее купить в электронном виде? Я живу в Киеве, и доставка из России стоит столько же, сколько книга )) Спасибо!
Однако перед тем, как сделать заказ, я бы посоветовал уточнить у продавца, какое это издание. В первой партии типография, к сожалению, сработала очень некачественно и в итоге шрифт комментариев к коду и шрифт результатов вычислений читаются очень плохо. Недавно это было исправлено, и следующая партия книг (т.е. напечатанная после августа) должна быть получше.
Кроме того, Вы всегда можете скачать свободно распростряняемую "самодельную" версию 2014-го года: http://r-analytics.blogspot.de/2014/12/r.html
Бесплатная версия на >90% аналогична платной версии.
Вопрос вот какой. Иногда надо сделать обратное перекодирование из фиктивных переменных. Есть ли возможность сделать это штатными средствами? Сейчас приходится писать собственную функцию, но благо что фиктивных переменных у меня не так много бывает. Однако, как справедливо, заметили в комментариях может быть и несколько тысяч уровней.
А с точки зрения зачем. Навскидку два варианта. Первый, выходы нейронной сети по фиктивным переменным. После обучения - сравнение по тестовой выборке выходов модели с тестовыми данными. Потом организация выходов уже готового сигнала для модели. Вариант два - в случае conjoint-анализа (если руками делать) обратное преобразование требуется для отчетности, графиков и пр.
Еще раз спасибо за блог и интересные статьи!
Спасибо!
Пока просто меняю уровни с помощью формулы factor() - и если поменять уровни фактора с помощью этой формулы, dummyVars меняет контрасты
как бы - потому что там не формируется датасет, но мы это понимаем по презентации решений.
например в дереве решений нам программа выдает ПолМ > 0,5 - так решения выдаются для numeric, хотя для integer форма записи была бы ПолМ = 1
Отправить комментарий