在R中采样列联表

时间:2014-09-11 06:34:41

标签: r

我想知道是否有人可以提出一种有效的方法来抽样列联表,以便观察总数和列总数保持不变。

例如,在下表中,行是案例和列观察,我希望"加扰"观察结果使得(a)观测总数为54,(b)变量(例如A)中的观测总数为 16 18,与原始列总数相同为了A。

x<-matrix(c(
4,6,0,0,8,0,0,
1,1,1,1,4,0,0,
3,0,1,1,6,0,1,
2,1,0,0,1,0,0,
1,1,0,1,0,1,1,
2,0,0,2,1,2,0),
ncol=6,byrow=F)

colnames(x)<-c("A","B","C","D","E","F")

我已经看到了列联表采样的讨论,其中单元频率是采样(...)调用的采样概率的来源。这不符合我的目的,因为除了其他原因之外,列总数不会等于原始列总数。

任何帮助将不胜感激, 帕特里克

修改

如果没有解决这个问题的简单方法,也许有人可以帮我解决我过于复杂(失败)的尝试。我首先创建一个由每个变量的观察数组成的向量,例如,

m <- matrix()
v <- matrix()
for (h in 1:cols) {
    m <- rep(colnames(x)[h], sum(x[, h]))
    v <- c(v, m)}

然后我对其进行采样以随机改变观察结果,并将其绑定到等于案例数量的值样本

    v<-sample(v,length(v))
    p<-sample(seq(1:nrow(x)),length(v),T)
    n<-as.data.frame(cbind(v,p))

    t(table(n))

      v
    p A B C D E F
    1 3 1 3 1 1 1
    2 1 1 0 0 0 0
    3 3 0 3 0 2 1
    4 3 2 1 2 1 2
    5 2 1 0 0 0 1
    6 3 2 3 1 1 1
    7 3 1 2 0 0 1

    colSums(t(table(n)))
    A  B  C  D  E  F 
   18  8 12  4  5  7 

这很有效,除非样本p不能包含序列中的一个值(即&#34; case&#34;缺失),这是我经常学到的,特别是当样本有很多次迭代时(例如,1000)。

再次感谢, 帕特里克

2 个答案:

答案 0 :(得分:1)

另一种方式是:

indx <- cbind(c(replicate(ncol(x), sample(1:nrow(x)))), c(col(x)))
x1 <- x
x1[] <- x[indx]

colSums(x1)
# A  B  C  D  E  F 
#18  8 12  4  5  7 

colSums(x)
#A  B  C  D  E  F 
#18  8 12  4  5  7 

sum(x1)
#[1] 54

更新

根据令人困惑的新信息,这可能会有所帮助:

 cSum <- colSums(x)
 ind1 <- vector("list", length=ncol(x))
 for(i in seq_along(cSum)){
 repeat{ind1[[i]] <- sample(0:cSum[i], nrow(x)-1, replace=TRUE)
 if(sum(ind1[[i]]) <=cSum[i]) break
  }
 }

 x1 <- do.call(cbind, ind1)
 x2 <- rbind(x1,cSum-colSums(x1))
 colSums(x2)
# A  B  C  D  E  F 
#18  8 12  4  5  7 

sum(colSums(x2))
#[1] 54

  x2
 #    A B C D E F
 #[1,] 0 0 0 0 0 0
 #[2,] 9 5 1 2 0 1
 #[3,] 0 1 1 1 0 2
 #[4,] 0 0 4 0 0 1
 #[5,] 8 0 5 0 4 2
 #[6,] 0 0 1 0 1 1
 #[7,] 1 2 0 1 0 0

答案 1 :(得分:-1)

您可以使用

x.swapped <- apply(x, MARGIN=2, FUN=sample)

apply将参数FUN中传递的函数应用于矩阵MARGIN的列(如果x为2,行为1时为行)。
在这种情况下,我们应用sample函数 在没有额外参数sample的情况下调用时,只需重新排序向量中的元素(有关更多帮助,请参阅?sample)。

我们可以检查每列中的总数是否保持不变。

colSums(x)

 A  B  C  D  E  F 
18  8 12  4  5  7 

colSums(x.swapped)
 A  B  C  D  E  F 
18  8 12  4  5  7 

显然

sum(x)
[1] 54

sum(x.swapped)
[1] 54

输出的示例可能是(请注意,除非您使用set.seed修复RNG种子,否则sample的结果每次都会有所不同。)

x

     A B C D E F
[1,] 4 1 3 2 1 2
[2,] 6 1 0 1 1 0
[3,] 0 1 1 0 0 0
[4,] 0 1 1 0 1 2
[5,] 8 4 6 1 0 1
[6,] 0 0 0 0 1 2
[7,] 0 0 1 0 1 0

x.swapped

     A B C D E F
[1,] 6 4 1 0 1 0
[2,] 0 1 3 2 0 0
[3,] 0 0 1 1 1 2
[4,] 0 0 0 0 1 2
[5,] 8 1 1 1 1 2
[6,] 4 1 0 0 1 0
[7,] 0 1 6 0 0 1