Категоризация набора данных в R

У меня проблема с категоризацией набора данных.

Набор данных - это матрица, в которой строки представляют собой наблюдения, а столбцы - характеристики. Значение каждой функции находится в диапазоне от 0 до 1. Набор данных используется для целей обучения, и поскольку метод, который я собираюсь использовать, зависит от небольшого изменения, набор данных должен быть отформатирован, чтобы не быть чувствительным.

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

Бывший. бункеры (1-2,2-3,3-4,4-5,5-6,6-7,7-8,8-9,9-10)

dataset #original dataset
>         [,1] [,2] [,3] [,4] [,5]
[1,]    8.1    5.3   10    4.4    4.6
[2,]    5.2   10    3.2    9.3    3.5
[3,]    7.3    1.6    9    8.9    8.4
[4,]    6.4    2.8    8    6.5    9.3
[5,]   10    4.3    2.2    1.1    5.3

transformed_dataset #binned dataset


>         [,1] [,2] [,3] [,4] [,5]
[1,]    8.5    5.5   9.5   4.5    4.5
[2,]    5.5   9.5   3.5    9.5   3.5
[3,]    7.5    1.5   8.5    8.5    8.5
[4,]    6.5    2.5   8.5    6.5    9.5
[5,]    9.5    4.5  2.5    1.5    5.5

Я не уверен, как я должен собирать такие данные и передавать их в качестве входных данных для naiveBayes из library("lattice"). Я знаю, что signif может округлять значение до заданного количества цифр и, таким образом, «связывать его», но я не могу определить количество ячеек.

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

Обновление данных о data.frame

Думаю, я забыл упомянуть об этом, но данные хранятся в data.frame, и я получаю доступ к данным с помощью $ data. все data.frame предоставляют метки для каждого наблюдения, к которым можно получить доступ с помощью $ labels.


r
person Lamda    schedule 15.04.2016    source источник
comment
Почему бы просто не округлить число в меньшую сторону? Таким образом, ваши корзины будут представлены одним числом, а не числом.   -  person ytk    schedule 15.04.2016
comment
Ох .. Хорошая идея. Таким образом я мог создавать более легкие корзины.   -  person Lamda    schedule 15.04.2016


Ответы (2)


Хм. У вас могут возникнуть проблемы с типами данных здесь, потому что класс matrix плохо работает с факторами, а интервалы объединения лучше всего описываются факторами.

Чтобы выполнить биннинг, вы можете использовать функцию cut из базовой установки R, например:

> data <- c(1,2,4,1,5,3,3,5,2,2,5,5,5,7,8,9,5,3,2,6,8,9,3,1)
> breaks <- c(0, 3, 6, 9)
> cut(data, breaks=breaks)
 [1] (0,3] (0,3] (3,6] (0,3] (3,6] (0,3] (0,3] (3,6] (0,3] (0,3] (3,6] (3,6]
 [13] (3,6] (6,9] (6,9] (6,9] (3,6] (0,3] (0,3] (3,6] (6,9] (6,9] (0,3] (0,3]
 Levels: (0,3] (3,6] (6,9]

Или, используя левый интервал:

> cut(data, breaks=breaks, right=FALSE)
 [1] [0,3) [0,3) [3,6) [0,3) [3,6) [3,6) [3,6) [3,6) [0,3) [0,3) [3,6) [3,6)
[13] [3,6) [6,9) [6,9) <NA>  [3,6) [3,6) [0,3) [6,9) [6,9) <NA>  [3,6) [0,3)
Levels: [0,3) [3,6) [6,9)

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

person andrechalom    schedule 15.04.2016
comment
Спасибо за ответ ... @Teja K пришла с идеей, которая кажется мне гораздо более простой и подходящей для меня. Проблема в том, что я не могу определить количество ящиков. Можно ли вместо этого определить категории как среднее значение корзины? - person Lamda; 15.04.2016
comment
ну, вы можете использовать что-то вроде bins <- seq(0, 10, length.out=XXX) и продолжать изменять length.out, чтобы было больше или меньше ящиков - person andrechalom; 15.04.2016
comment
было бы возможно иметь среднее значение ячеек, а не это (0,3] ... - person Lamda; 15.04.2016

Простое решение может быть таким:

d <- matrix(c(8.1, 5.3, 10, 4.4, 4.6,
              5.2, 10, 3.2, 9.3, 3.5,
              7.3, 1.6, 9, 8.9, 8.4,
              6.4, 2.8, 8, 6.5, 9.3,
              10, 4.3, 2.2, 1.1, 5.3), nrow=5, ncol=5, byrow=TRUE)

d <- as.data.frame(apply(d, 2, function(column) {
  as.factor(round(column+0.5)-0.5)
}))

Приводя к результатам:

> d
   V1  V2  V3  V4  V5
1 8.5 5.5 9.5 4.5 4.5
2 5.5 9.5 3.5 9.5 3.5
3 7.5 1.5 9.5 8.5 8.5
4 6.5 2.5 7.5 6.5 9.5
5 9.5 4.5 2.5 1.5 5.5

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

> class(d[,1])
[1] "factor"
> levels(d[,1])
[1] "5.5" "6.5" "7.5" "8.5" "9.5"

Обратите внимание, что трюк с добавлением и удалением 0,5 не удастся, если у вас есть какое-либо значение, равное 0 - он присвоит ему уровень «0» вместо «0,5». Вы можете решить эту проблему, добавив эту строку в функцию:

column[which(column == 0)] <- 0.5

Надеюсь, поможет.

person lrnzcig    schedule 15.04.2016
comment
Я думаю, что ваш способ сделать это кажется правильным, но я хочу контролировать количество ящиков, которые я создаю, чтобы я мог найти оптимальное количество .. - person Lamda; 15.04.2016
comment
Не уверен, что я понимаю, как вы хотите определять бункеры, в любом случае, если вы хотите контролировать бункеры, возможно, вы могли бы использовать cut, как в ответе @andrechalom. Вы можете размещать любые разрывы, которые хотите, не должны распределяться равномерно, и как только ваш столбец определен как категориальный, описания уровней предназначены только для удобства чтения, вы даже можете их изменить, алгоритм не будет использовать описание уровни. Удачи. - person lrnzcig; 15.04.2016
comment
На выходе должно быть не (0,3], а среднее значение интервала бункера. Но да. Cut можно использовать. - person Lamda; 15.04.2016
comment
Я имею ввиду: вывод бессмысленный. Вы можете изменить его на среднее значение интервала бункера, если хотите. Просто переназначьте, используя levels(column) <- c("level1", "level", ...). Ваше здоровье. - person lrnzcig; 15.04.2016