2016-08-11 11 views
5

私はキャンベラ距離の計算で何が起こっているのか理解しようとしています。私は自分の簡単なcanberra.distance関数を書いていますが、結果はdistと一貫していません。ゼロ分母があるときに合計を計算できるように、私は関数にオプションna.rm = Tを追加しました。 0-0と1-1は、問題があると思われるTerms with zero numerator and denominator are omitted from the sum and treated as if the values were missing.キャンベラ距離 - 矛盾する結果

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 

ペア:?distから私は、彼らが同様のアプローチを使用することを理解しています。最初のケース(0-0)では、分子と分母の両方がゼロに等しく、このペアを省略する必要があります。第2の場合(1-1)の分子は0であるが、分母はそうではないので、その項もまた0であり、その和は変化してはならない。

私はここで何が欠けていますか?

EDIT: Rの定義に沿ったものであるために、以下のように、関数canberra.distanceを修正することができる。

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

しかし、結果は前と同じです。

+2

あなたはベースRのバグに遭遇した可能性があります。わからないけど、[Wolfram Alphaはあなたに同意します](https://www.wolframalpha.com/input/?i=CanberraDistance%5B% 7B1、+ 0、+ 1、+ 0%7D、+%7B0、+ 1、+ 0、+ 0%7D%5D)。残念ながら私は信頼できる参照を見つけることができませんが、実装はWikipediaとWolframによると正しいと思われます。 –

+0

実際、 'dist'の文書(https://stat.ethz.ch/R-manual/R-devel/library/stats/html/dist.html)は、キャンバラの距離を* sum(| x_i - y_i |/| x_i + y_i |)*(これはあなたとWolframのものとは異なります)。また、負の値(例えば、カウント)を意図していることに注意してください:負の距離を避けるために、分母の絶対値をとるのは1998年の修正です。 " - Rの定義は異なると文書化されています。 –

+0

@KonradRudolphご返信ありがとうございます!私は自分の投稿を編集しました。キャンバラ距離のR定義では、不一致が残っているので、これは問題ではないと私は考えています。 – Adela

答えて

0

これは、相違点を明らかにするかもしれません。私の知る限り見ることができるように、これは実際のコードは、私は犯人はこのライン特殊なケースを処理し、文書化することはできません

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

だと思う距離

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; 
} 

を計算するために実行されています。

+0

ありがとうございます。残念ながら、私はC++に熟練していないので、これらの特殊なケースで何が起こっているのか分かりません。あなたはそれにいくつかの光を発散していただけますか? – Adela

+0

この行には、2つの値が同じである(diff == sum')場合、 'dev = 1'を設定するので、分子に1が加算されるという特殊なケースが含まれています。しかし、なぜコードが最初に 'diff> DBL_MIN'を過ぎるのかは、私には少し不明です。多分浮動小数点の変換/精度に問題がありますか? – ekstroem

+0

まあ、分子に1を加えることは、1-1対の場合と距離の値4を説明するでしょう。しかし、これがどのように0-0対のケースを伴うのか分かりません。何か案が? – Adela

関連する問題