Как сгруппировать точки широты / долготы, которые «близки» друг к другу? - PullRequest
26 голосов
/ 03 декабря 2010

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

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

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

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

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

Я чувствую, что упускаю что-то очевидное.

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

Ответы [ 5 ]

7 голосов
/ 04 декабря 2010

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

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

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

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

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

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

7 голосов
/ 03 декабря 2010

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

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

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

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

Затем вы сможете увидеть, как близко каждаянаходится в центре, чтобы определить, должна ли она быть частью «кластера».


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

5 голосов
/ 03 декабря 2010

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

3 голосов
/ 08 июля 2011

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

2 голосов
/ 03 декабря 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...