My task is quite simple; I have a table of data like
M = {{1,2}, {1,3}, {3,4}, {5,1}, {6,9}, {6,8}, {6,1}};
so the table is sorted with respect to the first entry of each tuple. What I want is basically to gather tuples with the same 'x' entry in a new one. M would look like this:
M = {{1,(2+3)/2}, {3,4}, {5,1}, {6,(9+8+1)/3}};
This can be possibly solved elegantly with some gathering and application of summation and counting, but since I'm a C speaker, I've taken the For loop as my first try:
Stringed = ConstantArray[{-1., -1.}, Dimensions[StoreFlat][[1]]]; (* this is
the array where all the data will be stored in. StoreFlat is the sorted but
"uncollected" input *)
Module[{i = 1, j = 1, k = 1, a = 1., f = 1.},
Monitor[
For[i = 1, i <= Dimensions[StoreFlat][[1]], i++, (* loop over the number of tuples *)
If[i == 1, (* first entry *)
f = StoreFlat[[1, 1]];
a = StoreFlat[[1, 2]];,
If[f == StoreFlat[[i, 1]], (* a tuple exists already with this entry *)
a += StoreFlat[[i, 2]];
k++;,
f = StoreFlat[[i, 1]]; (* this entry is larger than the former one *)
a = StoreFlat[[i, 2]];
j++; k = 1;
];
];
Stringed[[j]] = {f, a/k}; (* output. the second entry is divided by the number of
entries. *)
],
ProgressIndicator@N[i/Dimensions[StoreFlat][[1]]]
]
];
I know that this is probably not the fastest way. But since my input is not too larger (190 000 tuples of a real, floating point value) this should do the job. Is anything wrong about my approach? On my laptop, this thing takes a lot of time (10 to 20 minutes, I guess - I cancelled it).
GatherBy
. Your task can be implemented as a one-liner, and be fast. If you want to use the language effectively, you need to use its own idioms, rather than porting code from other languages you already know. $\endgroup$Stringed = GatherBy[StoreFlat, #[[1]] &]; Map[{#[[1, 1]], Mean[#[[All, -1]]]} &, Stringed]
to solve my problem! $\endgroup$