2016-08-11 13 views
5

Próbuję zrozumieć, co się dzieje z moimi obliczeniami odległości Canberra. Piszę własną prostą funkcję canberra.distance, jednak wyniki nie są zgodne z funkcją dist. Dodałem do mojej funkcji opcję na.rm = T, aby móc obliczyć sumę, gdy występuje zerowy mianownik. Od ?dist Rozumiem, że używają podobnego podejścia: Terms with zero numerator and denominator are omitted from the sum and treated as if the values were missing.odległość canberry - niespójne wyniki

canberra.distance <- function(a, b){ 
    sum((abs(a - b))/(abs(a) + abs(b)), na.rm = T) 
} 

a <- c(0, 1, 0, 0, 1) 
b <- c(1, 0, 1, 0, 1) 
canberra.distance(a, b) 
> 3 
# the result that I expected 
dist(rbind(a, b), method = "canberra") 
> 3.75 


a <- c(0, 1, 0, 0) 
b <- c(1, 0, 1, 0) 
canberra.distance(a, b) 
> 3 
# the result that I expected 
dist(rbind(a, b), method = "canberra") 
> 4 

a <- c(0, 1, 0) 
b <- c(1, 0, 1) 
canberra.distance(a, b) 
> 3 
dist(rbind(a, b), method = "canberra") 
> 3 
# now the results are the same 

Pary 0-0 i 1-1 wydaje się być problematyczne. W pierwszym przypadku (0-0) licznik i mianownik są równe zeru i tę parę należy pominąć. W drugim przypadku (1-1) licznik wynosi 0, ale nie jest to mianownik, a termin jest równy 0, a suma nie powinna się zmieniać.

Czego mi tu brakuje?

Edycja: Aby zgodne z definicją R funkcja canberra.distance może być modyfikowany w następujący sposób:

canberra.distance <- function(a, b){ 
    sum(abs(a - b)/abs(a + b), na.rm = T) 
} 

Jednakże, wyniki są takie same jak poprzednio.

+2

Myślę, że mogłeś się natknąć na błąd w bazie R. Nie jestem pewien, ale [Wolfram Alpha zgadza się z tobą] (https://www.wolframalpha.com/input/?i=CanberraDistance%5B% 7B1, + 0, + 1, + 0% 7D, +% 7B0, + 1, + 0, + 0% 7D% 5D). Niestety nie mogę znaleźć autorytatywnego odnośnika, ale twoja implementacja wydaje się poprawna zgodnie z Wikipedią i Wolfram. –

+0

W rzeczywistości [dokumentacja 'dist'] (https://stat.ethz.ch/R-manual/R-devel/library/stats/html/dist.html) określa odległość Canberra jako * sum (| x_i - y_i |/| x_i + y_i |) * (co różni się od twojego i Wolframa). Zauważa również, że "[t] jego jest przeznaczone dla wartości nieujemnych (np. Zliczeń): przyjęcie bezwzględnej wartości mianownika jest modyfikacją R z 1998 r., Aby uniknąć ujemnych odległości." - Tak więc definicja R jest udokumentowana jako inna. –

+0

@KonradRudolph Dziękujemy za odpowiedź! Zmieniłem mój post. Przy definicji R Canberry pozostają niezgodności odległości, więc nie sądzę, że to jest problem. – Adela

Odpowiedz

0

To może rzucić trochę światła na różnicę. O ile widzę, to jest rzeczywisty kod jest prowadzony do obliczania odległości

static double R_canberra(double *x, int nr, int nc, int i1, int i2) 
{ 
    double dev, dist, sum, diff; 
    int count, j; 

    count = 0; 
    dist = 0; 
    for(j = 0 ; j < nc ; j++) { 
    if(both_non_NA(x[i1], x[i2])) { 
     sum = fabs(x[i1] + x[i2]); 
     diff = fabs(x[i1] - x[i2]); 
     if (sum > DBL_MIN || diff > DBL_MIN) { 
     dev = diff/sum; 
     if(!ISNAN(dev) || 
      (!R_FINITE(diff) && diff == sum && 
      /* use Inf = lim x -> oo */ (int) (dev = 1.))) { 
      dist += dev; 
      count++; 
     } 
     } 
    } 
    i1 += nr; 
    i2 += nr; 
    } 
    if(count == 0) return NA_REAL; 
    if(count != nc) dist /= ((double)count/nc); 
    return dist; 
} 

myślę, że winowajcą jest ta linia

if(!ISNAN(dev) || 
       (!R_FINITE(diff) && diff == sum && 
       /* use Inf = lim x -> oo */ (int) (dev = 1.))) 

który obsługuje szczególny przypadek i nie mogą być udokumentowane.

+0

Dziękuję za odpowiedź. Niestety, nie jestem naprawdę biegły w C++, więc nie jestem pewien, co się dzieje w tych specjalnych przypadkach. Czy możesz rzucić trochę światła na to? – Adela

+0

Wiersz zawiera specjalny przypadek, że jeśli dwie wartości są identyczne 'diff == sum', to dodaje jeden do licznika, ponieważ ustawia on' dev = 1'. Jednak dlaczego kod przechodzi obok 'diff> DBL_MIN' w pierwszej kolejności jest dla mnie niejasny. Być może jest problem z konwersją/precyzją zmiennoprzecinkową? – ekstroem

+0

Dodanie jednego do licznika wyjaśniłoby przypadek 1-1 pary i wartości odległości równej 4. Jednak nie widzę, jak to dotyczy przypadku pary 0-0. Dowolny pomysł? – Adela

Powiązane problemy