создание матрицы индикаторных переменных

Я хотел бы создать матрицу индикаторных переменных. Моя первоначальная мысль состояла в том, чтобы использовать model.matrix, который также был предложен здесь: -1-0-indicator-variables">Автоматическое расширение R-фактора в набор индикаторных переменных 1/0 для каждого уровня фактора

Однако model.matrix не работает, если фактор имеет только один уровень.

Вот пример набора данных с тремя уровнями фактора «регион»:

dat = read.table(text = "
    reg1    reg2    reg3   
      1       0       0
      1       0       0
      1       0       0
      1       0       0
      1       0       0
      1       0       0
      0       1       0
      0       1       0
      0       1       0
      0       0       1
      0       0       1
      0       0       1
      0       0       1
", sep = "", header = TRUE)

# model.matrix works if there are multiple regions:

region <- c(1,1,1,1,1,1,2,2,2,3,3,3,3)

df.region <- as.data.frame(region)

df.region$region <- as.factor(df.region$region)

my.matrix <- as.data.frame(model.matrix(~ -1 + df.region$region, df.region))
my.matrix


# The following for-loop works even if there is only one level to the factor
# (one region):

# region <- c(1,1,1,1,1,1,1,1,1,1,1,1,1)

my.matrix <- matrix(0, nrow=length(region), ncol=length(unique(region)))

for(i in 1:length(region)) {my.matrix[i,region[i]]=1}
my.matrix

Цикл for эффективен и кажется достаточно простым. Тем не менее, я изо всех сил пытался придумать решение, которое не включает циклы. Я могу использовать петлю выше, но изо всех сил пытаюсь отучить себя от них. Есть ли способ лучше?


person Mark Miller    schedule 22.12.2012    source источник


Ответы (2)


Я бы использовал матричную индексацию. От 1_:

Третья форма индексации — это числовая матрица с одним столбцом для каждого измерения: каждая строка индексной матрицы затем выбирает один элемент массива, и результатом является вектор.

Используя эту приятную функцию:

my.matrix <- matrix(0, nrow=length(region), ncol=length(unique(region)))
my.matrix[cbind(seq_along(region), region)] <- 1

#       [,1] [,2] [,3]
#  [1,]    1    0    0
#  [2,]    1    0    0
#  [3,]    1    0    0
#  [4,]    1    0    0
#  [5,]    1    0    0
#  [6,]    1    0    0
#  [7,]    0    1    0
#  [8,]    0    1    0
#  [9,]    0    1    0
# [10,]    0    0    1
# [11,]    0    0    1
# [12,]    0    0    1
# [13,]    0    0    1
person flodel    schedule 22.12.2012
comment
+1 для всех, кто в любое время использует малоизвестную, но очень классную функцию индексации матриц. Это мой любимый. - person Aaron left Stack Overflow; 22.12.2012
comment
Я думаю, что вместо nlevels(region) должно быть length(unique(region)); если уровень отсутствует, матрица будет недостаточно широкой. - person Aaron left Stack Overflow; 22.12.2012
comment
@ Аарон, первую строку я скопировал из ОП. Посмотрите, как определяется region; это не фактор, поэтому я думаю, что length(unique(region)) подходит. - person flodel; 22.12.2012
comment
Ах да, я вижу. Я бы по-прежнему предпочитал что-то вроде max, но если оно всегда определяется как последовательность возрастающих целых чисел, при этом ни одно из них не пропущено, то, конечно, в любом случае все в порядке. - person Aaron left Stack Overflow; 22.12.2012

Я придумал это решение, изменив ответ на аналогичный вопрос здесь:

Преобразование столбца из фрейма данных в несколько столбцов с помощью R

region <- c(1,1,1,1,1,1,2,2,2,3,3,3,3)
site <- seq(1:length(region))
df <- cbind(site, region)
ind <- xtabs( ~ site + region, df)
ind

region <- c(1,1,1,1,1,1,1,1,1,1,1,1,1)
site <- seq(1:length(region))
df <- cbind(site, region)
ind <- xtabs( ~ site + region, df)
ind

РЕДАКТИРОВАТЬ:

Строка ниже извлечет фрейм данных индикаторных переменных из ind:

ind.matrix <- as.data.frame.matrix(ind)
person Mark Miller    schedule 25.12.2012