2
votes

Comment obtenir toutes les combinaisons de valeurs par ligne dans un dataframe

J'ai un tableau de contingence (ct) comme celui-ci:

 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)

Où les lignes représentent le cluster, les colonnes représentent les hôpitaux et les nombres dans le tableau le nombre d'isolats.
Par exemple: le cluster 1 a 3 isolats, 1 à l'hôpital 3 et 2 à l'hôpital 2.

Je veux maintenant vérifier si les clusters et les hôpitaux sont dépendants l'un de l'autre ou non. Pour cela, j'aimerais créer 1000 tables distribuées aléatoirement, où tous les isolats d'un cluster ont la possibilité de tomber dans chaque hôpital.
Par exemple: les 3 isolats du cluster 1 pourraient alors être répartis sur 3 hôpitaux, de sorte que j'obtienne les valeurs: 0 1 1 1 0 0.

Les combinaisons peuvent se produire plusieurs fois.

J'ai essayé ceci:

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 )

Mais par cela, seules les valeurs du dataframe sont mélangées à une autre position dans la ligne.
Quelqu'un peut-il m'aider?


6 commentaires

Si j'ai bien compris, j'imagine que ce n'est pas un problème résolu; vous aurez trop de combinaisons par ligne. 6 numéros peuvent déjà être réorganisés en 6! = 720 façons, et nous ne considérons pas encore les différentes décompositions possibles des sommes (en ligne).


Je n'ai pas vraiment besoin de toutes les combinaisons possibles. En fin de compte, je voudrais avoir une liste de 1000 dataframes où les valeurs de chaque ligne ont été réorganisées au hasard.


@Martinique Ce n'est pas clair pour moi. Donc, pour chaque ligne, vous voulez tirer au hasard 1000 échantillons de toutes les permutations des 6 nombres et de toutes les permutations de leurs décompositions de somme possibles? Y a-t-il une préférence / un biais à savoir si vous échantillonnez à partir des permutations de nombres ou des permutations de leurs décompositions de somme? Ce serait bien si vous deviez reformuler et clarifier votre énoncé de problème dans le message principal (n'ajoutez pas d'informations critiques dans les commentaires). Soyez précis et précis, le diable est dans les détails.


@MauritsEvers J'ai édité la question et j'espère pouvoir préciser un peu ce que j'aimerais avoir.


"Je veux maintenant vérifier si les clusters et les hôpitaux sont dépendants les uns des autres ou non." Un test d'indépendance du chi carré vous aider à répondre à cette question? Je ne vois pas pourquoi vous devez proposer un test personnalisé basé sur la permutation ici.


Parce que moins de 80% des cellules de mon tableau sont sous la valeur de 5, ce qui, à ma connaissance, est une hypothèse pour ce test. J'ai également essayé le test exact de Fishers comme alternative, mais nous voulions avoir une approche différente pour cette analyse. C'est pourquoi j'ai voulu créer moi-même des permutations. Cependant, je dois également manipuler des tableaux pour d'autres analyses de cette manière


3 Réponses :


1
votes

Je suis d'accord avec la réponse de Maurits Evers, au rang complet, vous obtenez une combinaison binomiale par lignes: n variables signifient 2 ^ n combinaison ... si vous ajoutez m-1 colonnes, cela donne 2 ^ (n + m) possibilités.


0 commentaires

1
votes

Voici une alternative utilisant partitions :: composition .

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

Le résultat est une liste où chaque élément est une matrice pour chaque ligne des données d'origine. Chaque colonne de matrice est une partition (échantillonnée).

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 ...

J'ai essayé de partitionner la plus grande somme de lignes dans vos données d'exemple (66), et cela fonctionne assez rapidement. Ainsi, si vos sommes de lignes ne sont pas beaucoup plus grandes et que le nombre de colonnes est petit (comme ici), le code ci-dessus peut être une option viable.

# [[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

Notez qu'il 'explose' rapidement si le nombre de colonnes augmente:

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)]
})


2 commentaires

Merci beaucoup pour vos efforts! Cela a vraiment beaucoup aidé!


Salut @Martinique Merci pour vos commentaires. Curieux de savoir comment (si ...) cela a fonctionné sur vos données réelles. À votre santé.



1
votes

Désolé @Henrik pour la réponse tardive. Votre code a très bien fonctionné pour moi! Cependant, avec l'aide d'un de mes collègues, j'ai trouvé ce code (je vais simplement le montrer en utilisant vos exemples de données):

#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


0 commentaires