title: Numpy : Grouping/ binning values based on associations
body: <p><code>Forgive me for a vague title. I honestly don't know which title will suit this question. If you have a better title, let's change it so that it will be apt for the problem at hand.</code></p>
  
  <h2>The problem.</h2>
  
  <p>Let's say <code>result</code> is a 2D array and <code>values</code> is a 1D array. <code>values</code> holds some values associated with each element in <code>result</code>. The mapping of an element in <code>values</code> to <code>result</code> is stored in <code>x_mapping</code> and <code>y_mapping</code>. A position in <code>result</code> can be associated with different values. Now, I have to find the sum of the values grouped by associations.</p>
  
  <p>An example for better clarification.</p>
  
  <p><code>result</code> array:</p>
  
  <pre><code>[[0, 0],
  [0, 0],
  [0, 0],
  [0, 0]]
  </code></pre>
  
  <p><code>values</code> array:</p>
  
  <pre><code>[ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.]
  </code></pre>
  
  <p>Note: Here <code>result</code> and <code>values</code> have the same number of elements. But it might not be the case. There is no relation between the sizes at all.</p>
  
  <p><code>x_mapping</code> and <code>y_mapping</code> have mappings from 1D <code>values</code> to 2D <code>result</code>. The sizes of <code>x_mapping</code>, <code>y_mapping</code> and <code>values</code> will be the same.</p>
  
  <p><code>x_mapping</code> - <code>[0, 1, 0, 0, 0, 0, 0, 0]</code></p>
  
  <p><code>y_mapping</code> - <code>[0, 3, 2, 2, 0, 3, 2, 1]</code> </p>
  
  <p>Here, 1st value(<code>values[0]</code>) have x as 0 and y as 0(<code>x_mapping[0]</code> and <code>y_mappping[0]</code>) and hence associated with <code>result[0, 0]</code>. If we are counting the number of associations, then element value at <code>result[0,0]</code> will be 2 as 1st value and 5th value are associated with <code>result[0, 0]</code>. If we are taking the sum, the <code>result[0, 0] = value[0] + value[4]</code> which is 6.</p>
  
  <h2>Current solution</h2>
  
  <pre><code># Initialisation. No connection with the solution.
  result = np.zeros([4,2], dtype=np.int16)
  
  values =  np.linspace(start=1, stop=8, num=8)
  y_mapping = np.random.randint(low=0, high=values.shape[0], size=values.shape[0])
  x_mapping = np.random.randint(low=0, high=values.shape[1], size=values.shape[0])
  # Summing the values associated with x,y (current solution.)
  for i in range(values.size):
      x = x_mapping[i]
      y = y_mapping[i]
      result[-y, x] = result[-y, x] + values[i]
  </code></pre>
  
  <p>The <code>result</code>,</p>
  
  <pre><code>[[6, 0],
  [ 6, 2],
  [14, 0],
  [ 8, 0]]
  </code></pre>
  
  <h2>Failed solution; But why?</h2>
  
  <pre><code>test_result = np.zeros_like(result)
  test_result[-y_mapping, x_mapping] = test_result[-y_mapping, x_mapping] + values # solution
  </code></pre>
  
  <p>To my surprise elements are overwritten in <code>test_result</code>. Values at <code>test_result</code>,</p>
  
  <pre><code>[[5, 0],
  [6, 2],
  [7, 0],
  [8, 0]]
  </code></pre>
  
  <h2>Question</h2>
  
  <h3>1. Why, in the second solution, every element is overwritten?</h3>
  
  <p>As @Divakar has pointed out in the comment in his answer - 
  NumPy doesn't assign accumulated/summed values when the indices are repeated in <code>test_result[-y_mapping, x_mapping] =</code>. It randomly assigns from one of the instances.</p>
  
  <h3>2. Is there any Numpy way to do this? That is without looping? I'm looking for some speed optimization.</h3>
  
  <p>Approach #2 in @Divakar's answer gives me good results. For 23315 associations, <code>for</code> loop took 50 ms while Approach #1 took 1.85 ms. Beating all these, Approach #2 took 668 µs.</p>
  
  <h2>Side note</h2>
  
  <p>I'm using Numpy version 1.14.3 with Python 3.5.2 on an i7 processor.</p>