Create a list of n (strictly positive) values ​​so that the list has predefined values ​​of x and std. deviation Y

I would like to generate a list of n strictly positive values, so that the list has a given mean and standard deviation (may be close / inaccurate). I used uniform distribution equations for mathematical expectation and variance and solutions for "a" and "b", but the system of equations (for a particular average and std. Dev. I wanted) did not have solutions for a, b> = 0 I was wondering Is there a plug-and-chug way to do this in any programming language, but hopefully in Python. Thank!

Ex: generate a list of 84 positive values ​​with an average value = = 60/84 = 0.71, std.dev. ~ = 1.7

+3
source share
4 answers

Answer

Use NumPy to create gamma samples with a scale parameter. theta = variance / mean and form parameter k = mean / theta.

Example

>> import numpy

>> mu = 0.71
>> var = 1.7**2 
>> theta = var / mean 
>> k = mu / theta

>> samples = numpy.random.gamma(k, theta, 1000)

>> numpy.mean(samples)
0.71622189354608201

>> numpy.std(samples) 
1.7865898752966483

Comment

, , . , , . , , , . . , , -. . .

k > 0 theta > 0, -

+1

() a b. :

mean = (a + b)/2

var = (b - a) ^ 2/12

- sqrt (var). (, , ), a b:

a = mean - sqrt (3 * var)

b = mean + sqrt (3 * var)

, , n [a, b]. Python:

#!/usr/bin/env python2.7
from math import sqrt


def uniform(mean, std, n):
    a = mean - sqrt(3.) * std
    b = mean + sqrt(3.) * std
    xs = [(b - a) * (i / (n - 1.)) + a for i in range(n)]
    return xs


for target_mean, target_std, n in [(10, 1, 100),
                                   (0.71, 1.7, 84)]:
    xs = uniform(target_mean, target_std, n)
    print xs

    mean = 1. * sum(xs) / n
    var = sum([(x - mean)**2 / n for x in xs])

    print 'mean: {} ({})'.format(mean, target_mean)
    print 'std: {} ({})'.format(sqrt(var), target_std)

    if not min(xs) > 0:
        print 'WARNING: but this is not strictly positive'

    print

, , . - , . , , . , .

, , , , , .

+1

, . , ,

x1, x2,..., mean,..., xn

mi = sum (x_i)/n

:

dev < xmax - , dev < mean - xmin. , - - (max of ( mean - xmin, xmax - mean)) ?

, , max of [ mean - xmin, xmax - mean], . :

  • (0, min of[ mean - xmin, xmax - mean])

  • (0, max of[ mean - xmin, xmax - mean]), (0, min of[ mean - xmin, xmax - mean]), ( , )


(0, min of[ mean - xmin, xmax - mean])

, mi d [xmin, xmax].

x1 = mi - d, x2 = mi + d

mi d.

#include <boost/random.hpp>
#include <boost/random/bernoulli_distribution.hpp>

double generate_from_bernoulli_distribution(double mi, double d,
                                                        double a, double b) {
    if (b <= a || d < 0) throw std::out_of_range( "invalid parameters");
    if (d > std::min(mi - a, b - mi)) throw std::out_of_range( " invalid
                                                         standard deviation");
    double x1 = mi - d, x2 = mi + d;
    boost::mt19937 rng; // I don't seed it on purpouse (it not relevant)
    boost::bernoulli_distribution<> bd;
    boost::variate_generator<boost::mt19937&,
            boost::bernoulli_distribution<> > var_ber( rng, bd);
    double bernoulli = var_ber();
    return ( x1 + bernoulli * 2 * d); // return x1 on 0, or x2 on 1
}

void generate_n_from_bernoulli_distribution( double mi, double d, double a, 
                                   double b, std::vector<double>& res, int n) {
    if (b <= a || d < 0) throw std::out_of_range( "invalid parameters");
    if (d > std::min(mi - a, b - mi)) throw std::out_of_range( " invalid
                                                          standard deviation");
    double x1 = mi - d, x2 = mi + d;

    boost::mt19937 rng; // I don't seed it on purpouse (it not relevant)
    boost::bernoulli_distribution<> bd;
    boost::variate_generator<boost::mt19937&,
            boost::bernoulli_distribution<> > var_ber( rng, bd);

    int i = 0;
    for (; i < n; ++i) {
        double bernoulli = var_ber();
        res.push_back( x1 + bernoulli * 2 * d); // push_back x1 on 0, or x2 on 1
    }
}

:

/*
 * 
 */
int main()
{
  double rc = generate_from_bernoulli_distribution( 4, 1, 0, 10);
  std::vector<double> sample;
  generate_n_from_bernoulli_distribution( 4, 1, 0, 10, sample, 100);
  return 0;
}

, - , . , , .


( ) [a, b]

enter image description here

enter image description here

a = mi -  b = mi + alpha  alpha -

, , mi. . a, b:

enter image description here

enter image description here

/**
 * generates intervals for a uniform distribution
 * with a given mean and deviation
 * @param mi    mean
 * @param d     deviation
 * @param a     left bound
 * @param b     right bound
 * @return 
 */
void uniform_distribution_intervals( double mi, double d, double& a, double& b) {
    a = mi - d * std::sqrt(3.0);
    b = mi + d * std::sqrt(3.0);
}

, mi, d, .

uniform_distribution_intervals (60/84, 1.7, a, b);

a = -2.9444863728670914, b = 2.9444863728670914.


, (0, max of[ mean - xmin, xmax - mean]), (0, min of[ mean - xmin, xmax - mean])

0

, " " " " ( ). , M=mean+var^2/mean , , - M. , . : M=4.78, 12 M 68 .001 mean=.718 std.dev.=1.71. 0 M.

0

Source: https://habr.com/ru/post/1537179/


All Articles