Преобразование фрейма данных в объект класса "dist" без фактического вычисления расстояний в R
У меня есть фрейм данных с расстояниями
df<-data.frame(site.x=c("A","A","A","B","B","C"),
site.y=c("B","C","D","C","D","D"),Distance=c(67,57,64,60,67,60))
Мне нужно преобразовать это в объект класса "dist", но мне не нужно вычислять расстояние, поэтому я использую функцию dist (). Есть советы?
4 ответов
У меня была аналогичная проблема не так давно и решила ее так:
n <- max(table(df$site.x)) + 1 # +1, so we have diagonal of
res <- lapply(with(df, split(Distance, df$site.x)), function(x) c(rep(NA, n - length(x)), x))
res <- do.call("rbind", res)
res <- rbind(res, rep(NA, n))
res <- as.dist(t(res))
ничто не мешает вам создать объект dist самостоятельно. Это просто вектор расстояний с атрибутами, которые настраивают метки, размер и т. д.
используя df
это как
dij2 <- with(df, Distance)
nams <- with(df, unique(c(as.character(site.x), as.character(site.y))))
attributes(dij2) <- with(df, list(Size = length(nams),
Labels = nams,
Diag = FALSE,
Upper = FALSE,
method = "user"))
class(dij2) <- "dist"
или вы можете сделать это с помощью structure()
напрямую:
dij3 <- with(df, structure(Distance,
Size = length(nams),
Labels = nams,
Diag = FALSE,
Upper = FALSE,
method = "user",
class = "dist"))
это дает:
> df
site.x site.y Distance
1 A B 67
2 A C 57
3 A D 64
4 B C 60
5 B D 67
6 C D 60
> dij2
A B C
B 67
C 57 60
D 64 67 60
> dij3
A B C
B 67
C 57 60
D 64 67 60
Примечание: выше не проверяйте, что данные находятся в правильном порядке. Убедитесь, что у вас есть данные в df
в правильном порядке как и в примере; т. е. Сортировать по site.x
затем site.y
перед запуском кода я показываю.
для людей, поступающих из google... Функция acast в библиотеке reshape2 намного проще для такого рода вещей.
library(reshape2)
acast(df, site.x ~ site.y, value.var='Distance', fun.aggregate = sum, margins=FALSE)