生成0和1范围内的正态分布数据

时间:2013-11-03 22:14:01

标签: r

我正在研究关于收入分配的项目......我想生成用于测试理论的随机数据。假设我有N = 5个国家,每个国家有n = 1000人口,我想为每个人口中的每个人产生随机收入(正态分布),收入约束在0到1之间,并且在相同的平均值和不同的标准所有国家的偏差。我使用函数rnorm(n,meanx,sd)来完成它。我知道UNIFORM DISTRIBUTION(runif(n,min,max)有一些设置min,max但没有rnorm的参数。因为rnorm没有提供设置min和max值的参数。我必须编写一段代码检查随机数据集,看它们是否满足我的约束[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)
}

3 个答案:

答案 0 :(得分:6)

这是一个明智的简单方法......

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)

答案 1 :(得分: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)

答案 2 :(得分:1)

这是我的看法。

首先将数据标准化(在哪个阶段标准偏差丢失)。之后,它适合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(test = (is.na(mean)|| (mean < lower) || (mean > upper)),
                  yes = mean(c(lower, upper)),
                  no = mean)
    data <- rnorm(n, mean = mean, 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)
}

示例:

a <- rtnorm(n = 1000, lower = 10, upper = 90)
range(a)
plot(hist(a, 50))

enter image description here