The main reason for a flat index is allowing the use of `np.unique`. But it wouldn't be too hard to rewrite the functionality for two index arrays using `np.unique`'s [source code](https://github.com/numpy/numpy/blob/master/numpy/lib/arraysetops.py#L93) as a guide. It would also help performance, as calling `np.unique` sorts an already sorted array. And in the latest numpy master, the implementation can compute `unq_cnt` faster than calling `np.bincount` on `unq_inv`. It would look something like this:

```
order = np.lexsort((self.row,self.col))
self.row = self.row[order]
self.col = self.col[order]
self.data = self.data[order]
flag = np.concatenate(([True], (self.row[1:] != self.row[:-1]) | (self.col[1:] != self.col[:-1])))
self.row = self.row[flag]
self.col = self.col[flag]
add_idx = np.nonzero(flag)[0]
self.data = np.add.reduceat(self.data, add_idx)
```

This is probably even less readable, but I wouldn't be surprised if it was 2x faster.