# Calculate the Mean of lists of the same length

I have the function

genList[n0_]:=Module[{n=n0,list3},list3={0};Do[AppendTo[list3,(RandomChoice[Range[0,100],1][[1]])];If[MemberQ[Drop[list3,-1],Last@list3],Break[]],{i,1,n}];Return[list3]]


Which generates the list of integers 0 to 100 until the list becomes non-unique or until the target $$n0$$ is hit.

From this I generate list of lists.

listoflists = Table[genList[100],{i,1,100}]


Now if two list are the same length I want to calculate the mean of their components. That is I have to use Mean@Flatten@.... If there is a list of unique length I just need the mean of that list.

I've tried using function like GroupBy[#,Length] but I've had no luck.

## 4 Answers

Using the listoflists:

SeedRandom[1];
listoflists = Table[genList[100], {i, 1, 100}];
mlists = GroupBy[listoflists, Length -> Mean] // KeySort


<|2 -> {0}, 3 -> {29}, 4 -> {151/4}, 5 -> {199/5, 142/5, 149/5, 318/5, 158/5, 38, 167/5}, 6 -> {127/3, 131/3, 161/3, 95/3}, 7 -> {150/7, 243/7, 333/7, 423/7, 293/7, 202/7, 419/7, 334/7}, 8 -> {131/4, 363/8, 95/2}, 9 -> {541/9, 473/9, 286/9, 623/9, 391/9, 305/9, 137/3, 484/9, 464/9}, 10 -> {489/10, 26, 47, 493/10, 186/5, 449/10, 549/10, 242/5, 583/10, 43, 261/5}, 11 -> {459/11, 574/11, 496/11, 324/11, 538/11, 269/11}, 12 -> {93/2, 239/6, 457/12, 649/12, 475/12, 33, 43}, 13 -> {484/13, 538/13, 543/13, 849/13}, 14 -> {657/14, 575/14, 689/14}, 15 -> {796/15, 724/15, 39, 598/15, 763/15, 556/15, 628/15}, 16 -> {639/16}, 17 -> {790/17, 944/17, 937/17, 668/17, 838/17, 1138/17, 747/17}, 18 -> {941/18, 527/9, 911/18}, 19 -> {905/19, 974/19}, 20 -> {471/10}, 21 -> {365/7, 381/7, 1063/21, 1273/21, 312/7, 1051/21, 857/21, 375/ 7}, 22 -> {1009/22, 541/11, 566/11}, 23 -> {1364/23}, 26 -> {1277/26}, 29 -> {1267/29}|>

Also try:

mNlists = GroupBy[listoflists, Length -> N@*Mean] // KeySort


UPDATE

To further reduce the lists generated, use an additional argument:

mlists2 = GroupBy[listoflists, Length -> Mean, Mean] // KeySort


<|2 -> 0, 3 -> 29, 4 -> 151/4, 5 -> 189/5, 6 -> 257/6, 7 -> 2397/56,
8 -> 335/8, 9 -> 442/9, 10 -> 5101/110, 11 -> 1330/33, 12 -> 3529/84, 13 -> 1207/26, 14 -> 1921/42, 15 -> 310/7, 16 -> 639/16, 17 -> 866/17, 18 -> 1453/27, 19 -> 1879/38, 20 -> 471/10, 21 -> 8543/168, 22 -> 293/6, 23 -> 1364/23, 26 -> 1277/26, 29 -> 1267/29|>

• I've wanted to have the Mean of the Flattened lists. You generate List of Means. For future readers this can be achieved by 'Map[Mean, mlists]'. (Mean of multiple "Means" is the same as Mean of the whole set if they have the same weight. Which they have thanks to the same length.) Oct 26, 2023 at 12:28
• Thanks for the accept. Please see update.
– Syed
Oct 26, 2023 at 12:34

One of the ways is as follows.

Table[Mean@Flatten[GatherBy[listoflists, Length][[j]]],
{j, 1,  Dimensions[GatherBy[listoflists, Length]][[1]]}]


{779/16, 4582/105, 27, 392/9, 0, 521/15, 332/9, 4747/99, 3404/81, 2251/48, 2461/50, 1134/25, 1039/21, 1319/27, 2973/56, 4164/95, 1422/35, 3131/80, 39/2, 2421/52, 3527/72, 525/11, 2398/51, 1373/27, 1473/31, 1112/23}

Another possibility with Merge:

list = Table[genList[100], {i, 1, 100}];

res = Merge[Mean @* N] @ MapApply[{Length[{##}] -> {##}} &] @ list;


A simple query:

res[3]


{0., 67., 27.5}

Use Flatten to move up one level:

res = Merge[Mean @* Flatten @* N] @ MapApply[{Length[{##}] -> {##}} &] @ list;

res[3]


31.5

Transform Association to List:

KeyValueMap[List] @ res


{{2, 0.}, {3, 31.5}, {4, 5.5}, {5, 33.}, {6, 36.1667}, {7, 42.2286}, {8, 40.875}, {9, 48.7619}, {10, 49.0667}, {11, 39.6364}, {12, 53.0139}, {13, 46.7019}, {14, 42.7946}, {15, 45.4333}, {16, 54.75}, {17, 46.7206}, {18, 52.9167}, {19, 46.}, {20, 51.6833}, {21, 52.5119}, {22, 48.8636}, {23, 53.}, {24, 50.3611}, {26, 51.4038}}

Although not an answer to your question, I should point out that your genList function could be coded more efficiently; for example,

genList2[n0_] := NestWhileList[RandomInteger[100] &, 0, UnsameQ, All, n0]


This function runs about 2.5 times as fast as yours. I'm sure that others who are more skilled than I, could improve upon this even further.

Note that in either case, genList will always generate a $$0$$ as the first element of the list, and the last element will be a duplicate of another element except when the list reaches a length of $$n_0 + 1$$. You could easily modify this if needed.

As for the means by length groups, GroupBy is the natural choice, as shown in the already accepted answer.

• Thanks for the comment. I wrote the function in the way I did since I will later accumulate to each new element. Is it possible to apply Accumulate to your function? Oct 27, 2023 at 8:48
• @Nitaaa the output of my version of your function is equivalent to yours. They both return lists. Why don't you try it? Oct 27, 2023 at 14:45