【问题标题】:Computing normalized Euclidean distance in R在 R 中计算归一化欧几里得距离
【发布时间】:2014-11-03 16:53:24
【问题描述】:

我的数据框如下:

Binning_data[1:4,]
  person_id  V1  V2  V3  V4    V5  V6  V7  V8    V9 V10 V11 V12 V13 V14 V15 V16
1       312  74  80  NA  87  90.0  85  88  98  96.5  99  94  95  90  90  93 106
2       316  NA  NA 116 106 105.0 110 102 105 105.0 102  98 101  98  92  89  91
3       318  71  61  61  61  60.5  68  62  67  64.0  60  59  60  62  59  63  63
4       319  64  NA  80  80  83.0  84  87  83  85.0  88  87  95  74  70  63  83

我想计算给定“index_person_id”(比如 312)与所有其他 person_id 的欧几里得距离,同时忽略所有 NA。

例如:“312”和“316”之间的归一化欧几里得距离应该省略前 3 个 bin (V1,V2,V3),因为两行中至少有一个具有 NA。它应该只计算从第 4 个 bin 到第 16 个 bin 的欧几里得距离并除以 13(非空 bin 的数量)

Binning_Data的维度是10000*17。

输出文件的大小应为 10000*2,第一列为 person_id,第二列为“归一化欧几里得距离”。

我目前正在为此使用 sapply:

index_person<-binning_data[which(binning_data$person_id==index_person_id),]
non_empty_index_person=which(is.na(index_person[2:ncol(index_person)])==FALSE)

distance[,2]<-sapply(seq_along(binning_data$person_id),function(j) {

compare_person<-binning_data[j,]    
non_empty_compare_person=which(is.na(compare_person[2:ncol(compare_person)])==FALSE)
non_empty=intersect(non_empty_index_person,non_empty_compare_person)
distance_temp=(index_person[non_empty+1]-compare_person[non_empty+1])^2
as.numeric(mean(distance_temp))    
})

这似乎需要相当长的时间。有没有更好的方法来做到这一点?

【问题讨论】:

    标签: r euclidean-distance sapply


    【解决方案1】:

    如果我运行你的代码,我会得到:

     0.0000 146.0192 890.9000 200.8750
    

    如果您将数据框转换为矩阵,转置,然后您可以减去列,然后在mean 上使用na.rm=TRUE 来获得您想要的距离。这可以使用colMeans 在列上完成。这里是您的示例数据的II 行:

    > II = 1
    > m = t(as.matrix(binning_data[,-1]))
    > colMeans((m - m[,II])^2, na.rm=TRUE)
           1        2        3        4 
      0.0000 146.0192 890.9000 200.8750 
    

    那么你的 10000x2 矩阵是(这里是 10000==4):

    > cbind(II,colMeans((m - m[,II])^2, na.rm=TRUE))
      II         
    1  1   0.0000
    2  1 146.0192
    3  1 890.9000
    4  1 200.8750
    

    如果您想为给定的索引列表计算此值,请将其循环,可能像这样使用 lapplyrbind 将它们重新组合在一起作为数据框进行更改:

    II = c(1,2,1,4,4)
    do.call(rbind,lapply(II, function(i){data.frame(i,d=colMeans((m-m[,i])^2,na.rm=TRUE))}))
       i         d
    1  1    0.0000
    2  1  146.0192
    3  1  890.9000
    4  1  200.8750
    11 2  146.0192
    21 2    0.0000
    31 2 1595.0179
    41 2  456.7143
    12 1    0.0000
    22 1  146.0192
    32 1  890.9000
    42 1  200.8750
    13 4  200.8750
    23 4  456.7143
    33 4  420.8833
    43 4    0.0000
    14 4  200.8750
    24 4  456.7143
    34 4  420.8833
    44 4    0.0000
    

    这是一个4 x length(II)-row 矩阵

    【讨论】:

      猜你喜欢
      • 2021-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-28
      • 2013-04-07
      • 2020-11-29
      • 2018-02-14
      相关资源
      最近更新 更多