2013-11-03 76 views
1

我正在研究關於收入分配的項目...我想生成用於測試理論的隨機數據。假設我有N = 5個國家,每個國家有1000個人口,我想爲每個人口在每個人口中產生隨機收入(正態分佈),收入約束在0和1之間,並且具有相同的均值和不同的標準所有國家的偏差。我用函數rnorm(n,meanx,sd)來完成它。我知道UNIFORM DISTRIBUTION(runif(n,min,max))有一些設置min,max,但沒有rnorm的參數,因爲rnorm沒有提供設置min和max值的參數,所以我必須寫一段代碼檢查一組隨機數據,看它們是否滿足我[0,1]的約束條件在範圍0和1內生成正態分佈數據

我成功生成了n = 100的收入數據,但是如果我增加n = k的100次,例如,n = 200,300 ...... 1000,我的程序掛起了,我可以看到程序掛起的原因,因爲它只是隨機生成數據而沒有min,max的限制因此,當我使用更大的n ,我將成功生成的概率小於n = 100,並且循環再次運行:生成數據,檢查失敗

從技術上講,爲了解決這個問題,我想把n = 1000分成小批量,比方說b = 100。由於rnorm成功生成範圍爲[0,1]範圍內的100個樣本,並且它是正態分佈,所以如果我爲100個樣本的每個批次分別運行10次10​​0個樣本的循環,它將工作得很好。然後,我會將10 * 100個樣本的所有數據收集到一個1000的數據中,供我以後分析。 然而,在數學上言語,我不確定n = 1000的正態分佈的約束是否仍然滿足或不這樣做。我在這裏附上我的代碼。希望我的解釋對你很清楚。所有的意見對我的工作都非常有用。非常感謝。

# Update: 
# plot histogram 
# create the random data with same mean, different standard deviation and x in range [0,1] 

# Generate the output file 
# Generate data for K countries 
#--------------------------------------------- 
# Configurable variables 
number_of_populations = 5 
n=100 #number of residents (*** input the number whish is k times of 100) 
meanx = 0.7 
sd_constant = 0.1 # sd = sd_constant + j/50 

min=0 #min income 
max=1 #max income 

#--------------------------------------------- 
batch =100 # divide the large number of residents into small batch of 100 

x= matrix(
    0,       # the data elements 
    nrow=n,      # number of rows 
    ncol=number_of_populations, # number of columns 
    byrow = TRUE)     # fill matrix by rows 

x_temp = rep(0,n) 
# generate income data randomly for each country 
for (j in 1:number_of_populations){ 
    # 1. Generate uniform distribution 
    #x[,j] <- runif(n,min, max) 
    # 2. Generate Normal distribution 
    sd = sd_constant+j/50 

    repeat 
    { 
{ 
    x_temp <- rnorm(n, meanx, sd) 
    is_inside = TRUE 
    for (i in 1:n){ 
    if (x_temp[i]<min || x_temp[i] >max) { 
     is_inside = FALSE 
     break 
    } 
    } 
} 
if(is_inside==TRUE) {break} 
    } #end repeat 

    x[,j] <- x_temp 

} 


# write in csv 
# each column stores different income of its residents 
working_dir= "D:\\dataset\\" 
setwd(working_dir) 

file_output = "random_income.csv" 
sink(file_output) 

write.table(x,file=file_output,sep=",", col.names = F, row.names = F) 
sink() 
file.show(file_output) #show the file in directory 

#plot histogram of x for each population 
#par(mfrow=c(3,3), oma=c(0,0,0,0,0)) 
attach(mtcars) 
par(mfrow=c(1,5)) 
for (j in 1:number_of_populations) 
{ 
    #plot(X[,i],y,'xlab'=i) 
    hist(x[,j],main="Normal",'xlab'=j) 
} 
+0

如果你想要一個正態分佈,它不能像你描述的那樣有界。你想要發生的值落在[0,1]之外? – Thomas

+0

嗨,托馬斯,我希望我的分析有效數據落在[0,1]。如果數據不符合約束,我根本無法使用它。 –

+0

也許[此帖](http:// stackoverflow。com/questions/19343133/setting-upper-and-lower-limits-in-rnorm)幫助 –

回答

4

可以標準化數據:

x = rnorm(100) 

# normalize 
min.x = min(x) 
max.x = max(x) 

x.norm = (x - min.x)/(max.x - min.x) 
print(x.norm) 
+0

是的,但由於'x'中的數據是正態分佈的,因爲樣本量越大'min.x'和' max.x'朝向無限。 OP需要定義*他們希望他們的數據受到限制。 – Marius

+0

嗨費爾南多,很酷!只是非常簡單的代碼行,你做到了。非常感謝朋友。你幫了我很多! –

+0

這改變了數據的標準偏差,從'sd'到'sd /(max.x - min.x)'。你確定你想要發生? –

4

這裏是一個明智的簡單方法...

sampnorm01 <- function(n) qnorm(runif(n,min=pnorm(0),max=pnorm(1))) 

測試出來:

mysamp <- sampnorm01(1e5) 
hist(mysamp) 

感謝@PatrickPerry,這裏是一個廣義的截斷法線,再次使用反CDF方法。它允許正常和不同截斷邊界上的不同參數。

rtnorm <- function(n, mean = 0, sd = 1, min = 0, max = 1) { 
    bounds <- pnorm(c(min, max), mean, sd) 
    u <- runif(n, bounds[1], bounds[2]) 
    qnorm(u, mean, sd) 
} 

測試出來:

mysamp <- rtnorm(1e5, .7, .2) 
hist(mysamp) 
+0

@PatrickPerry感謝您的編輯!我改變了它以保留兩個版本,希望人們能更好地看到你的工作方式。我也用散文寫了它,而不是評論......只是我的文體偏好。 – Frank

0

這是我拿就可以了。

數據首先被標準化(標準偏差在哪個階段丟失)。之後,它被安裝在參數lowerupper指定的範圍內。

#' Creates a random normal distribution within the specified bounds 
#' 
#' WARNING: This function does not preserve the standard deviation 
#' @param n The number of values to be generated 
#' @param mean The mean of the distribution 
#' @param sd The standard deviation of the distribution 
#' @param lower The lower limit of the distribution 
#' @param upper The upper limit of the distribution 
rtnorm <- function(n, mean=0, sd=1, lower=-1, upper=1){ 
    mean = ifelse(is.na(mean)|| mean < lower || mean > upper, 
       mean(c(lower, upper)), mean) 
    data <- rnorm(n, mean=m, sd=sd) # data 

    if (!is.na(lower) && !is.na(upper)){ # adjust data to specified range 
    drange <- range(data)   # data range 
    irange <- range(lower, upper) # input range 
    data <- (data - drange[1])/(drange[2] - drange[1]) # normalize data (make it 0 to 1) 
    data <- (data * (irange[2] - irange[1]))+irange[1] # adjust to specified range 
    } 
    return(data) 
} 
相關問題