0の行・列を縮める

  • 複数のカテゴリカル変数が作る、多元表があって、各変数の周辺度数が0になっているかもしれない(のだが、元の多元表の形で考えていたい)とき、表を縮めたり(そのあと、縮めることで処理が容易になることをしたり)、いったん縮めた表を元の形に戻したりしたい(かもしれない)
  • そのためのメモ
# Aは周辺度数が0である行・列などを持つアレイ(縮めるとき)
# Aは縮めた後のアレイ(もとに戻すとき)
# A.oriはNULLなら、縮める処理、A.oriに縮める前の多元表アレイを与えるのはAをもとに戻す処理の時
reshape.table <- function(A,A.ori=NULL){
	inv <- FALSE
	if(!is.null(A.ori)){
		inv <- TRUE
	}
	if(!inv){
		A.ori <- A
	}
# 多元表の周辺度数をリストにする
	M <- calc.marg(A.ori)
# 周辺度数の0判定
	S <- lapply(M,sign)
# 縮めた後の表のレベル数
	new.dim <- lapply(S,sum)
# 周辺度数によって0であることが規定されるセルを確認
	tmp <- S[[1]]
	for(i in 2:length(S)){
		tmp <- t(S[[i]]) %x% tmp
	}
	if(!inv){
		return(array(A[which(tmp!=0)],new.dim))
	}else{
		tmp.A <- rep(0,length(A.ori))
		tmp.A[which(tmp!=0)] <- c(A)
		return(array(tmp.A,dim(A.ori)))
	}	
}
# 周辺度数を計算
calc.marg <- function(A){
  d <- dim(A)
  ret <- list()
  for(i in 1:length(d)){
    ret[[i]] <- apply(A,i,sum)
  }
  ret
}
  • 使ってみる
# 適当に周辺度数が0になる可能性の高いn-way 表を作る
n <- 5
M <- list()
N <-100

for(i in 1:n){
	M[[i]] <- sample(0:5,sample(2:4,1))
	M[[i]] <- M[[i]]/sum(M[[i]])*N
}

	tmp <- M[[1]]
	for(i in 2:length(M)){
		tmp <- t(M[[i]]/N) %x% tmp
	}
A <- array(tmp,lapply(M,length))

A.r <- reshape.table(A)
A.2 <- reshape.table(A.r,A)
calc.marg(A)
calc.marg(A.r)
calc.marg(A.2)
A-A.2