Create list of given length with given values - convert histogram to list of values
<p>I have a histogram which I need to convert into a list of individual instances for another piece of software I am using: If I have four hits for a value of "1" and three hits for a value of "2" then my list would need to read <code>[1,1,1,1,2,2,2]</code>.</p>

<p>My histogram is structured as two numpy arrays packed into a list called <code>hist</code>, say. The array in <code>hist[1]</code> stores my bin edges, the array in <code>hist[0]</code> stores the counts for each bin.</p>

<p>A very crude way of achieving this conversion would be to simply run the following code:</p>

<pre><code>inhist=[]
for i in range(len(hist[0])):
   for j in xrange(int(hist[0][i])):
       inhist.append(int(hist[1][i]))
</code></pre>

<p>Is there a better way of doing this? Particularly as the histogram gets very large this will presumably not be the most efficient way of achieving this anymore. Seeing as I know precisely how many time I want a certain value I wonder if I could save myself all that looping? </p>

<p>I realise doing this whole thing in general will eat RAM and isn't terribly efficient but, alas, I have little choice at the moment.</p>

<p>EDIT:
<code>print hist</code> returns:</p>

<pre><code>[array([  0.00000000e+00,   1.83413630e+07,   1.74493106e+09,
          7.91390628e+10,   4.54474023e+11,   5.38810039e+11,
          3.01718080e+11,   1.38440761e+11,   6.17865624e+10,
          2.77457730e+10,   1.32412328e+10,   6.71579967e+09,
          3.35556066e+09,   2.00513046e+09,   1.18435261e+09,
          7.34440685e+08,   5.13846805e+08,   3.97894623e+08,
          1.97770421e+08,   1.11546165e+08,   6.63624300e+07,
          3.93196820e+07,   2.81038760e+07,   1.87733930e+07,
          1.57307950e+07,   1.55162030e+07,   1.38710060e+07,
          3.52969100e+06,   2.32881000e+05,   5.32210000e+04,
          1.59100000e+04,   4.89700000e+03,   1.61300000e+03,
          6.54000000e+02,   2.63000000e+02,   1.08000000e+02,
          3.10000000e+01,   8.00000000e+00,   4.00000000e+00,
          2.00000000e+00]),
 array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
        34, 35, 36, 37, 38, 39, 40], dtype=uint64)]
</code></pre>

<p>Those <code>i</code> indices are basically range of elements ranging for the length of number of <code>hist[0]</code> elements repeated by the numbers present in that first array <code>hist[0]</code> itself. Using those we simply index into the second array <code>hist[1]</code> to give us the desired output. For the <code>repeat</code> part, we could use <a href="http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.repeat.html" rel="nofollow"><code>np.repeat</code></a>.</p>

<p>So, we would have an implementation, like so -</p>

<pre><code>inhist = hist[1][np.arange(len(hist[0])).repeat(hist[0])]
</code></pre>

<p>Being a vectorized solution that avoids appending elements off NumPy arrays, this should be pretty efficient.</p>

<p>Also, if we are working with NumPy arrays of floating point numbers, we might need to convert to <code>int</code> dtype. So, feed in <code>hist[0].astype(int)</code> and if the output is needed as <code>int</code> dtype too, use the same conversion on it, like so -</p>

<pre><code>inhist = hist[1][np.arange(len(hist[0])).repeat(hist[0].astype(int))]
</code></pre>

python arrays list numpy