[Matrix-SIG] QUERY: Array indexing
Tim Peters
tim_one@email.msn.com
Fri, 12 Mar 1999 02:29:13 -0500
[Perry Stoll, locates an old timbot gather/scatter tutorial]
[Frank Horowitz chews & chews, but is still hungry]
> Thanks for that "incomparable Tim Peters" citation; that's a fascinating
> thread (have I sucked up enough yet? :-).
No. Keep going! We'll let you know when it's enough <wink>.
> My applications require local references in the array (somewhat akin to
> finite difference/convolution templates) but the operations I need to
> perform are more general than multiply-and-sum, hence I can't use the
> recent n-d convolve routines from Travis Oliphant (or was it someone
> else; senility is obviously setting in...)
>
> My approach to date has been to build shifted/rolled versions of the
> array, and operate with them (code available upon request, if anyone is
> silly enough to want it :-). Obviously, this comes at a severe cost in
> memory ...
I don't know the best way to approach this in NumPy, perhaps because I
haven't yet installed it <wink>. In straight Python I do stuff like this by
writing thin wrapper classes that leave the original matrices alone, merely
permuting the *indices* in __setitem__/__getitem__ (instead of physically
permuting the *data*). For example, if your need to transpose a 2D array,
just swap the indices in the wrappers before passing them on to the actual
(still untransposed) array.
Here's an overly simplistic but complete example:
class VectorRotate:
def __init__(self, data, shift):
"""Make data act as if it had been rotated left by shift slots"""
self.x = data
self.n = len(data)
self.shift = shift
def __getitem__(self, i):
return self.x[(i + self.shift) % self.n]
def __setitem__(self, i, val):
self.x[(i + self.shift) % self.n] = val
def __len__(self):
return self.n
def getdata(self):
return self.x
vec = range(10)
print vec
r = VectorRotate(vec, 3)
r[0] = "hmm!"
for i in range(len(r)):
print i, r[i]
print r.getdata()
That prints:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
0 hmm!
1 4
2 5
3 6
4 7
5 8
6 9
7 0
8 1
9 2
[0, 1, 2, 'hmm!', 4, 5, 6, 7, 8, 9]
If you want to get really fancy, you can define arbitrarily complex
N-dimensional "mapping objects" independent of specific matrices, and
manipulate them for their own sake, reluctantly applying them to actual
matrices when deadlines get too close <wink>.
> It seems to me that something like this gather operation would do the
> trick, with one hell of a lot less memory thrashing, but I can't quite
> fathom the idiom for generating an indexing sequence that says something
> like "one over in the plus X direction at the same time as one over in the
> negative Z direction" .
If the above was suggestive enough, I expect you'll find this kind of thing
easier than gather/scatter. Yes?
> ...
> Wisdom anyone? (Tim? :-)
Sorry, you didn't suck up enough to get a wise answer!
although-you're-off-to-a-fine-start-ly y'rs - tim