2015-08-31 3 views
2

Я выполняю проверку перестановки Фишера, в которой я должен генерировать все комбинации статуса лечения.Использовать значения матриц в качестве индексов

У нас есть 4 предмета, из которых 2 обработаны. Используя combn, я могу генерировать все комбинации обработанных предметов. Например, первая строка означает, что обрабатываются первый и второй субъекты.

t(combn(4, 2)) 

    [,1] [,2] 
[1,] 1 2 
[2,] 1 3 
[3,] 1 4 
[4,] 2 3 
[5,] 2 4 
[6,] 3 4 

Как перейти от этой матрицы к матрице состояния лечения следующим образом:

 [,1] [,2] [,3] [,4] 
[1,] 1 1 0 0 
[2,] 1 0 1 0 
... 
+2

Это может быть сделано с помощью 'опции FUN' в' 'combn' + (T (combn (4,2, ПОТЕХИ = функция (х) 1: 4% в% х)))' – akrun

+0

@ Комментарий akrun действительно работает лучше всего (т.е. проще всего понять). (Не могли бы вы разместить его в качестве ответа?) Ответ героики, вероятно, имеет небольшую опечатку, так как я получаю ошибку. Ответ Майкла Чирико самый быстрый. – Heisenberg

+0

Я сравнивал себя с @ akrun's & his lightyears быстрее (3000 раз быстрее на 20 выбирают 10). – MichaelChirico

ответ

3

Публикация мой комментарий в качестве решения. Это модификация предложения Хероки. + преобразует logical в numeric и должен быть быстрее, чем as.integer.

+(t(combn(4,2, FUN=function(x) 1:4 %in% x))) 
#  [,1] [,2] [,3] [,4] 
#[1,] 1 1 0 0 
#[2,] 1 0 1 0 
#[3,] 1 0 0 1 
#[4,] 0 1 1 0 
#[5,] 0 1 0 1 
#[6,] 0 0 1 1 
6

Использование базового R:

res <- t(apply(t(combn(4,2)),MARGIN=1,FUN=function(x){ 
    return(as.numeric(1:4 %in% x)) 
})) 
> res 
    [,1] [,2] [,3] [,4] 
[1,] 1 1 0 0 
[2,] 1 0 1 0 
[3,] 1 0 0 1 
[4,] 0 1 1 0 
[5,] 0 1 0 1 
[6,] 0 0 1 1 
+0

Следующее предложение @ akrun «FUN» в «combn» и вдохновение от вашего «1: 4% в% x», я думаю, что это самый простой ответ: 't (combn (4, 2, FUN = function (x) {return (as.numeric (1: 4% in% x))})) ' – Heisenberg

+0

с использованием' as.integer' должно быть еще быстрее. – MichaelChirico

5

Как насчет:

out <- matrix(0L, nrow = nrow(x), ncol = max(x)) 

for (i in 1:nrow(x)) out[i, x[i, ]] <- 1L 

> out 
    [,1] [,2] [,3] [,4] 
[1,] 1 1 0 0 
[2,] 1 0 1 0 
[3,] 1 0 0 1 
[4,] 0 1 1 0 
[5,] 0 1 0 1 
[6,] 0 0 1 1 

Мы также можем сделать это без цикла, хотя это может быть немного менее читаемым (спасибо @Frank для ног):

m <- matrix(0L, choose(4, 2), 4) 
m[cbind(rep(1:choose(4, 2), each = 2), c(combn(4, 2)))] <- 1L 

Легко упаковывается в функции:

participants <- function(m, n){ 
    if (n > m) stop() 
    mcn <- choose(m, n) 
    out <- matrix(0L, mcn, m) 
    out[cbind(rep(1:mcn, each = n), c(combn(m, n)))] <- 1L 
    out 
} 

> participants(6, 5) 
    [,1] [,2] [,3] [,4] [,5] [,6] 
[1,] 1 1 1 1 1 0 
[2,] 1 1 1 1 0 1 
[3,] 1 1 1 0 1 1 
[4,] 1 1 0 1 1 1 
[5,] 1 0 1 1 1 1 
[6,] 0 1 1 1 1 1 
+2

Вы можете использовать (1) 'choose' для получения числа комбо и (2) присваивания матрицы вместо цикла:' m <- matrix (0L, выбрать (4,2), 4); m [cbind (rep (1: выбрать (4,2), each = 2), c (combn (4,2)))] <- 1L'. Та же идея. – Frank

Смежные вопросы