Votre clarification de la question indique que vous souhaitez que le clustering soit basé sur les segments de ligne réels , dans le sens où deux paires origine-destination (OD) doivent être considérées comme "proches" lorsque les deux origines sont proches et les deux destinations sont proches , quel que soit le point considéré comme origine ou destination .
Cette formulation suggère que vous avez déjà une idée de la distance d entre deux points: il peut s'agir de la distance lorsque l'avion vole, de la distance sur la carte, du temps de trajet aller-retour ou de toute autre métrique qui ne change pas lorsque O et D sont commuté. La seule complication est que les segments n'ont pas de représentations uniques: ils correspondent à des paires non ordonnées {O, D} mais doivent être représentés comme des paires ordonnées , soit (O, D) ou (D, O). Nous pourrions donc prendre la distance entre deux paires ordonnées (O1, D1) et (O2, D2) pour être une combinaison symétrique des distances d (O1, O2) et d (D1, D2), telles que leur somme ou le carré racine de la somme de leurs carrés. Écrivons cette combinaison comme
distance((O1,D1), (O2,D2)) = f(d(O1,O2), d(D1,D2)).
Définissez simplement la distance entre les paires non ordonnées comme étant la plus petite des deux distances possibles:
distance({O1,D1}, {O2,D2}) = min(f(d(O1,O2)), d(D1,D2)), f(d(O1,D2), d(D1,O2))).
À ce stade, vous pouvez appliquer n'importe quelle technique de clustering basée sur une matrice de distance.
À titre d'exemple, j'ai calculé les 190 distances point à point sur la carte pour 20 des villes américaines les plus peuplées et j'ai demandé huit grappes à l'aide d'une méthode hiérarchique. (Par souci de simplicité, j'ai utilisé des calculs de distance euclidienne et appliqué les méthodes par défaut dans le logiciel que j'utilisais: en pratique, vous voudrez choisir les distances et les méthodes de regroupement appropriées à votre problème). Voici la solution, avec des clusters indiqués par la couleur de chaque segment de ligne. (Les couleurs ont été assignées au hasard aux grappes.)
Voici le R
code qui a produit cet exemple. Son entrée est un fichier texte avec les champs "Longitude" et "Latitude" pour les villes. (Pour étiqueter les villes sur la figure, il comprend également un champ "Clé".)
#
# Obtain an array of point pairs.
#
X <- read.csv("F:/Research/R/Projects/US_cities.txt", stringsAsFactors=FALSE)
pts <- cbind(X$Longitude, X$Latitude)
# -- This emulates arbitrary choices of origin and destination in each pair
XX <- t(combn(nrow(X), 2, function(i) c(pts[i[1],], pts[i[2],])))
k <- runif(nrow(XX)) < 1/2
XX <- rbind(XX[k, ], XX[!k, c(3,4,1,2)])
#
# Construct 4-D points for clustering.
# This is the combined array of O-D and D-O pairs, one per row.
#
Pairs <- rbind(XX, XX[, c(3,4,1,2)])
#
# Compute a distance matrix for the combined array.
#
D <- dist(Pairs)
#
# Select the smaller of each pair of possible distances and construct a new
# distance matrix for the original {O,D} pairs.
#
m <- attr(D, "Size")
delta <- matrix(NA, m, m)
delta[lower.tri(delta)] <- D
f <- matrix(NA, m/2, m/2)
block <- 1:(m/2)
f <- pmin(delta[block, block], delta[block+m/2, block])
D <- structure(f[lower.tri(f)], Size=nrow(f), Diag=FALSE, Upper=FALSE,
method="Euclidean", call=attr(D, "call"), class="dist")
#
# Cluster according to these distances.
#
H <- hclust(D)
n.groups <- 8
members <- cutree(H, k=2*n.groups)
#
# Display the clusters with colors.
#
plot(c(-131, -66), c(28, 44), xlab="Longitude", ylab="Latitude", type="n")
g <- max(members)
colors <- hsv(seq(1/6, 5/6, length.out=g), seq(1, 0.25, length.out=g), 0.6, 0.45)
colors <- colors[sample.int(g)]
invisible(sapply(1:nrow(Pairs), function(i)
lines(Pairs[i, c(1,3)], Pairs[i, c(2,4)], col=colors[members[i]], lwd=1))
)
#
# Show the points for reference
#
positions <- round(apply(t(pts) - colMeans(pts), 2,
function(x) atan2(x[2], x[1])) / (pi/2)) %% 4
positions <- c(4, 3, 2, 1)[positions+1]
points(pts, pch=19, col="Gray", xlab="X", ylab="Y")
text(pts, labels=X$Key, pos=positions, cex=0.6)