32
votes
$\begingroup$

Most standard distributions in R have a family of commands - pdf/pmf, cdf/cmf, quantile, random deviates (for example- dnorm, pnorm, qnorm, rnorm).

I know it's easy enough to make use of some standard commands to reproduce these functions for the discrete uniform distributions, but is there already a preferred built-in family of functions for modeling discrete uniform distributions in R that I'm unaware of?

$\endgroup$
3

4 Answers 4

36
votes
$\begingroup$

As nico wrote, they're not implemented in R. Assuming we work in 1..k, those functions should look like:

For random generation:

rdu<-function(n,k) sample(1:k,n,replace=T)

PDF:

ddu<-function(x,k) ifelse(x>=1 & x<=k & round(x)==x,1/k,0) 

CDF:

pdu<-function(x,k) ifelse(x<1,0,ifelse(x<=k,floor(x)/k,1))
$\endgroup$
2
  • 5
    $\begingroup$ Thanks. I think it would be handy to have built-in functions (with min and max paraemters ala the unif family). It's a bit ugly to have to add function definitions into scripts just to use the discrete uniform distributions the way you would use other standard distributions. The builtin functions also deal with error handling (for example - if parameters aren't integers) and are optimized for speed. $\endgroup$
    – Joseph Hsieh
    Oct 25, 2010 at 0:47
  • 2
    $\begingroup$ Nice answer. And for the quantiles we can do something like qdu <- function(p, k) ifelse(p <= 0 | p > 1, return("undefined"), ceiling(p*k)) $\endgroup$
    – user1108
    Oct 25, 2010 at 15:24
17
votes
$\begingroup$

Here is the code for the discrete uniform distribution in the range [min, max], adapted from mbq's post:

dunifdisc<-function(x, min=0, max=1) ifelse(x>=min & x<=max & round(x)==x, 1/(max-min+1), 0)
punifdisc<-function(q, min=0, max=1) ifelse(q<min, 0, ifelse(q>=max, 1, (floor(q)-min+1)/(max-min+1)))
qunifdisc<-function(p, min=0, max=1) floor(p*(max-min+1))
runifdisc<-function(n, min=0, max=1) sample(min:max, n, replace=T)
$\endgroup$
15
votes
$\begingroup$

The CRAN Task View: Probability Distributions page says:

The discrete uniform distribution can be easily obtained with the basic functions.

I guess something on the lines of this should do:

a <- round(runif(1000, min=0, max=100))

EDIT

As csgillespie pointed out, this is not correct...

a <- ceiling(runif(1000, min=0, max=100))

will work though (note that the example will generate values between 1 and 100, not 0 and 100)

$\endgroup$
3
  • 5
    $\begingroup$ This isn't correct for the edge cases. To see this, try running the following command: table(round(runif(10000, min=0, max=2))) It's clearly not discrete uniform. $\endgroup$ Oct 25, 2010 at 8:30
  • $\begingroup$ @csgillespie: nicely spotted, I updated my answer :) $\endgroup$
    – nico
    Oct 25, 2010 at 8:32
  • 1
    $\begingroup$ Couldn't you use ceiling(runif(1000, min=-1, max=100))? $\endgroup$ Aug 2, 2012 at 13:26
0
votes
$\begingroup$

This function might be what you are looking for:

https://purrr.tidyverse.org/reference/rdunif.html

rdunif(n, b, a = 1)
$\endgroup$