0

I want to generate some random numbers, that is for such distribution:

  • 10% of them are in Category A (T = 6),
  • 40% of them are in Category B (T = 8),
  • 40% of them are in Category C (T = 10),
  • 10% of them are in Category D (T = 12).

I just started to learn MATLAB and I tried rand(x) and randn(x) but it seems neither of them can do that?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • 1
    I believe the linked question is a duplicate, with a variety of solutions for your problem. Please say why if you believe this isn't the case. – Wolfie Nov 06 '19 at 08:39
  • I think [this thread](https://stackoverflow.com/q/58607156/8239061) provides a superior answer from @LuisMendo than the [currently linked dupe target](https://stackoverflow.com/q/13914066/8239061). – SecretAgentMan Nov 06 '19 at 14:04
  • 1
    @SecretAgentMan: added that dupe. – Cris Luengo Nov 06 '19 at 14:12

1 Answers1

1

You'll have to set up some kind of mapping from the uniformly distributed random numbers you get from rand to your desired values, i.e. with respect to the wanted distribution.

In my solution, I generate random numbers using rand, and map them to integers 1, 2, 3, 4 as well as to (categorical) characters A, B, C, D. I built a whole function to support variable amount of input arguments to mimic the behaviour of rand.

That's the code of the myRand function:

function [rn, in, ch] = myRand(varargin)

  % No input arguments.
  if (numel(varargin) == 0)  
    rn = rand();

  % One input argument; might be a scalar or an array.
  elseif (numel(varargin) == 1)
    a = varargin{1};
    if (!isnumeric(a))
      error('myRand: argument must be numeric');
    end
    rn = rand(a);

  % More than one input argument; must be scalars.
  elseif (numel(varargin) > 1)
    if (!all(cellfun(@(x)isnumeric(x), varargin)))
      error('myRand: arguments must be numeric');  
    end
    if (!all(cellfun(@(x)isscalar(x), varargin)))
      error('myRand: arguments must be scalar');  
    end
    rn = rand(varargin{:});

  end

  in = zeros(size(rn));
  in((0 <= rn) & (rn < 0.1)) = 1;
  in((0.1 <= rn) & (rn < 0.5)) = 2;
  in((0.5 <= rn) & (rn < 0.9)) = 3;
  in((0.9 <= rn) & (rn < 1)) = 4;

  ch = cell(size(rn));  
  ch((0 <= rn) & (rn < 0.1)) = { 'A' };
  ch((0.1 <= rn) & (rn < 0.5)) = { 'B' };
  ch((0.5 <= rn) & (rn < 0.9)) = { 'C' };
  ch((0.9 <= rn) & (rn < 1)) = { 'D' };

end

And, here's some test code with the corresponding outputs:

% Single random number with integer and category
[rn, in, ch] = myRand()

% Multiple random numbers with integers and categories (array input)
[rn, in, ch] = myRand([2, 3])

% Multiple random numbers with integers and categories (multiple scalars input)
[rn, in, ch] = myRand(2, 3)


rn =  0.19904
in =  2
ch =
{
  [1,1] = B
}

rn =
   0.206294   0.420426   0.835194
   0.793874   0.593371   0.034055

in =
   2   2   3
   3   3   1

ch =
{
  [1,1] = B
  [2,1] = C
  [1,2] = B
  [2,2] = C
  [1,3] = C
  [2,3] = A
}

rn =
   0.96223   0.87840   0.49925
   0.54890   0.88436   0.92096

in =
   4   3   2
   3   3   4

ch =
{
  [1,1] = D
  [2,1] = C
  [1,2] = C
  [2,2] = C
  [1,3] = B
  [2,3] = D
}

Hope that helps!

Disclaimer: I tested the code with Octave 5.1.0, but I'm quite sure, that it should be fully MATLAB-compatible. If not, please leave a comment, and I'll try to fix possible issues.

HansHirse
  • 18,010
  • 10
  • 38
  • 67
  • Thank you very much! I tried it in MATLAB, and error happened in line 'ch((0 <= rn) & (rn < 0.1)) = 'A';' saying that Conversion to cell from char is not possible. –  Nov 06 '19 at 08:58
  • @Bobet I edited my answer, please try again. The characters are now explicitly put into a cell. – HansHirse Nov 06 '19 at 12:17