5
$\begingroup$

So lets say I have a list of spending transactions tlist = {{john,23},{bob,2},{john,7}...} and I want to have a list of the total expenses per person.

I can do this procedurally by iterating over the transactions in tlist using a for loop. If their name is not yet in the expense list, I add it as a row, with the corresponding spending. If their name is in the expense list, I add the transaction amount to their total.

This is fine, but I am aware that for loops are frowned upon in Mathematica, and are relatively inefficient. So, what would be the proper, "good code" way of doing this?

$\endgroup$
  • 2
    $\begingroup$ Dataset[Total /@ GroupBy[tlist, First -> Last]] $\endgroup$ – b3m2a1 Dec 22 '19 at 0:42
  • 5
    $\begingroup$ Also Dataset@GroupBy[tlist, First -> Last, Total] $\endgroup$ – Bob Hanlon Dec 22 '19 at 1:52
8
$\begingroup$

GroupBy is very helpful function for exploring data. This answer is an extension of Bob Hanlon's comment where more structure has been added to the sample data.

First, some random names

names = WolframAlpha[ToString[100] <> " random surnames", {{"Result", 1},"ComputableData"}]; 

Then a modified list

tlist =  Table[<|"name" -> RandomChoice[names], 
"expense" -> RandomReal[{1, 1000}], 
"age" -> RandomReal[{23, 56}]|>, {i, 1, 10000}]; 

Then to find the total expense for each person

res = GroupBy[tlist, #["name"] &, Total[#[[All, {"expense"}]]] &]

and to format the output

Dataset[res]

Example output

| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ +1 You might also want to sort: Manipulate[ Dataset[res] // SortBy[#, sort] &, {{sort, "name", "Sort By"}, {"name", "expense"}}] $\endgroup$ – Bob Hanlon Dec 22 '19 at 11:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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