How can I generate uniformly distributed points on a circle?

I am looking to generate 450 data points in R. There are three distinct sets 150 of each distributed in a circular band with different radii (at 1, 2.8 and 5).

In particular, I'm looking to reproduce the first graph on p546 of The Elements of Statistical Learning.

I would be very grateful for some assistance in the R code that could generate this data.

Thanks!

• See e.g. Lovisolo, da Silva. Uniform distribution of points on a hyper-sphere with applications to vector bit-plane encoding. There is no ready code in the article, but the algorithm. If you can't find the pdf, drop me e-mail. – ttnphns Dec 10 '13 at 8:24
• Generating points uniformly on a sphere is described at stats.stackexchange.com/questions/7977/…; the method generalizes directly to all other dimensions. But the title of this question appears to have little or nothing to do with the question itself, which asks for a uniform distribution on the circle together with additive "Gaussian noise" in the radial direction. I have therefore edited the title to change "hypersphere" to "circle." – whuber Dec 10 '13 at 15:25

1 Answer

In the case of a circle, it suffices to generate a uniform angle, $\theta$, on $[0,2\pi)$ and then make the radius, $r$, whatever is desired. If you want Cartesian, rather than polar co-ordinates, $x=r\cos\theta$ and $y=r\sin\theta$.

One really easy way to generate random points from a uniform distribution a d-sphere (a hypersphere in a space of arbitrary dimension $d+1$, with surface of dimension $d$), is to generate multivariate standard normals $X_i\sim N_{d+1}(0,I)$, and then scale by their distance from the origin:

$$Y_i=X_i/||X_i||\,,$$

where $||.||$ is the Euclidean norm.

In R, let's generate on the surface of a (2-)sphere:

x <- matrix(rnorm(300),nc=3)
y <- x/sqrt(rowSums(x^2))
head(y)
[,1]        [,2]       [,3]
[1,]  0.9989826 -0.03752732 0.02500752
[2,] -0.1740810  0.08668104 0.98090887
[3,] -0.7121632 -0.70011994 0.05153283
[4,] -0.5843537 -0.49940138 0.63963192
[5,] -0.7059208  0.20506946 0.67795451
[6,] -0.6244425 -0.70917197 0.32733262

head(rowSums(y^2))
[1] 1 1 1 1 1 1


Here's that data from two slightly different angles:

You can then scale to whatever other radius you like.

In low dimensions, there are faster ways, but if your normal random number generator is reasonably fast, it's pretty good in higher dimensions.

There are several packages on CRAN for circular statistics, including CircStats and circular. There's probably something on CRAN that generates uniform distributions on n-spheres for n>1, but I don't know of it.

• This is the first step of the approach that is used in the article I refer to in my comment above. The authors use 3 stages: 1) generate very many normal datapoints and rescale them to a unit radius; 2) use k-means clustering to replace the many points to the k poins you need to tile the hypersphere, the tiling is close to uniform so far; 3) apply the special shift to each point to arrive at almost exact uniformity. I once coded that algorithm, but in SPSS, not in R. – ttnphns Dec 10 '13 at 9:39
• I think steps 2 and 3 are useful when you want to generate a good mesh on the sphere, but not for random points generation... [ @Glen_b nice answer! ] – Elvis Dec 10 '13 at 9:44
• @ttnphns I took the question to be asking about points having a uniform distribution over the surface, rather than something where the points are close to evenly spaced. – Glen_b Dec 10 '13 at 9:46
• But I understood that the OP asked for this: really uniform, regular, evenly spaced tiling. Random data are far from being really uniform. – ttnphns Dec 10 '13 at 9:47
• Yes, of course. For disambiguation, it is always wise to say "coming from uniform/normal" distribution instead of dubious "having uniform/normal" distribution. – ttnphns Dec 10 '13 at 10:01