Cómo calcular la estadística de Kolmogorov-Smirnov entre dos muestras ponderadas

Digamos que tenemos dos muestras data1 y data2 con sus respectivos pesos weight2 y weight2 y que queremos calcular el estadístico de Kolmogorov-Smirnov entre las dos muestras ponderadas.

La forma en que lo hacemos en python sigue:

 def ks_w(data1,data2,wei1,wei2): ix1=np.argsort(data1) ix2=np.argsort(data2) wei1=wei1[ix1] wei2=wei2[ix2] data1=data1[ix1] data2=data2[ix2] d=0. fn1=0. fn2=0. j1=0 j2=0 j1w=0. j2w=0. while(j1<len(data1))&(j2<len(data2)): d1=data1[j1] d2=data2[j2] w1=wei1[j1] w2=wei2[j2] if d1<=d2: j1+=1 j1w+=w1 fn1=(j1w)/sum(wei1) if d2d: d=abs(fn2-fn1) return d 

donde simplemente modificamos para nuestro propósito la estadística KS clásica de dos muestras implementada en Press, Flannery, Teukolsky, Vetterling – Recetas numéricas en C – Cambridge University Press – 1992 – pag.626 .

Nuestras preguntas son:

  • ¿Alguien es consciente de alguna otra forma de hacerlo?
  • ¿hay alguna biblioteca en python / R / * que lo realice?
  • que hay de la prueba ¿Existe o deberíamos usar un procedimiento de reorganización para evaluar la estadística?

Al estudiar el código scipy.stats.ks_2samp , pudimos encontrar una solución Python más eficiente. Compartimos a continuación en caso de que alguien esté interesado:

 from __future__ import division # (for python 2/3 support) import numpy as np def ks_w2(data1, data2, wei1, wei2): ix1 = np.argsort(data1) ix2 = np.argsort(data2) data1 = data1[ix1] data2 = data2[ix2] wei1 = wei1[ix1] wei2 = wei2[ix2] data = np.concatenate([data1, data2]) cwei1 = np.hstack([0, np.cumsum(wei1)/sum(wei1)]) cwei2 = np.hstack([0, np.cumsum(wei2)/sum(wei2)]) cdf1we = cwei1[[np.searchsorted(data1, data, side='right')]] cdf2we = cwei2[[np.searchsorted(data2, data, side='right')]] return np.max(np.abs(cdf1we - cdf2we)) 

Para evaluar el desempeño realizamos la siguiente prueba:

 ds1 = random.rand(10000) ds2 = random.randn(40000) + .2 we1 = random.rand(10000) + 1. we2 = random.rand(40000) + 1. 

ks_w2(ds1, ds2, we1, we2) tomó 11.7 ms en nuestra máquina, mientras que ks_w(ds1, ds2, we1, we2) tomó 1.43s