Стандартною, потужною, добре зрозумілою, теоретично налагодженою і часто реалізованою мірою «рівномірності» є функція Ріплі К і його близький родич, функція L. Хоча вони зазвичай використовуються для оцінки двовимірних просторових конфігурацій точок, аналіз, необхідний для адаптації їх до одного виміру (який, як правило, не наведено у посиланнях), простий.
Теорія
Функція K оцінює середню частку точок на відстані від типової точки. Для рівномірного розподілу на інтервалі справжня частка може бути обчислена і (асимптотично за розміром вибірки) дорівнює . Відповідна одновимірна версія функції L віднімає це значення від K, щоб показати відхилення від однорідності. Тому ми можемо розглянути можливість нормалізації будь-якої партії даних, щоб мати одиницю діапазону, і вивчити її функцію L на відхилення навколо нуля.d[0,1]1−(1−d)2
Опрацьовані приклади
Для ілюстрації я імітував незалежних зразків розміром з рівномірного розподілу та побудував їх (нормалізовані) функції L на більш короткі відстані (від до ), створивши таким чином конверт для оцінки розподілу вибірки функції L. (Нанесені точки добре у цій оболонці не можна суттєво відрізнити від рівномірності.) На цьому я побудував L функції для зразків однакового розміру з U-подібного розподілу, розподілу суміші з чотирма очевидними компонентами та стандартного нормального розподілу. Гістограми цих зразків (та їх батьківських розподілів) показані для довідки, використовуючи символи ліній для відповідності символам L функцій.9996401/3
Гострі розділені шипи U-подібного розподілу (пунктирна червона лінія, крайня ліва гістограма) створюють скупчення близько розташованих значень. Це відображається дуже великим нахилом функції L при . Потім функція L зменшується, з часом стає негативною для відображення прогалин на проміжних відстанях.0
Вибірка з нормального розподілу (суцільна синя лінія, найправіша гістограма) досить близька до рівномірного розподілу. Відповідно, його функція L не відходить від швидко. Однак, на відстані або близько того, він піднявся достатньо вище конверта, щоб сигналізувати про незначну тенденцію до скупчення. Постійний підйом на проміжні відстані вказує на те, що кластеризація дифузна і широко поширена (не обмежується окремими піками).00.10
Початковий великий нахил вибірки з розподілу суміші (середня гістограма) виявляє кластеризацію на невеликих відстанях (менше ). Опускаючись до негативних рівнів, він сигналізує про поділ на проміжні відстані. Порівнюючи це з U-подібною функцією розподілу L виявляється: нахили на , величини, на які ці криві піднімаються вище , і швидкості, з якими вони в кінцевому підсумку опускаються назад до надають інформацію про характер кластеризації, присутній у дані. Будь-яка з цих характеристик може бути обрана як єдиний показник «рівномірності» відповідно до конкретного застосування.0.15000
Ці приклади показують, як L-функцію можна досліджувати для оцінки відхилень даних від однорідності ("рівномірності") та як кількісна інформація про масштаб та характер відхилень може бути витягнута з неї.
(Дійсно можна побудувати всю функцію L, поширюючись на повну нормовану відстань , для оцінки масштабних відступів від однорідності. Однак, як правило, велике значення має оцінка поведінки даних на менших відстанях.)1
Програмне забезпечення
R
Код для створення цієї цифри наступним чином. Він починається з визначення функцій для обчислення K і L. Це створює можливість імітувати з розподілу суміші. Потім він генерує змодельовані дані та робить графіки.
Ripley.K <- function(x, scale) {
# Arguments:
# x is an array of data.
# scale (not actually used) is an option to rescale the data.
#
# Return value:
# A function that calculates Ripley's K for any value between 0 and 1 (or `scale`).
#
x.pairs <- outer(x, x, function(a,b) abs(a-b)) # All pairwise distances
x.pairs <- x.pairs[lower.tri(x.pairs)] # Distances between distinct pairs
if(missing(scale)) scale <- diff(range(x.pairs))# Rescale distances to [0,1]
x.pairs <- x.pairs / scale
#
# The built-in `ecdf` function returns the proportion of values in `x.pairs` that
# are less than or equal to its argument.
#
return (ecdf(x.pairs))
}
#
# The one-dimensional L function.
# It merely subtracts 1 - (1-y)^2 from `Ripley.K(x)(y)`.
# Its argument `x` is an array of data values.
#
Ripley.L <- function(x) {function(y) Ripley.K(x)(y) - 1 + (1-y)^2}
#-------------------------------------------------------------------------------#
set.seed(17)
#
# Create mixtures of random variables.
#
rmixture <- function(n, p=1, f=list(runif), factor=10) {
q <- ceiling(factor * abs(p) * n / sum(abs(p)))
x <- as.vector(unlist(mapply(function(y,f) f(y), q, f)))
sample(x, n)
}
dmixture <- function(x, p=1, f=list(dunif)) {
z <- matrix(unlist(sapply(f, function(g) g(x))), ncol=length(f))
z %*% (abs(p) / sum(abs(p)))
}
p <- rep(1, 4)
fg <- lapply(p, function(q) {
v <- runif(1,0,30)
list(function(n) rnorm(n,v), function(x) dnorm(x,v), v)
})
f <- lapply(fg, function(u) u[[1]]) # For random sampling
g <- lapply(fg, function(u) u[[2]]) # The distribution functions
v <- sapply(fg, function(u) u[[3]]) # The parameters (for reference)
#-------------------------------------------------------------------------------#
#
# Study the L function.
#
n <- 64 # Sample size
alpha <- beta <- 0.2 # Beta distribution parameters
layout(matrix(c(rep(1,3), 3, 4, 2), 2, 3, byrow=TRUE), heights=c(0.6, 0.4))
#
# Display the L functions over an envelope for the uniform distribution.
#
plot(c(0,1/3), c(-1/8,1/6), type="n",
xlab="Normalized Distance", ylab="Total Proportion",
main="Ripley L Functions")
invisible(replicate(999, {
plot(Ripley.L(x.unif <- runif(n)), col="#00000010", add=TRUE)
}))
abline(h=0, lwd=2, col="White")
#
# Each of these lines generates a random set of `n` data according to a specified
# distribution, calls `Ripley.L`, and plots its values.
#
plot(Ripley.L(x.norm <- rnorm(n)), col="Blue", lwd=2, add=TRUE)
plot(Ripley.L(x.beta <- rbeta(n, alpha, beta)), col="Red", lwd=2, lty=2, add=TRUE)
plot(Ripley.L(x.mixture <- rmixture(n, p, f)), col="Green", lwd=2, lty=3, add=TRUE)
#
# Display the histograms.
#
n.breaks <- 24
h <- hist(x.norm, main="Normal Sample", breaks=n.breaks, xlab="Value")
curve(dnorm(x)*n*mean(diff(h$breaks)), add=TRUE, lwd=2, col="Blue")
h <- hist(x.beta, main=paste0("Beta(", alpha, ",", beta, ") Sample"),
breaks=n.breaks, xlab="Value")
curve(dbeta(x, alpha, beta)*n*mean(diff(h$breaks)), add=TRUE, lwd=2, lty=2, col="Red")
h <- hist(x.mixture, main="Mixture Sample", breaks=n.breaks, xlab="Value")
curve(dmixture(x, p, g)*n*mean(diff(h$breaks)), add=TRUE, lwd=2, lty=3, col="Green")