2013-05-05 139 views
3

我有一个包含这样的一个数据集:欧氏距离

case,group,val1,val2,val3,val4 
1,1,3,5,6,8 
2,1,2,7,5,4 
3,2,1,3,6,8 
4,2,5,4,3,7 
5,1,8,6,5,3 

我试图计算编程值的组中的向量之间的欧几里得距离。

这意味着我在n个组中有x个个案。欧几里德距离是在行对之间计算的,然后对该组进行平均。所以,在上面的例子中,首先我计算组1的平均值和标准偏差(情况1,2和5),然后标准化值(即[(原始值 - 平均值)/ st dev],然后计算情况之间的ED 1和案例2,案例2和5,案例1和5,最后取平均ED的组。

任何人都可以表明,在一个合理有效的方式实现这一目标的一种巧妙的方法?

回答

1

作为我将如何处理这在SPSS一个示例中,第一允许读出的示例性数据到SPSS。

data list list (",")/case group val1 val2 val3 val4 (6F1.0). 
begin data 
1,1,3,5,6,8 
2,1,2,7,5,4 
3,2,1,3,6,8 
4,2,5,4,3,7 
5,1,8,6,5,3 
end data. 
dataset name orig. 

然后我们可以使用SPLIT FILEPROXIMITIES按组,让我们的距离矩阵。请注意,正如您在flodel答案的评论中提到的那样,这会产生需要处理的单独数据集(另请注意,SPSS语法中实际上从不重要,例如split fileSPLIT FILE等效)。

sort cases by group. 
split file by group. 
dataset declare dist. 
PROXIMITIES val1, val2, val3, val4 
/STANDARDIZE = Z 
/MEASURE = EUCLID 
/PRINT = NONE 
/MATRIX = OUT('dist'). 

不同于R,一个SPSS数据矩阵内基本上一切都像的R data.frame,附近以便SPLIT文件功能替换所有不同*ply功能R.非常convienant,但一般不太灵活。所以现在我们需要汇总我保存结果的dist文件中的距离。我们首先对行进行求和,然后通过AGGREGATE命令进行求和。

dataset activate dist. 
compute dist_sum = SUM(VAR1 to VAR3). 
*it appears SPSS keeps empty cases - we dont want them in the aggregation. 
select if MISSING(dist_sum) = 0. 
dataset activate dist. 
DATASET DECLARE dist_agg. 
AGGREGATE 
    /OUTFILE='dist_agg' 
    /BREAK=group 
    /dist_sum = SUM(dist_sum) 
    /N_Cases=N. 
dataset activate dist_agg. 
compute mean_dist = dist_sum /(N_Cases*(N_Cases - 1)). 

这里我将汇总结果保存到名为dist_agg的另一个数据集中。因为SPSS(令人讨厌地)保存了全距离矩阵,所以平均值不会是n*(n-1)/2(如等效的R语法),但假设你不想对对数的平均值计算对角元素,那么将会是n*(n-1)。然后我们可以通过匹配文件命令将这些数据文件合并到orig数据文件中。

*merge back into the original dataset. 
dataset activate orig. 
match files file = * 
/table = 'dist_agg' 
/by group. 
exe. 

*clean out old datasets if you like. 
dataset close dist. 
dataset close dist_agg. 

R的灵活性,来回走matrixdata.frame对象之间,使SPSS这个工作更笨重一点。我可以用SPSS的MATRIX语言编写更简洁的程序来完成此任务,但是在MATRIX中的跨组执行操作时会遇到麻烦(与R的*ply语法相比)。

+0

andy-w感谢提供此解决方案与SPSS。我不得不说,我比来自@ flodel的R解决方案更了解它,但也许是因为SPSS(在它的笨拙中)使每个中间步骤都可见!非常感谢您的意见 – lorenzov 2013-05-07 02:45:07

5

是,它可能是R中更容易...

您的数据:

dat <- data.frame(case = 1:5, 
        group = c(1, 1, 2, 2, 1), 
        val1 = c(3, 2, 1, 5, 8), 
        val2 = c(5, 7, 3, 4, 6), 
        val3 = c(6, 5, 6, 3, 5), 
        val4 = c(8, 4, 8, 7, 3)) 

短溶液:

library(plyr) 
ddply(dat[c("group", "val1", "val2", "val3", "val4")], 
     "group", function(x)c(mean.ED = mean(dist(scale(as.matrix(x)))))) 
# group mean.ED 
# 1  1 3.121136 
# 2  2 3.162278 
+0

由于这是辉煌的,但我必须详细研究的嵌套,因为我不明白......高兴,它的工作,但! – lorenzov 2013-05-05 08:42:27

+0

还有一个问题,我如何确保如果有NA值,该函数也不会返回NA,而是跳过丢失数据的情况? – lorenzov 2013-05-05 08:48:31

+0

查看'mean'函数的'na.rm'参数。 – flodel 2013-05-05 19:16:59

0

这是一个使用base R更简单的解决方案。

d <- by (dat[,2:5], dat$group, function(x) dist(x)) 

sapply(d,平均)