在SPSS,R或Excel中由其他variables分组的向量之间的欧式距离

我有一个数据集包含这样的东西:

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,最后为该组取平均值。

任何人都可以提出一个相当有效的方式实现这一点的整洁方式?

作为一个例子,我将如何在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来获得我们的距离matrix。 注意,正如你在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数据matrix中的所有内容基本上都是R data.frame ,所以在function上,SPLIT文件在function上替代了R中所有不同的*ply函数。非常stream行,但总的来说不太灵活。 所以现在我们需要汇总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(令人讨厌地)保存了全距离matrix,所以平均值将不是n*(n-1)/2 (如在等效的R语法中),但是假设你不想计算对angular元素的平均值。 然后,我们可以通过匹配文件命令将这些文件合并到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在matrix和数据data.frame对象之间来回的灵活性使得SPSS在这项工作中更加笨拙。 我可以用SPSS的MATRIX语言编写一个更简洁的程序来完成这个任务,但是在MATRIX不同组中,这样做会比较麻烦(与R的*ply语法相比)。

是的,在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)) 

简短的解决scheme:

 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 

这是一个更简单的解决scheme,使用基R

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

sapply(d,平均值)

Interesting Posts