Following whuber's advice I checked the methods for edge effects correction:
none
:
this method does not take into account any edge effects whatsoever.
translation
:
computes the intersection of rectangular areas centered at the given points provided the upper bounds of the dimensions of the rectangular area of study. It assumes that all the points lie in a bounded rectangular region satisfying x_min < x_i < x_max; y_min < y_i < y_max. A detailed description of this method can be found on ref [4].
ohser
:
this method uses the isotropized set covariance function of the window of study as a weight to correct for edge-effects. A detailed description of this method can be found on ref [4].
var-width
:
this method considers the distance of each observed point to the nearest boundary of the study window as a factor to account for edge-effects. See [3] for a brief description of this method.
ripley
:
this method is known as Ripley’s edge-corrected estimator. The weight for edge-correction is a function of the proportions of circumferences centered at each data point which crosses another data point of interest. See [3] for a detailed description of this method.
His intuition was right, apparently the problem is with the default none
method which does not take into account edge effects. All the other (except var-width
where I'm not sure what's going on) give results much closer to what I was expecting:
>>> Kest = RipleysKEstimator(area=1, x_max=1, y_max=1, x_min=0, y_min=0)
>>> xy=np.random.uniform(0., 1., (1000, 2))
>>> Kest(data=xy, radii=(.5,), mode='none')
array([0.48910911])
>>> Kest(data=xy, radii=(.5,), mode='translation')
array([0.79486786])
>>> Kest(data=xy, radii=(.5,), mode='ohser')
array([0.79475738])
>>> Kest(data=xy, radii=(.5,), mode='var-width')
array([0.])
>>> Kest(data=xy, radii=(.5,), mode='ripley')
array([0.79369159])
Kest
deals with the edge effects? That alone could explain the difference, because $r=0.5$ is such a large fraction of the diameter of this region. $\endgroup$