Как группировать точки широты / долготы, которые "близки" друг к другу?

у меня есть база данных пользовательских отправленных точек широты / долготы и я пытаюсь сгруппировать "закрыть" точки вместе. "Близко" относительно, но пока кажется, что ~500 футов.

сначала казалось, что я могу просто сгруппировать строки, которые имеют одинаковую широту / долготу для первых 3 десятичных знаков (примерно 300x300, понимая, что он меняется по мере удаления от экватора).

однако этот метод, похоже, совершенно отсутствует. "Близость" не может быть значительно отличается от расстояния, которое представляет каждый десятичный знак. Он не учитывает, что два местоположения могут иметь разные цифры в 3-м (или любом) десятичном знаке, но все равно находиться на расстоянии, которое представляет это место (33.1239 и 33.1240).

Я также обдумал ситуацию, когда точка A и точка C оба "близки" к точке B (но не друг к другу) - должны ли они быть сгруппированы вместе? Если да, то что происходит, когда точка D "близка" к точке C (и никакой другой points) - он также должен быть сгруппирован. Конечно, я должен определить желаемое поведение, но как это будет реализовано?

может ли кто-нибудь указать мне в правильном направлении, как это можно сделать и какие различные методы/подходы можно использовать?

Я чувствую, что мне не хватает чего-то очевидного.

В настоящее время данные являются базой данных MySQL, используемой приложением PHP; однако я открыт для других методов хранения, если они являются ключом часть в достижении этого. здесь.

5 ответов


Существует несколько способов определения расстояния между двумя точками, но для построения точек на 2-D график, вы, вероятно, хотите, чтобы Евклидово расстояние. Если (x1, y1) представляет первую точку и (x2, y2) представляет ваш второй, расстояние

d = sqrt( (x2-x1)^2 + (y2-y1)^2 )

Что касается группировки, вы можете использовать своего рода 2-D, чтобы определить, насколько "близки" вещи друг к другу. Например, если у вас есть три точки,(x1, y1), (x2, y2), (x3, y3), вы можете найти центр этих трех точек простым усреднением:

x(mean) = (x1+x2+x3)/3
y(mean) = (y1+y2+y3)/3

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


существует несколько способов определения кластеров, все из которых используют некоторый вариант алгоритм кластеризации. Я сейчас спешу и не успеваю подвести итоги, но проверьте ссылку и алгоритмы, и, надеюсь, другие люди смогут предоставить больше деталь. Удачи!


Используйте что-то похожее на метод, который вы изложили в своем вопросе, чтобы получить приблизительный набор результатов, а затем вычеркните этот приблизительный набор, выполнив правильные вычисления. Если вы правильно выбираете размер сетки (то есть, сколько вы округляете свои координаты), вы можете, по крайней мере, надеяться уменьшить объем работы до приемлемого уровня, хотя вам нужно управлять размером этой сетки.

например,earthdistance расширение для PostgreSQL работает путем преобразования пар lat/long в (x,y,z) декартовые координаты, моделируя землю как однородную сферу. PostgreSQL имеет сложную систему индексирования, которая позволяет индексировать эти координаты или коробки вокруг них в R-деревья, но вы можете ударить что-то вместе, что все еще полезно без этого.

Если вы берете свой (x,y,z) тройной и округлить-то есть умножить на некоторый фактор и усечь до целого числа - у вас есть три целых числа, которые вы можете объединить для получения "имя поля", которое идентифицирует поле в вашей" сетке", в которой находится точка.

Если вы хотите найти все точки в пределах X км от какой-либо целевой точки, вы генерируете все "имена полей" вокруг этой точки (после того,как вы преобразовали свою целевую точку в (x,y, z) тройной, это легко) и устраняете все коробки, которые не пересекают поверхность Земли (tricker, но использование x^2+y^2+z^2=R^2 формула в каждом углу скажет вам) вы в конечном итоге со списком ящиков целевые точки могут быть в-так просто найдите все точки, соответствующие одному из этих ящиков, который также вернет вам некоторые дополнительные очки. Таким образом, в качестве заключительного этапа вам нужно рассчитать фактическое расстояние до целевой точки и устранить некоторые (опять же, это можно ускорить, работая в декартовых координатах и преобразовывая радиус расстояния большого круга цели в секущее расстояние).

возня сводится к тому, чтобы убедиться, что вам не нужно искать слишком много ящиков, но в то же время не приносите слишком много дополнительные баллы. Я нашел полезным индексировать каждую точку на нескольких разных сетках (например, разрешения 1Km, 5Km, 25Km, 125Km и т. д.). В идеале вы хотите искать только одну коробку, помните, что она расширяется по крайней мере до 27, как только ваш целевой радиус превышает размер сетки.

я использовал этот метод для построения пространственного индекса с использованием Lucene, а не для выполнения вычислений в базах данных SQL. Он работает, хотя есть некоторые скрипки, чтобы настроить его, и индексы занимают некоторое время, чтобы генерируют и довольно большие. Использование R-дерева для хранения всех координат является гораздо более приятным подходом, но потребует больше пользовательского кодирования - этот метод в основном требует быстрого поиска хэш-таблицы (так что, вероятно, будет хорошо работать со всеми базами данных NoSQL, которые являются яростью в эти дни, и должны использоваться в базе данных SQL тоже).


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


Если вы рассматриваете широту и долготу, есть несколько факторов, которые следует учитывать в данных в реальном времени: препятствия, такие как реки и озера, и объекты, такие как мосты и туннели. Вы не можете сгруппировать их просто; если вы используете простой алгоритм как K, вы не сможете сгруппировать их. Я думаю, вы должны пойти на методы пространственной кластеризации как метод секционирования CLARANS.


Если бы я занимался этим, я бы начал с сетки. Поместите каждую точку в квадрат на сетке. Ищите густонаселенные сетки. Если соседние сетки не заполнены, то у вас есть приличная группа.

Если у вас есть соседние густонаселенные сетки, вы всегда можете удалить круг в центре каждой сетки и оптимизировать для области круга vs (количество точек в круге * некоторый настраиваемый вес). Не идеально, но легко. Лучшие группировки - гораздо более сложная оптимизация проблемы.