# Weighted random choice from a list

I want to randomly choose one element from a list but preferring elements with small distance from the center of a list. How to do it properly say with normal distribution? I am not good at statistics.

My ugly code (with unknow distribution (of triangle-like shape)):

li = Range;
Table[RandomChoice[
Join[Range[1, Floor[Length[#]/2]],
Range[Ceiling[Length[#]/2], 1, -1]] -> #], {i, 1000}] &@li;
ListPlot[% // Tally]
Clear[li]


Update:

Based on the answers and comments I came to the conclusion that there is no elegant solution of choosing random element from a list preferring those near the middle of the list resembling normal distribution.

Here is the code combined of comments and answers that uses normal distribution with standard deviation dev.

li=Range;
le=Length[li];
dev=1;
RandomChoice[(PDF[NormalDistribution[0,dev],#]&/@Subdivide[-le/2,le/2,le-1]//N//Chop//Quiet)->li]
Clear[li,le,dev]

• I am not sure I understood, taking distribution[x_]=exp(-x^2), is RandomChoice[distribution/@ Subdivide[-5,5,Length[list]-1]-> list,10000] a solution ? Aug 11, 2022 at 22:15
• So what would you do with this unequal probability sampling method? For example, you wouldn't want to use the usual estimators for the population mean as those would be biased. Don't get me wrong: unequal probability sampling can be much, much better than simple random sampling. But the selection of the probabilities and then the associated population parameter estimators need to be fine tuned.
– JimB
Aug 11, 2022 at 22:28

If your context is complicated, this might not work, but my initial thought was to use WeightedData. You can apply RandomChoice directly to WeightedData.

RandomChoice[WeightedData[Range@10, 1/Abs[Range@10 - 5.5]], 10]
(* {6, 10, 6, 6, 7, 6, 6, 7, 4, 4} *)


I made up a weighting scheme,

1/Abs[Range@10 - 5.5
(* {0.222222, 0.285714, 0.4, 0.666667, 2., 2., 0.666667, 0.4, 0.285714, 0.222222} *)


but you could use anything you want, like something to approximate a normal distribution.

• Not a good solution. It depends on length of the list I want to choose from - whether it's length is even or odd. For odd length you then got 1/0 error. Aug 12, 2022 at 6:32

Even though @lericr beat me with a more elegant solution, I am providing another approach.

You can generate a discrete probability distribution for list indices, then sample from it.

list = Range[10, 50, 3]
(* {10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49} *)

sigma = 2;
dist = ProbabilityDistribution[
PDF[NormalDistribution[(Length[list] + 1)/2, sigma]][i], {i, 1,
Length[list], 1}];

sample = list[[RandomVariate[dist, 1000000]]];

Histogram[sample, {Min[list], Max[list] + 1, 1}] li=Range;
le=Length[li];
RandomChoice[Table[Binomial[le-1,n],{n,0,le-1}]->li,100000];
ListPlot[%//Tally,PlotRange->All]
Clear[li,le,dev] 