Каков оптимальный способ сопоставления записей списка после округления в Mathematica? - PullRequest
5 голосов
/ 16 ноября 2011

У меня есть два списка в Mathematica:

list1 = {{a1, b1, c1}, ... , {an, bn, cn}} 

и

list2 = {{d1, e1, f1}, ... , {dn, en, fn}}

списки содержат числовые результаты и примерно состоят из 50000 триплетов каждый. Каждый триплет представляет две координаты и числовое значение некоторого свойства в этих координатах. Каждый список имеет разную длину и координаты не совсем одинаковы. Я намерен сопоставить числовые значения третьего свойства из каждого списка, поэтому мне нужно просмотреть списки и определить свойства, координаты которых совпадают. Мой вывод будет что-то вроде

list3 = {{ci, fj}, ... , {cl, fm}}

, где

{ai, bi}, ..., {al, bl}

будет (примерно) равно соответственно

{dj, ej}, ..., {dm, em}

Под "грубо говоря" я подразумеваю, что координаты будут совпадать один раз с округлением до некоторой желаемой точности:

list1(2) = Round[{#[[1]], #[[2]], #[[3]]}, {1000, 500, 0.1}] & /@ list1(2)

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

Пример списка из 6 элементов:

list1 = {{-1.16371*10^6, 548315., 14903.}, {-1.16371*10^6, 548322., 14903.9}, 
   {-1.16371*10^6, 548330., 14904.2}, {-1.16371*10^6, 548337., 14904.8}, 
   {-1.16371*10^6, 548345., 14905.5}, {-1.16371*10^6, 548352., 14911.5}}

Ответы [ 2 ]

5 голосов
/ 16 ноября 2011

Вы можете использовать что-то вроде этого:

{Round[{#, #2}], #3} & @@@ Join[list1, list2];

% ~GatherBy~ First ~Select~ (Length@# > 1 &)

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

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

Вот еще один метод, использующий Sow и Reap. Применяются те же предостережения. Оба эти примера являются просто рекомендациями о том, как вы можете реализовать свои функциональные возможности.

Reap[
  Sow[#3, {Round[{#, #2}]}] & @@@ Join[list1, list2],
  _,
  List
][[2]] ~Cases~ {_, {_, __}}

Чтобы иметь дело с дублирующими элементами в каждом списке, вы можете использовать Round и GatherBy в каждом списке следующим образом.

newList1 = GatherBy[{Round[{#, #2}], #3} & @@@ list1, First][[All, 1]];

newList2 = GatherBy[{Round[{#, #2}], #3} & @@@ list2, First][[All, 1]];

, а затем продолжить с:

newList1 ~Join~ newList2 ~GatherBy~ First ~Select~ (Length@# > 1 &)
4 голосов
/ 16 ноября 2011

Вот мой подход, полагаясь на Nearest, чтобы соответствовать точкам.

Предположим, что list1 не имеет меньше элементов, чем list2.(В противном случае вы можете поменять их местами с помощью {list1, list2} = {list2, list1})

(* extract points *)

points1=list1[[All,{1,2}]];
points2=list2[[All,{1,2}]];

(* build a "nearest-function" for matching them *)

nf=Nearest[points1]

(* two points match only if they're closer than threshold *)
threshold=100;

(* This function will find the match of a point from points2 in points1.  
   If there's no match, the point is discarded using Sequence[]. *)
match[point_]:= 
   With[{m=First@nf[point]}, 
       If[Norm[m-point]<threshold, {m,point}, Unevaluated@Sequence[]]
   ]

(* find matching point-pairs *)
matches=match/@points1;

(* build hash tables to retrieve the properties associated with points quickly *)
Clear[values1,values2]
Set[values1[{#1,#2}],#3]&@@@list1;
Set[values2[{#1,#2}],#3]&@@@list2;

(* get the property-pairs *)
{values1[#1],values2[#2]}&@@@matches

Альтернативой является использование пользовательского DistanceFunction в ближайшем, чтобы избежать использования values1 & values2, и иметь более короткую программу,Это может быть медленнее или быстрее, я вообще не тестировал большие данные.

Примечание: Насколько сложной должна быть реализация, зависит от вашего конкретного набора данных.У каждой точки первого набора есть совпадение во втором?Есть ли дубликаты?Насколько близко могут быть точки из одного набора данных?И т. Д. Я попытался предоставить что-то, что можно настроить относительно надежно, за счет более длинного кода.

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