Obtendo os elementos excluídos para cada uma das combinações combn (n, k)
-
21-09-2019 - |
Pergunta
Suponha que geramos uma matriz A
onde cada coluna contém uma das combinações de n
elementos em grupos de k
. Então, suas dimensões serão k,choose(n,k)
. Essa matriz é produzida dando o comando combn(n,k)
. O que eu gostaria de obter é outra matriz B
com dimensões (n-k),choose(n,k)
, onde cada coluna B[,j]
vai conter o excluído n-k
elementos de A[,j]
.
Aqui está um exemplo da maneira como eu uso a tabela Get B
. Você acha que é um método seguro de usar? Existe outra maneira?
n <- 5 ; k <- 3
(A <- combn(n,k))
(B <- combn(n,n-k)[,choose(n,k):1])
Outro exemplo
x<-c(0,1,0,2,0,1) ; k<- 4
(A <- combn(x,k))
(B <- combn(x,length(x)-k)[,choose(length(x),k):1])
Este pergunta anterior do meu faz parte desse problema.
Obrigada.
Solução
Usando Musa idéia
B <- apply(A,2,function(z) x[is.na(pmatch(x,z))])
No que diz respeito ao primeiro exemplo:
B <- apply(A,2,function(z) (1:n)[is.na(pmatch((1:n),z))])
Outras dicas
Use o setdiff
função:
N <- 5
m <- 2
A <- combn(N,m)
B <- apply(A,2,function(S) setdiff(1:N,S))
Modificado: o acima funciona apenas quando os vetores têm valores exclusivos. Para o segundo exemplo, escrevemos um substituto para setdiff
isso pode lidar com valores duplicados. Nós usamos rle
Para contar o número de ocorrência de cada elemento nos dois conjuntos, subtraia as contagens e inverta o RLE:
diffdup <- function(x,y){
rx <- do.call(data.frame,rle(sort(x)))
ry <- do.call(data.frame,rle(sort(y)))
m <- merge(rx,ry,by='values',all.x=TRUE)
m$lengths.y[is.na(m$lengths.y)] <- 0
rz <- list(values=m$values,lengths=m$lengths.x-m$lengths.y)
inverse.rle(rz)
}
x<-c(0,1,0,2,0,1) ; k<- 4
A <- combn(x,k)
B <- apply(A,2,function(z) diffdup(x,z))
Aqui uma solução mais geral (você pode substituir X
por qualquer vetor que contenha entradas exclusivas):
X<-1:n
B<-apply(A,2,function(x,ref) ref[!ref%in%x],ref=X)
B<-do.call(cbind,B)
Enquanto na sua pergunta anterior X e Y não eram conjuntos, desde que as colunas de A sejam conjuntos adequados, o código acima deve funcionar.