Быстрое вычисление средней близости в матрице близости

У меня есть матрица сходства между всеми случаями и в отдельном фрейме данных классы этих случаев. Я хочу вычислить среднее сходство между случаями из одного класса, вот уравнение для примера n из класса j:

Средняя близость между делами

Нам нужно вычислить сумму всех квадратов близости между n и всеми случаями k из того же класса, что и n. Ссылка: http://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm#outliers

Я реализовал это с двумя циклами for, но это очень медленно. Есть ли более быстрый способ сделать это в R?

Спасибо.

//ДАННЫЕ (вывод)

Фрейм данных с классами:

structure(list(class = structure(c(1L, 2L, 2L, 1L, 3L, 3L, 1L, 
                            1L, 2L, 3L), .Label = c("1", "2", "3", "5", "6", "7"), class = "factor")), .Names = "class", row.names = c(NA, 
            -10L), class = "data.frame")

Матрица близости (строка m и столбец m соответствуют классу в строке m кадра данных выше):

structure(c(1, 0.60996875, 0.51775, 0.70571875, 0.581375, 0.42578125, 
0.6595, 0.7134375, 0.645375, 0.468875, 0.60996875, 1, 0.77021875, 
0.55171875, 0.540375, 0.53084375, 0.4943125, 0.462625, 0.7910625, 
0.56321875, 0.51775, 0.77021875, 1, 0.451375, 0.60353125, 0.62353125, 
0.5203125, 0.43934375, 0.6909375, 0.57159375, 0.70571875, 0.55171875, 
0.451375, 1, 0.69196875, 0.59390625, 0.660375, 0.76834375, 0.606875, 
0.65834375, 0.581375, 0.540375, 0.60353125, 0.69196875, 1, 0.7194375, 
0.684, 0.68090625, 0.50553125, 0.60234375, 0.42578125, 0.53084375, 
0.62353125, 0.59390625, 0.7194375, 1, 0.53665625, 0.553125, 0.513, 
0.801625, 0.6595, 0.4943125, 0.5203125, 0.660375, 0.684, 0.53665625, 
1, 0.8456875, 0.52878125, 0.65303125, 0.7134375, 0.462625, 0.43934375, 
0.76834375, 0.68090625, 0.553125, 0.8456875, 1, 0.503, 0.6215, 
0.645375, 0.7910625, 0.6909375, 0.606875, 0.50553125, 0.513, 
0.52878125, 0.503, 1, 0.60653125, 0.468875, 0.56321875, 0.57159375, 
0.65834375, 0.60234375, 0.801625, 0.65303125, 0.6215, 0.60653125, 
1), .Dim = c(10L, 10L))

Правильный результат:

c(2.44197227050781, 2.21901680175781, 2.07063155175781, 2.52448621289062, 
1.88040830957031, 2.16019295703125, 2.58622273828125, 2.81453253222656, 
2.1031745078125, 2.00542063378906)

person Uros K    schedule 03.10.2012    source источник


Ответы (1)


Должно быть возможно. Ваша нотация не дает понять, найдем ли мы членов подобных классов в строках или столбцах, поэтому этот ответ предполагает в столбцах, но очевидные модификации также работали бы, если бы они были в строках.

colSums(mat^2))  # in R this is element-wise application of ^2 rather than matrix multiplication.

Поскольку обе операции векторизованы, можно ожидать, что они будут намного быстрее, чем циклы for.

С модификацией и предположением, что матрица называется «mat», а класс-данные — «cldf»:

sapply( 1:nrow(mat) , 
           function(r) sum(mat[r, cldf[['class']][r] ==  cldf[['class']] ]^2)  )
[1] 2.441972 2.219017 2.070632 2.524486 1.880408 2.160193 2.586223 2.814533 2.103175 2.005421

person IRTFM    schedule 03.10.2012
comment
Проблема в том, что мы не можем определить, какие примеры относятся к одному классу, только по матрице. Мы должны искать это из фрейма данных. - person Uros K; 04.10.2012
comment
В этом случае ваша публикация репрезентативного примера и правильного ответа уже давно назрела. - person IRTFM; 04.10.2012
comment
Я думаю, что могу изменить матрицу (или для каждого класса использовать некоторое подмножество матрицы) и использовать ваш ответ. Попробую, насколько быстро. Спасибо четыре ваша помощь. - person Uros K; 04.10.2012
comment
Я имею в виду еще несколько подходов, которые потребуют примера, на котором их можно было бы протестировать. - person IRTFM; 04.10.2012
comment
Я предоставил некоторые данные: классы, матрицу близости и правильный результат. - person Uros K; 04.10.2012
comment
Это намного быстрее. Спасибо. - person Uros K; 04.10.2012