1
$\begingroup$

I am looking for a way to iteratively select all sublists with the same ID (my 1st column, residual columns are AbsoluteTime entries). First, I obtained the list of unique IDs with Union. Then I want to use this list for the selection task. I assume that it must work with Sequence and ReplaceAll, but could not make it work. Here's what I have so far:

ticketList = Union[dataList[[1 ;;, 1]]];
tempList = Select[dataList, #1[[1]] == x &] /. x ->  Sequence[ticketList];

My ultimate goal is to build up a TemporalData array with all items which each belong to the same ID.

My data is has dimensions n x m. The ticket list has dimension t. The resulting table should have dimensions t x i x m, where i is the cardinality of items with the same ID, and the i's sum to n. I assumed, that I can then map TemporalData on every t-th item in order to build the temporal list.

I searched the site but didn't find a previous question that seem to address my problem. Maybe I misunderstood the use cases of similiar questions.

$\endgroup$
2

2 Answers 2

4
$\begingroup$

Here's an attempt to address your question based on the sort of data I imagine you have in mind. First, some data. Note: the integers are understood to be ID's.

times = RandomReal[{0, 100}, {20, 5}];
ids = RandomInteger[4, 20];
data = Transpose[Prepend[Transpose[times], ids]]

{{1, 95.2049, 98.1609, 35.1946, 32.636, 81.2383}, {3, 92.8072, 36.0249, 68.3793, 54.1311, 95.1051}, {3, 4.26078, 47.9919, 31.627, 53.0064, 96.8995}, {4, 18.2792, 94.4752, 5.66575, 5.62435, 35.8945}, {4, 67.4149, 68.1577, 25.281, 17.8322, 15.3123}, {2, 77.6343, 35.3486, 81.3541, 73.6091, 51.4884}, {0, 28.5346, 29.2705, 78.9446, 32.2112, 7.05296}, {4, 91.9405, 79.4176, 75.6947, 72.1069, 5.94247}, {2, 11.0662, 24.4381, 79.5328, 20.2195, 79.4703}, {0, 61.6779, 73.8532, 61.5861, 7.79641, 38.3836}, {4, 52.3064, 95.9954, 62.3701, 34.7654, 99.8931}, {2, 92.6636, 57.8744, 23.4167, 76.3724, 44.8631}, {2, 73.7149, 84.6716, 36.1234, 89.5432, 39.8183}, {3, 50.4444, 7.98911, 69.4092, 96.3191, 79.6566}, {3, 41.2261, 58.5009, 57.7989, 58.9187, 8.87187}, {4, 53.5552, 11.3278, 8.24034, 67.3065, 19.4648}, {2, 19.9501, 30.5649, 73.9395, 13.3722, 36.5546}, {3, 96.5631, 19.1948, 23.226, 92.8776, 64.4002}, {0, 65.9084, 10.2902, 8.83754, 93.0831, 36.464}, {1, 18.2795, 12.4673, 42.0253, 39.8816, 50.8252}}

Now to gather the records that have the same id:

GatherBy[data, First]//TableForm

Mathematica graphics

$\endgroup$
3
  • $\begingroup$ That's exactly what I was aiming for and the absolute elegant solution. I am sorry that I did not find GatherBy in the manual. Sometimes the power of MM is really amazing / overwhelming. $\endgroup$
    – Frank
    Mar 10, 2013 at 19:57
  • $\begingroup$ Thanks. Yes, Mathematica knows many useful ways to manipulate lists. BTW, if you wanted the id's to appear in standard order, you might do a SortBy[data,First] before GatherBy. $\endgroup$
    – DavidC
    Mar 10, 2013 at 20:37
  • $\begingroup$ Actually, Sort[data] is sufficient if it's inside the GatherBy. $\endgroup$
    – DavidC
    Mar 10, 2013 at 22:18
3
$\begingroup$

Using @David's example data

 times = RandomReal[{0, 100}, {20, 5}]; 
 ids =   RandomInteger[4, 20]; 
 data = Transpose[Prepend[Transpose[times], ids]];

"few" more alternatives (none as elegant as David's answer):

 dt1 = Select[data, (#1[[1]] == x) & /. x -> #] & /@  Union[data[[All, 1]]];
 dt2 = Function[{xx}, Select[data, #[[1]] == xx &]] /@ Union@data[[All, 1]];
 dt3 = Cases[data, {#, __}] & /@ Union[data[[All, 1]]];
 dt4 = DeleteCases[data, Except[{#, __}]] & /@ Union[data[[All, 1]]];
 dt5 = Pick[data, data[[All, 1]], #] & /@ Union@data[[All, 1]];
 dt6 = Pick[data, data[[All, 1]] - #, 0] & /@ Union@data[[All, 1]];
 dt7 = SplitBy[SortBy[data, {First}], First];
 dt8 = SortBy[GatherBy[data, First], First];
 dt9 = GatherBy[SortBy[data, {First}], First];
 dt10 = Extract[data, #] & /@ Position[data, {#, __}] & /@ Union[data[[All, 1]]];
 dt11 = data[[#]] & /@ Join @@ Position[data, {#, __}] & /@ Union[data[[All, 1]]];
 dt12 = Reap[Sow[#, First[#]] & /@ SortBy[data, {First}]][[2]];
 dt1 == dt2 == dt3 == dt4 == dt5 == dt6 == dt7 == dt8 == dt9 == dt10 == dt11 == dt12
 (* True *)

Note: If the ordering of the elements in the sublists does not matter, Last@Reap[Sow[#, First[#]] & /@ data] gives the same result as GatherBy[data,First]:

 GatherBy[data,First]==Last@Reap[Sow[#, First[#]] & /@ data]
 (* True *)
$\endgroup$
8
  • $\begingroup$ Whatever I had you've plainly caught. Get well soon! xD $\endgroup$
    – Mr.Wizard
    Mar 11, 2013 at 0:20
  • $\begingroup$ Also, where the devil is Sow & Reap? $\endgroup$
    – Mr.Wizard
    Mar 11, 2013 at 0:20
  • $\begingroup$ @Mr.Wizard, added Reap[Sow[...]...]:) $\endgroup$
    – kglr
    Mar 11, 2013 at 0:45
  • $\begingroup$ Another one for your list: Reap[{##} ~Sow~ # & @@@ data, Union[First /@ data]][[2, All, 1]] -- no claims of efficiency. $\endgroup$
    – Mr.Wizard
    Mar 11, 2013 at 0:59
  • $\begingroup$ I think in many cases, SortBy[data,{First}] may be simplified to Sort[data]. $\endgroup$
    – DavidC
    Mar 11, 2013 at 1:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.