2016-10-20 1 views
0

J'essaie de tirer de deux distributions différentes avec une probabilité 100000 fois. Malheureusement je ne peux pas voir ce qui ne va pas avec ma boucle for, cependant, il ajoute seulement 1 valeur à simulated_data au lieu des 100.000 valeurs désirées.Dessin à partir de deux distributions avec une probabilité dans R

Question 1: Comment puis-je résoudre ce problème?

Question 2: Existe-t-il une méthode beaucoup plus efficace où je n'ai pas besoin de faire défiler 100 000 éléments dans une liste?

#creating a vector of probabilities 
probabilities <- rep(0.99,100000) 
#creating a vector of booleans 
logicals <- runif(length(probabilities)) < probabilities 

#empty list for my simulated data 
simulated_data <- c() 

#drawing from two different distributions depending on the value in logicals 
for(i in logicals){ 

    if (isTRUE(i)) { 
    simulated_data[i] <- rnorm(n = 1, mean = 0, sd = 1) 
    }else{ 
    simulated_data[i] <- rnorm(n = 1, mean = 0, sd = 10) 
    } 
} 
+0

Je vois que vous avez résolu votre problème d'une manière ordonnée, mais pour référence ultérieure la raison pour laquelle votre boucle échoué est parce que lorsque vous utilisez une boucle 'for each', le' i'th terme n'est pas un index. Ainsi, 'simulated_data [i]' est seulement instancié comme 'simulated_data [TRUE]' ou 'simulated_data [FALSE]', et ne reçoit qu'une seule valeur. Une solution potentielle est d'utiliser 'for (i in 1: length (logicals))'. – Zach

+0

@Zach: presque un +1, sauf que vous ne devriez pas utiliser '1: n' dans les boucles. Utilisez à la place 'seq_len (n)' (le premier ferait des choses étranges si 'n 'se révélait être zéro, ou négatif.). 'seq_along' est une autre fonction pertinente. – JDL

Répondre

0

Voici une solution agréable pour tout le monde ici:

n <- 100000 
prob1 <- 0.99 
prob2 <- 1-prob1 

dist1 <- rnorm(prob1*n, 0, 1) 
dist2 <- rnorm(prob2*n, 0, 10) 

actual_sample <- c(dist1, dist2) 
0

Il semble que vous voulez créer un échantillon final où chaque élément est pris au hasard à partir soit sample1 ou sample2, avec des probabilités 0,99 et 0,01 .

L'approche correcte serait de générer les deux échantillons, chacun contenant le même nombre d'éléments, puis de sélectionner aléatoirement de l'un ou l'autre.

L'approche correcte serait:

# Generate both samples 
n = 100000 
sample1 = rnorm(n,0,1) 
sample2 = rnorm(n,0,10) 

# Create the logical vector that will decide whether to take from sample 1 or 2 
s1_s2 = runif(n) < 0.99 

# Create the final sample 
sample = ifelse(s1_s2 , sample1, sample2) 

Dans ce cas, il n'est pas garanti qu'il y a exactement 0,99 * n échantillons de sample1 et 0,01 * n de sample2. En fait:

> sum(sample == sample1) 
[1] 98953 

Ceci est proche de 0,99 * n, comme prévu, mais pas exactement.

0

créer un vecteur avec la fraction désirée de valeurs de chaque distribution, puis créer une permutation aléatoire des valeurs:

N = 10000 
frac =0.99 
rand_mix = sample(c(rnorm(frac*N, 0, sd=1) , rnorm((1-frac)*N, 0, sd=10))) 

> table(abs(rand_mix) >1.96) 

FALSE TRUE 
9364 636 
> (100000-636)/100000 
[1] 0.99364 

> table(rnorm(10000) >6) 

FALSE 
10000 

La fraction est fixe. Si vous WANTE une fraction éventuellement aléatoire (mais proche de 0,99 statistiquement) puis essayez ceci:

> table(sample(c(rnorm(10e6), rnorm(10e4, sd=10)), 10e4) > 1.96) 

FALSE TRUE 
97151 2849 

Comparer avec:

> N = 100000 
> frac =0.99 
> rand_mix = sample(c(rnorm(frac*N, 0, sd=1) , rnorm((1-frac)*N, 0, sd=10))) 
> table(rand_mix > 1.96) 

FALSE TRUE 
97117 2883 
+0

Je pense que c'est le meilleur jusqu'à présent. Pas forcé comme forçant les 0.99 et 0.1 exactement sur les distributions. – mat4nier

+0

En fait, il faut exactement 0,99 * N de un et 0,01 * N de l'autre, mais les valeurs sont aléatoires, de sorte que la fraction au-dessus d'un point de coupe spécifié variera d'un tirage à l'autre. Cette solution peut être «meilleure» dans le sens où elle renvoie les valeurs d'une manière qui ne permet pas vraiment de savoir de quelle distribution provient une valeur particulière depuis que l'ordre est brouillé. –

+0

Ah donc c'est la même que la première solution de générer juste un vecteur 0,99 * n de 1 dist, et 0,01 * n d'un autre dist et de les coller ensemble. – mat4nier