Search code examples
graphstata

Random Dots on a Circle


Is there a way to randomly scatter a pre-defined number of dots on a circle? The example below randomly scatters dots on a square but I need the area to be a circle.

clear
set seed 101010
set obs 225           // There should be 225 dots on the circle. 
gen x1 = runiform()
gen y1 = runiform()

twoway  (scatter x1 y1 ///
        , graphregion(color(white)) xtitle("") ytitle("") ///
        yscale(lstyle(none)) xscale(lstyle(none)) ///
        ylabel(none, nolabels noticks nogrid) xlabel(none, nolabels noticks nogrid))

Edit The code below outlines a possible solution but the dots are not distributed evenly across the area. Since this is most visible when there is a large number of dots, the code below generates 10000 observations.

Any idea how to make the dots evenly distributed across the area?

clear 
set obs 10000
gen obs = _n
gen N = _N
gen y = runiform()
gen angle = obs * 2 * _pi / N

gen obsx = y * cos(angle)
gen obsy = y * sin(angle)

twoway scatter obsx obsy, msize(tiny) graphregion(color(white)) xtitle("") ytitle("") ///
            yscale(lstyle(none)) xscale(lstyle(none)) ysize(1) xsize(1) ///
            ylabel(none, nolabels noticks nogrid) xlabel(none, nolabels noticks nogrid)  


Solution

  • Here is an answer that 1) generalizes for any bounding radius (which may not be useful for you); and 2) abstracts away from explicitly using N.

    
    clear 
    set seed 101010
    set obs 250
    gen obs = _n
    scalar R = 1 // set the  bounding radius
    gen y = R * sqrt(runiform()) // random "sub" radius
    gen angle = runiform() * 2 * _pi
    
    gen obsx = y * cos(angle)
    gen obsy = y * sin(angle)
    
    twoway scatter obsx obsy, msize(tiny) graphregion(color(white)) xtitle("") ytitle("") ///
                yscale(lstyle(none)) xscale(lstyle(none)) ysize(1) xsize(1) ///
                ylabel(none, nolabels noticks nogrid) xlabel(none, nolabels noticks nogrid)