Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate 3 random number that sum to 1 in R

Tags:

random

r

I am hoping to create 3 (non-negative) quasi-random numbers that sum to one, and repeat over and over.

Basically I am trying to partition something into three random parts over many trials.

While I am aware of

a = runif(3,0,1)

I was thinking that I could use 1-a as the max in the next runif, but it seems messy.

But these of course don't sum to one. Any thoughts, oh wise stackoverflow-ers?

like image 226
mmann1123 Avatar asked Jun 12 '12 20:06

mmann1123


People also ask

How do you generate a random number from 0 to 1 in R?

For uniformly distributed (flat) random numbers, use runif() . By default, its range is from 0 to 1. To generate numbers from a normal distribution, use rnorm() . By default the mean is 0 and the standard deviation is 1.

What three numbers add up to 1?

(1, 0, 0), an equally valid triple, must come from (1, 0, 0). One solution: The set of positive numbers that add to 1 form a n equilateral triangle in three-space, with coordinates (1,0,0), (0,1,0), (0,0,1).

How do you generate a sum of random numbers?

You could use the RAND() function to generate N numbers (8 in your case) in column A. Then, in column B you could use the following formula B1=A1/SUM(A:A)*320 , B2=A2/SUM(A:A)*320 and so on (where 320 is the sum that you are interested into). So you can just enter =RAND() in A1, then drag it down to A8.

What is the formula to generate a random number between 1 and R?

To generate uniformly distributed random number runif() is used. Default range 0 – 1. First, we will require to specify the number required to be generated. In addition, the range of the distribution can be specified using the max and min argument.


2 Answers

This question involves subtler issues than might be at first apparent. After looking at the following, you may want to think carefully about the process that you are using these numbers to represent:

## My initial idea (and commenter Anders Gustafsson's):
## Sample 3 random numbers from [0,1], sum them, and normalize
jobFun <- function(n) {
    m <- matrix(runif(3*n,0,1), ncol=3)
    m<- sweep(m, 1, rowSums(m), FUN="/")
    m
}

## Andrie's solution. Sample 1 number from [0,1], then break upper 
## interval in two. (aka "Broken stick" distribution).
andFun <- function(n){
  x1 <- runif(n)
  x2 <- runif(n)*(1-x1)
  matrix(c(x1, x2, 1-(x1+x2)), ncol=3)
}

## ddzialak's solution (vectorized by me)
ddzFun <- function(n) {
    a <- runif(n, 0, 1)
    b <- runif(n, 0, 1)
    rand1 = pmin(a, b)
    rand2 = abs(a - b)
    rand3 = 1 - pmax(a, b)
    cbind(rand1, rand2, rand3)
}

## Simulate 10k triplets using each of the functions above
JOB <- jobFun(10000)
AND <- andFun(10000)
DDZ <- ddzFun(10000)

## Plot the distributions of values
par(mfcol=c(2,2))
hist(JOB, main="JOB")
hist(AND, main="AND")
hist(DDZ, main="DDZ")

enter image description here

like image 91
Josh O'Brien Avatar answered Sep 18 '22 15:09

Josh O'Brien


just random 2 digits from (0, 1) and if assume its a and b then you got:

rand1 = min(a, b)
rand2 = abs(a - b)
rand3 = 1 - max(a, b)
like image 26
ddzialak Avatar answered Sep 18 '22 15:09

ddzialak