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
  • 2
    $\begingroup$ Dataset[Total /@ GroupBy[tlist, First -> Last]] $\endgroup$
    – b3m2a1
    Dec 22, 2019 at 0:42
  • 6
    $\begingroup$ Also Dataset@GroupBy[tlist, First -> Last, Total] $\endgroup$
    – Bob Hanlon
    Dec 22, 2019 at 1:52

1 Answer 1

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

$\endgroup$
1
  • 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, 2019 at 11:17

Your Answer

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

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