如何在数据框中按行获取值的所有组合

时间:2019-05-13 09:08:01

标签: r dataframe permutation

我有一个像这样的列联表(ct):

read.table( text=     
      1  2  3 4 5 6
1     0  0  1 0 2 0
2     0  0  2 0 0 0
70    0  0  3 0 0 0
76   15 13 19 2 9 8
85    0  0  2 0 0 0
109   0  0  0 0 1 2
479   0  0  0 0 2 0
491   2  0  0 0 0 0
1127  0  1  0 1 6 0
1131  0  1  1 1 2 0
1206  1  3  1 0 0 1
1208  1  0  1 0 0 1
1210  0  1  0 0 0 1
1225  2  0  1 0 0 0
1232  0  0  0 0 1 1
1242  0  0  0 1 0 1
1243  1  0  0 0 1 1
1251  0  0  2 0 1 2
1267  0  2  1 0 0 0
4415  0  2  0 0 0 0
4431  0  0  0 2 0 0
4808  0  0  0 0 2 0
4823  0  2  0 0 0 0 )

其中行表示簇,列表示医院,表中的数字表示分离株的数量。
例如:群集1有3个分离株,医院3中有1个,医院2中有2个。

我现在要检查集群和医院是否相互依赖。为此,我想创建1000个随机分布的表,其中一个群集中的所有隔离株都有机会落入每家医院。
例如:然后,群集1中的3个隔离区可能会分布在3家医院中,这样我得到的值是:0 1 1 1 0 0 0。

组合可以发生多次。

我尝试过:

 replicates <- 1000

 permutations <- lapply(seq(replicates), function(i, ct){
   list <- lapply(apply(ct,1,list),unlist)
   list <- lapply(list, function(x)as.numeric(x))
    z <- as.data.frame(do.call(rbind, lapply(list, function(x) sample(x))))
 }, ct = ct)

但是这样一来,只有数据帧中的值才被改组到行中的另一个位置。
有人可以帮我吗?

3 个答案:

答案 0 :(得分:1)

我同意Maurits Evers的回答,在排名上,每行有二项式组合:n个变量表示2 ^ n个组合...如果添加m-1列,则会产生2 ^(n + m)种可能性。

答案 1 :(得分:1)

这是使用partitions::composition的替代方法。

library(partitions)

# smaller toy data
d <- data.frame(x1 = c(0, 1, 1), x2 = c(2, 2, 0), x3 = c(0, 1, 1))

# calculate row sums
rs <- rowSums(d)

# for each unique row sum, partition the value with order m = number of columns
# this avoids repeating calculation of partitions on duplicate row sums
l <- lapply(unique(rs), compositions, m = ncol(d))

# name list elements with row sums
names(l) <- unique(rs)

# set number of samples
n <- 4

# to reproduce sample in this example  
set.seed(1)

# loop over rows in data frame
lapply(1:nrow(d), function(i){

  # index list of partitions using row sums
  m <- l[[as.character(rs[i])]]

  # number of columns to sample from
  nc <- ncol(m)

  # select columns from matrix using a sample of n column indexes
  m[ , sample(nc, n, replace = TRUE)]
})

结果是一个列表,其中每个元素都是原始数据每一行的矩阵。每个矩阵列都是一个(采样的)分区。

# [[1]]
#      [,1] [,2] [,3] [,4]
# [1,]    1    0    1    0
# [2,]    1    2    0    0
# [3,]    0    0    1    2
# 
# [[2]]
#     [,1] [,2] [,3] [,4]
# [1,]    1    0    0    2
# [2,]    3    1    0    0
# [3,]    0    3    4    2
# 
# [[3]]
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    1    1
# [2,]    0    0    1    1
# [3,]    1    0    0    0

我尝试对示例数据中最大的行总和(66)进行分区,并且运行很快。因此,如果您的行总和不是很大并且列数很小(例如此处),那么上面的代码可能是一个可行的选择。

system.time(p <- compositions(66, 6))
#   user  system elapsed 
#   1.53    0.16    1.68 
str(p)
# 'partition' int [1:6, 1:13019909] 66 0 0 0 0 0 65 1 0 0 ...

请注意,如果列数增加,它将迅速“爆炸”:

system.time(p <- compositions(66, 7))
#    user  system elapsed 
#   14.11    1.61   15.72

答案 2 :(得分:1)

对不起,@ Henrik的回复很晚。您的代码对我来说效果很好!但是,在我的一位同事的帮助下,我找到了这段代码(我将使用您的示例数据来显示它):

#data
d <- data.frame(x1 = c(0, 1, 1), x2 = c(2, 2, 0), x3 = c(0, 1, 1))
#Number of replicates I want
replicates <- 1000
#Number of columns in the table 
k<- 3

l <- NULL

#unlist the dataframe
list <- lapply(apply(d,1,list),unlist)

#Calculate replicates of the dataframe, where numbers are permuted within rows

permutations <- lapply(seq(replicates), function(j){
        l_sampled <- lapply(list, function(x){
          pos.random <- sample(k, sum(x), replace = T) 
          x.random <- rep(0,k)                        
          for (i in 1:k){
            x.random[i] <- sum(pos.random==i)
          }
          l = rbind(l, data.frame(x.random)) 
        })
        df <- data.frame(matrix(unlist(l_sampled), nrow=length(l_sampled), byrow=T))
})

#Example for results:

> permutations[[8]]
  X1 X2 X3
1  2  0  0
2  1  2  1
3  1  0  1
> permutations[[10]]
  X1 X2 X3
1  0  1  1
2  2  0  2
3  0  2  0