title: How to optimize a numpy loop that sums values from an array which is indexed by another array where values equal the loop index
body: <p>I have this piece of code that is called multiple times during the run of the application.
  It takes an array of numbers which represent values (value_array).
  These should be summed up in zones, which are defined in the zone_array.
  zone_ids represents a list of all the possible zones in zone_array.</p>
  
  <p>Its basically something in the lines of: i got a population raster map and i want to know how many people live in each zone of the zone map.</p>
  
  <p>the code:</p>
  
  <pre><code>values = np.zeros(len(zone_ids))
  for i in zone_ids:
      values[i] = round(np.nansum(value_array[zone_array == i]), 2)
  return values
  </code></pre>
  
  <p>The culprit seems to be the for loop, but i have not found a way to eliminate it and have the same results.</p>
  
  <p>I tried it with bincount but i did not succeed.
  Using numba jit also has no effect.</p>
  
  <p>I would like to stay away from cython as this code will be used in a Qgis plugin which has no cython support.</p>
  
  <p>test code:</p>
  
  <pre><code>import numpy as np
  
  
  def fill_values(zone_array, value_array, zone_ids):
      values = np.zeros(len(zone_ids))
      for i in zone_ids:
          values[i] = round(np.nansum(value_array[zone_array == i]), 2)
      return values
  
  
  def run():
      # 300 different zones
      zone_ids = range(300)
      # zone map with 300 zones
      zone_array = (np.random.rand(2000, 2000) * 300).astype(int)
      # value map from which we want the sum of values per zone (real map can have NaN values)
      value_array = (np.random.rand(2000, 2000) * 10.)
      value_array[5, 5] = np.NAN
      fill_values(zone_array, value_array, zone_ids)
  
  
  if __name__ == '__main__':
      run()
  </code></pre>
  
  <p>1.92 s ± 17.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)</p>
  
  <p>With the implementation of bincount as suggested by Divakar :</p>
  
  <p>203 ms ± 15.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)</p>