我模拟了以 50 为中心的正态分布中的数字,然后仅将数字保留在 0 到 100 之间:
mean <- 50
sd <- 15
n <- 100000
set.seed(123)
numbers <- rnorm(n, mean, sd)
numbers <- pmax(0, pmin(numbers, 100))
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,结果看起来像钟形曲线:
然后,我想看看每个单位间隔之间的数字百分比是多少:
min_interval <- seq(0, 99, by = 1)
max_interval <- seq(1, 100, by = 1)
count <- sapply(min_interval, function(x) {
sum(numbers >= x & numbers < (x + 1))
})
percentage <- count / length(numbers) * 100
df <- data.frame(min_interval = min_interval,
max_interval = max_interval,
count = count,
percentage = percentage)
Run Code Online (Sandbox Code Playgroud)
结果看起来像这样:
library(dplyr)
df %>% arrange(desc(percentage))
min_interval max_interval count percentage
1 50 51 2714 2.714
2 48 49 2632 2.632
3 49 50 2628 2.628
4 52 53 2626 2.626
5 47 48 2615 2.615
#> sum(df$percentage)
#[1] 99.957
Run Code Online (Sandbox Code Playgroud)
我的问题:假设我想对此结果表 (df) 进行以下更改,以便:
如何重新计算百分比列以满足这些条件?可以为这个问题写一个通用的函数吗?(例如输入您想要的约束,优化算法会找到相应的钟形曲线)
相关问题
很高兴您使用模拟来学习统计数据,这是一种有趣的学习方式。
该函数pnorm告诉您正态分布(有时也称为“钟形曲线”)低于某个值的比例。您可以通过计算两点之间的值的差值来找到正态分布的比例pnorm。例如,根据您的参数,49 到 50 之间的预期比例是
pnorm(50,mean=50, sd=15) - pnorm(49, mean=50, sd=15)
# 0.02657646
Run Code Online (Sandbox Code Playgroud)
或大约 2.657%,与模拟的 2.628% 相差不远。
要找到此范围内 5% 的正态分布,您可以创建一个函数来表示范围内的比例
f1 <- function(x) {
pnorm(50,mean=50,sd=x) - pnorm(49, mean=50, sd=x)
}
plot(x <- seq(0,10,len=100),f1(x), type="l")
# horizontal line at 0.05, or 5%
abline(0.05,0)
Run Code Online (Sandbox Code Playgroud)
所以你无法挑选出该房产所在的地块。
如果你想解决这个问题,请使用optimize找到该交叉发生的位置。交叉点f1(x) - 0.05为零时,因此定义f2为
f2 <- function(x) {
abs(f1(x) - 0.05)
}
Run Code Online (Sandbox Code Playgroud)
绝对值允许我们在唯一解处最小化函数
optimize(lower=5,upper=10,f=f2)
# $minimum
# [1] 7.957901
#
# $objective
# [1] 3.038535e-08
Run Code Online (Sandbox Code Playgroud)
这表明,如果将标准差设置为 7.956,则应该得到 49 到 50 之间分布的大约 5%。