Вычислить все попарные различия внутри вектора в R
Есть несколько сообщений о вычислении парных различий между векторами, но я не могу найти, как вычислить все различия внутри вектора.
Скажем, у меня есть вектор, v.
v<-c(1:4)
Я хотел бы создать второй вектор, который является абсолютным значением всех парных различий внутри вектора. Похоже на:
abs(1-2) = 1
abs(1-3) = 2
abs(1-4) = 3
abs(2-3) = 1
abs(2-4) = 2
abs(3-4) = 1
Результат будет вектором из 6 значений, которые являются результатом моих 6 сравнений:
output<- c(1,2,3,1,2,1)
Есть ли в R функция, которая может это сделать?
Ответы
Ответ 1
Пусть играют в гольф
abs(apply(combn(1:4,2), 2, diff))
@Ben, ваш убийца!
> system.time(apply(combn(1:1000,2), 2, diff))
user system elapsed
6.65 0.00 6.67
> system.time(c(dist(1:1000)))
user system elapsed
0.02 0.00 0.01
> system.time({
+ v <- 1:1000
+ z = outer(v,v,'-');
+ z[lower.tri(z)];
+ })
user system elapsed
0.03 0.00 0.03
Кто знал, что этот элегантный (читаемый понятный/гибкий) код может быть настолько медленным.
Ответ 2
as.numeric(dist(v))
похоже, работает; он рассматривает v
как матрицу столбца и вычисляет евклидово расстояние между строками, которое в этом случае равно sqrt((x-y)^2)=abs(x-y)
Если мы играем в гольф, то я предлагаю c(dist(v))
, что эквивалентно, и я предполагаю, что это будет непобедимым.
@AndreyShabalin делает все возможное, чтобы использование method="manhattan"
, вероятно, было бы немного более эффективным, так как оно избегает возведения в квадрат/квадратного корня.
Ответ 3
Возможное решение:
z = outer(v,v,'-');
z[lower.tri(z)];
[1] 1 2 3 1 2 1