अप्रत्यक्ष लाइनों को क्लस्टर करना


16

मैं उनकी दिशा से स्वतंत्र क्लस्टर लाइनों के लिए एक कुशल मार्ग की तलाश कर रहा हूं। इसका मतलब है कि न्यूयॉर्क और लॉस एंजिल्स के बीच एक लाइन लॉस एंजिल्स और न्यूयॉर्क के बीच दूसरी दिशा में एक लाइन के रूप में एक ही क्लस्टर में होनी चाहिए। प्रारंभ / समाप्ति बिंदु स्थान समान होना चाहिए (यानी सैन डिएगो से लॉन्ग आइलैंड ला-एनवाई के रूप में एक ही क्लस्टर में होना चाहिए, लेकिन शायद बोस्टन से सैन फ्रांसिस्को नहीं) और कोई मध्यवर्ती बिंदु नहीं हैं। इनपुट डेटा इस उदाहरण के समान होगा:

यहाँ छवि विवरण दर्ज करें ( विकिपीडिया कॉमन्स के माध्यम से जापानी विकिपीडिया GFDL या CC-BY-SA-3.0 पर कैसोपिया मीठा )

मैंने पहले से लाइनों को क्रमबद्ध करने की कोशिश की है, जैसे कि उन सभी को पश्चिम से पूर्व की ओर चलाने के लिए, लेकिन यह उत्तर से दक्षिण तक और अन्य तरह से चलने वाली लाइनों के लिए समस्या का समाधान नहीं करता है।

क्या आप इस समस्या से निपटने के लिए कोई एल्गोरिथ्म जानते हैं? मैं देख रहा हूँ, लेकिन इसके अलावा अल्गोरिद्म के अलावा अप्रत्यक्ष सेगमेंट की औसत दिशा की गणना करने के लिए मुझे दूरस्थ रूप से उपयोगी कुछ भी नहीं मिला है, इसलिए मुझे गलत खोज शब्दों का उपयोग करना चाहिए।


1
मैं दोनों सिरों के निर्देशांक की गणना करता हूं और स्ट्रिंग फ़ील्ड को पॉप्युलेट करने के लिए STR (सेट ([X1, y1, x2, y2])) का उपयोग करता हूं। आप इस क्षेत्र को अद्वितीय मूल्यों को खोजने के लिए संक्षेप में
लिख सकते

जवाबों:


10

अगर मैं आपको सही समझता हूं तो आप उन पंक्तियों को क्लस्टर करना चाहते हैं जो दिशा के सम्मान के बिना उसी के बारे में हैं।

यहाँ एक विचार है जो मुझे लगता है कि काम कर सकता है।

  1. स्टार्ट पॉइंट और एंड पॉइंट में लाइनों को विभाजित करें

  2. अंकों को क्लस्टर करें और क्लस्टर आईडी प्राप्त करें

  3. क्लस्टर आईडी के समान संयोजन वाली लाइनें ढूंढें। वे एक क्लस्टर हैं

यह PostGIS (निश्चित रूप से :-)) संस्करण 2.3 में संभव होना चाहिए

मैंने ST_ClusterDBSCAN फ़ंक्शन का परीक्षण नहीं किया है, लेकिन इसे कार्य करना चाहिए।

यदि आपके पास इस तरह की एक पंक्ति तालिका है:

CREATE TABLE the_lines
(
   geom geometry(linestring),
   id integer primary key
)

और आप उस क्लस्टर को बनाना चाहते हैं जहां स्टार्ट और एंड पॉइंट अधिकतम 10 किमी अलग हों। और एक क्लस्टर होने के लिए कम से कम 2 बिंदु होने चाहिए फिर क्वेरी कुछ इस तरह हो सकती है:

WITH point_id AS
   (SELECT (ST_DumpPoints(geom)).geom, id FROM the_lines),
point_clusters as
   (SELECT ST_ClusterDBSCAN(geom, 10000, 2) cluster_id, id line_id FROM point_id) 
SELECT array_agg(a.line_id), a.cluster_id, b.cluster_id 
FROM point_clusters a 
     INNER JOIN point_clusters b 
     ON a.line_id = b.line_id AND a.cluster_id < b.cluster_id
GROUP BY a.cluster_id, b.cluster_id

a.cluster_id<b.cluster_idआपके साथ जुड़कर दिशा से स्वतंत्र क्लस्टर आईडी प्राप्त कर सकते हैं।


आपका धन्यवाद! मुझे यह दृष्टिकोण पसंद है क्योंकि यह मुझे क्लस्टरिंग करते समय विभिन्न इकाइयों (यानी कोण और दूरी) को मिलाने के लिए मजबूर नहीं करता है।
UnderDark

5

क्या आप वास्तव में मूल या गंतव्य के किसी भी विचार के बिना, दिशा से पूरी तरह से क्लस्टर करना चाहते हैं? यदि हां, तो कुछ बहुत ही सरल तरीके हैं। शायद प्रत्येक पंक्ति के असर की गणना करना सबसे आसान है, इसे दोगुना करें, और इसे एक सर्कल के बिंदु के रूप में प्लॉट करें। चूंकि आगे-पीछे की तरफ की बीयरिंग 180 डिग्री से भिन्न होती है, वे दोहरीकरण के बाद 360 डिग्री से भिन्न होती हैं और इसलिए उसी स्थान पर साजिश करती हैं। अब अपनी पसंद के किसी भी तरीके का इस्तेमाल करके प्लेन के पॉइंट्स को क्लस्टर करें।

इसमें एक कार्यशील उदाहरण दिया गया है R, जिसमें इसके उत्पादन में चार समूहों में से प्रत्येक के अनुसार रेखाओं को रंगीन दिखाया गया है। बेशक आप बीयरिंगों की गणना करने के लिए जीआईएस का उपयोग करेंगे - मैंने सादगी के लिए यूक्लिडियन बीयरिंग का उपयोग किया।

आकृति

cluster.undirected <- function(x, ...) {
  #
  # Compute the bearing and double it.
  #
  theta <- atan2(x[, 4] - x[, 2], x[, 3] - x[, 1]) * 2
  #
  # Convert to a point on the unit circle.
  #
  z <- cbind(cos(theta), sin(theta))
  #
  # Cluster those points.
  #
  kmeans(z, ...)
}
#
# Create some data.
#
n <- 100
set.seed(17)
pts <- matrix(rnorm(4*n, c(-2,0,2,0), sd=1), ncol=4, byrow=TRUE)
colnames(pts) <- c("x.O", "y.O", "x.D", "y.D")
#
# Plot them.
#
plot(rbind(pts[1:n,1:2], pts[1:n,3:4]), pch=19, col="Gray", xlab="X", ylab="Y")
#
# Plot the clustering solution.
#
n.centers <- 4
s <- cluster.undirected(pts, centers=n.centers)
colors <- hsv(seq(1/6, 5/6, length.out=n.centers), 0.8, 0.6, 0.25)
invisible(sapply(1:n, function(i) 
  lines(pts[i, c(1,3)], pts[i, c(2,4)], col=colors[s$cluster[i]], lwd=2))
)

धन्यवाद! उत्पत्ति और गंतव्य (O & D) भी मायने रखते हैं। "आरंभ / अंत बिंदु स्थानों के साथ समान होना चाहिए" पर संकेत देने की कोशिश की, लेकिन मुझे परवाह नहीं है कि कौन सा हे और जो डी है। फिर भी, मुझे लगता है कि आपका स्पष्टीकरण मुझे उस समाधान के करीब ले जा सकता है जिसकी मुझे तलाश थी, अगर मैं केमियां चलाने से पहले बिंदु के निर्देशांक में इकाई सर्कल मानों को कैसे स्केल किया जाए, यह पता लगा सकते हैं।
UnderDark

मुझे संदेह था कि आपके मन में ऐसा हो सकता है। इसलिए मैंने एक निर्देशांक (अंक) की एक जोड़ी को अर्ध-दिशाओं का मानचित्रण करने का सुझाव दिया। आप एक दूसरे चर द्वारा उन बिंदुओं को सोच सकते हैं (ध्रुवीय निर्देशांक) और / या उत्पत्ति या गंतव्यों के लिए अतिरिक्त निर्देशांक पेश करते हैं। क्लस्टरिंग के अंतिम उद्देश्य को जाने बिना, अधिक सलाह देना मुश्किल है क्योंकि अतिरिक्त निर्देशांक (सर्कल निर्देशांक की तुलना में) के सापेक्ष आकार क्लस्टरिंग समाधान का निर्धारण करेंगे। एक अन्य उपाय Hough के परिवर्तन का फायदा उठाना है ।
whuber

4

आपके प्रश्न का स्पष्टीकरण आपको इंगित करता है कि आप वास्तविक लाइन खंडों पर आधारित क्लस्टरिंग करना चाहते हैं , इस अर्थ में कि किसी भी दो मूल-गंतव्य (OD) जोड़े को "करीब" माना जाना चाहिए जब दोनों मूल पास हों और दोनों गंतव्य पास हों , चाहे जिस बिंदु को मूल या गंतव्य माना जाए

यह सूत्रीकरण बताता है कि आपके पास पहले से ही दो बिंदुओं के बीच की दूरी d की समझ है : यह दूरी के रूप में हो सकता है, जब विमान उड़ता है, नक्शे पर दूरी, गोल-यात्रा यात्रा का समय, या कोई अन्य मीट्रिक जो ओ और डी होने पर परिवर्तित नहीं होता है। बंद। एकमात्र जटिलता यह है कि सेगमेंट में अद्वितीय प्रतिनिधित्व नहीं होते हैं: वे अनऑर्डर्ड जोड़े {O, D} के अनुरूप होते हैं , लेकिन आदेश दिए गए जोड़े के रूप में प्रतिनिधित्व किया जाना चाहिए , (O, D) या (D, O)। इसलिए हम दो ऑर्डर किए गए जोड़े (O1, D1) और (O2, D2) के बीच की दूरी d (O1, O2) और d (D1, D2) के कुछ सममित संयोजन हो सकते हैं, जैसे कोई योग या वर्ग। उनके वर्गों के योग की जड़। आइए इस संयोजन को लिखें

distance((O1,D1), (O2,D2)) = f(d(O1,O2), d(D1,D2)).

बस दो संभव दूरी के छोटे होने के लिए अनियंत्रित जोड़े के बीच की दूरी को परिभाषित करें:

distance({O1,D1}, {O2,D2}) = min(f(d(O1,O2)), d(D1,D2)), f(d(O1,D2), d(D1,O2))).

इस बिंदु पर आप दूरी मैट्रिक्स के आधार पर किसी भी क्लस्टरिंग तकनीक को लागू कर सकते हैं।


एक उदाहरण के रूप में, मैंने सबसे अधिक आबादी वाले अमेरिकी शहरों में से 20 के लिए मानचित्र पर सभी 190 बिंदु-से-बिंदु दूरी की गणना की और एक पदानुक्रमित पद्धति का उपयोग करते हुए आठ क्लस्टर का अनुरोध किया। (सादगी के लिए मैंने यूक्लिडियन दूरी की गणना का इस्तेमाल किया और सॉफ्टवेयर में डिफ़ॉल्ट तरीकों को लागू किया जो मैं उपयोग कर रहा था: व्यवहार में आप अपनी समस्या के लिए उचित दूरी और क्लस्टरिंग विधियों का चयन करना चाहेंगे)। यहाँ समाधान है, प्रत्येक पंक्ति खंड के रंग से संकेतित समूहों के साथ। (रंग बेतरतीब ढंग से गुच्छों को सौंपा गया था।)

आकृति

यहाँ Rकोड है कि इस उदाहरण का उत्पादन किया है। इसका इनपुट शहरों के लिए "देशांतर" और "अक्षांश" फ़ील्ड के साथ एक पाठ फ़ाइल है। (आकृति में शहरों को लेबल करने के लिए, इसमें "कुंजी" फ़ील्ड भी शामिल है।)

#
# 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)

धन्यवाद! बड़े आयुध डिपो के लिए जोड़ीदार दूरी की गणना एक मुद्दा होगा?
UnderDark

हां, क्योंकि n रेखा खंडों के साथ n (n-1) / 2 दूरी की गणनाएं हैं। लेकिन कोई अंतर्निहित समस्या नहीं है: सभी क्लस्टरिंग एल्गोरिदम को बिंदुओं (या बिंदुओं और क्लस्टर केंद्रों) के बीच की दूरी या असामान्यताएं खोजने की आवश्यकता होती है। यह एक ऐसा सामान्य मुद्दा है कि कई एल्गोरिदम एक कस्टम डिस्टेंस फ़ंक्शन के साथ काम करते हैं।
whuber
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.