2012-06-12 26 views
9

Tôi hy vọng tạo ra 3 số ngẫu nhiên không âm, tổng hợp thành một và lặp lại nhiều lần.Tạo 3 số ngẫu nhiên tổng cộng là 1 trong R

Về cơ bản, tôi đang cố phân vùng thứ gì đó thành ba phần ngẫu nhiên trong nhiều thử nghiệm.

Trong khi tôi biết

a = runif (3,0,1)

Tôi đã suy nghĩ rằng tôi có thể sử dụng 1-a như tối đa trong thời gian tới nếu, nhưng có vẻ như lộn xộn .

Nhưng những khóa học này không được tính vào một. Bất kỳ suy nghĩ, oh stackoverflow-ers khôn ngoan?

+2

Đây có phải là tùy chọn để chuẩn hóa lại các số ngẫu nhiên sau khi tạo không? –

+0

Làm thế nào về việc tạo ra 2 số ngẫu nhiên a và b? Sau đó, a + b + c = 1 => c = 1 - (a + b) –

+0

và nếu tổng a và b lớn hơn 1? – mmann1123

Trả lời

9

chỉ ngẫu nhiên 2 chữ số từ (0, 1) và nếu giả định của nó ab sau đó bạn có:

rand1 = min(a, b) 
rand2 = abs(a - b) 
rand3 = 1 - max(a, b) 
+0

Ngoài ra, bạn phải lặp lại tạo số thứ hai nếu một == b ... (nên là trường hợp hiếm RẤT) – ddzialak

+0

@user để a = 0,85 , b = 0,99 sau đó bạn có số: 0,85, 0,14, 0,01 (đối với tôi đây là 3 số ngẫu nhiên rất tốt từ 0,1) – ddzialak

+3

Kết quả phân phối dường như không chính xác nhỏ: http: //www.jstor. org/discover/10.2307/2983572? uid = 2129 & uid = 2 & uid = 70 & uid = 4 & sid = 21100849643501 và sau đó có thể truy cập miễn phí http://doc.utwente.nl/70657/1/Sleutel67random.pdf – Christian

4

Tôi đoán nó phụ thuộc vào những gì phân phối mà bạn muốn trên những con số, nhưng đây là một cách :

diff(c(0, sort(runif(2)), 1)) 

Sử dụng replicate để có được càng nhiều bộ như bạn muốn:

> x <- replicate(5, diff(c(0, sort(runif(2)), 1))) 
> x 
      [,1]  [,2]  [,3]  [,4]  [,5] 
[1,] 0.66855903 0.01338052 0.3722026 0.4299087 0.67537181 
[2,] 0.32130979 0.69666871 0.2670380 0.3359640 0.25860581 
[3,] 0.01013117 0.28995078 0.3607594 0.2341273 0.06602238 
> colSums(x) 
[1] 1 1 1 1 1 
11

Câu hỏi này liên quan đến các vấn đề về subtler so với ban đầu. Sau khi xem xét những điều sau đây, bạn có thể muốn suy nghĩ cẩn thận về quá trình mà bạn đang sử dụng những con số để biểu diễn:

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

+0

Đẹp, tôi đã suy nghĩ về âm mưu kết quả nhưng bạn đã làm điều này. Thật thú vị khi thấy rằng dường như không có giải pháp nào thực sự làm những gì người ta có thể thích trực quan. Nó cũng thú vị rằng trong các lô này bạn không thể thực sự thấy rằng DDZ làm điều đúng theo các phương tiện trong khi AND thậm chí không. – Christian

6

Khi bạn muốn tạo ra một cách ngẫu nhiên con số mà thêm vào 1 (hoặc một số giá trị khác) thì bạn nên xem số Dirichlet Distribution.

Có một chức năng rdirichlet trong gói gtools và chạy RSiteSearch('Dirichlet') sẽ trả về khá một vài số truy cập có thể dễ dàng dẫn bạn đến các công cụ để làm điều này (và nó không phải là khó để mã bằng tay, hoặc cho các bản phân phối Dirichlet đơn giản).

2

Vấn đề này và các giải pháp khác nhau được đề xuất hấp dẫn tôi. Tôi đã làm một bài kiểm tra nhỏ về ba thuật toán cơ bản được đề xuất và giá trị trung bình mà chúng sẽ mang lại cho các con số được tạo ra.

choose_one_and_divide_rest 
means:    [ 0.49999212 0.24982403 0.25018384] 
standard deviations: [ 0.28849948 0.22032758 0.22049302] 
time needed to fill array of size 1000000 was 26.874945879 seconds 

choose_two_points_and_use_intervals 
means:    [ 0.33301421 0.33392816 0.33305763] 
standard deviations: [ 0.23565652 0.23579615 0.23554689] 
time needed to fill array of size 1000000 was 28.8600130081 seconds 

choose_three_and_normalize 
means:    [ 0.33334531 0.33336692 0.33328777] 
standard deviations: [ 0.17964206 0.17974085 0.17968462] 
time needed to fill array of size 1000000 was 27.4301018715 seconds 

Đo thời gian sẽ được thực hiện với một hạt muối vì chúng có thể bị ảnh hưởng nhiều hơn bởi việc quản lý bộ nhớ Python so với chính thuật toán. Tôi quá lười biếng để làm điều đó đúng với timeit. Tôi đã làm điều này trên 1GHz Atom để giải thích lý do tại sao nó mất quá lâu.

Dù sao, select_one_and_divide_rest là thuật toán do Andrie đề xuất và áp phích câu hỏi của anh ta/mình (AND): bạn chọn một giá trị a [0,1], sau đó nhập [a, 1] và sau đó bạn nhìn những gì bạn đã để lại. Nó cho biết thêm một, nhưng đó là về nó, các bộ phận đầu tiên là hai lần lớn như hai người kia. Người ta có thể đoán được nhiều ...

select_two_points_and_use_intervals là câu trả lời được chấp nhận bởi ddzialak (DDZ). Phải mất hai điểm trong khoảng [0,1] và sử dụng kích thước của ba khoảng phụ được tạo bởi các điểm này dưới dạng ba số. Làm việc như một say mê và các phương tiện là tất cả 1/3.

select_three_and_normalize là giải pháp của Anders Gustafsson và Josh O'Brien (JOB). Nó chỉ tạo ra ba số trong [0,1] và bình thường hóa chúng trở lại thành một số 1. Hoạt động tốt và đáng ngạc nhiên hơn một chút trong việc thực hiện Python của tôi. Phương sai là thấp hơn một chút so với giải pháp thứ hai.

Có bạn có nó. Không có ý tưởng về những gì phân phối beta các giải pháp này tương ứng hoặc tập hợp các tham số nào trong bài báo tương ứng mà tôi đã đề cập trong một nhận xét nhưng có lẽ một người khác có thể hình dung ra điều đó.