P: n/a

I have the following matrix that I want to transform:
import random
import Numeric as N
ru = []
for i in range(25):
ru.append(int(random.uniform(0, 2)))
ru = N.reshape(ru, (5, 5)) ru
array([[1, 0, 1, 1, 1],
[0, 1, 1, 1, 0],
[1, 1, 0, 0, 1],
[0, 1, 0, 0, 1],
[1, 1, 0, 1, 1]])
Trailing numbers (ie, from left to right) after the first encounter of a "1"
for all rows should equal "0".
Thus, I want this:
ru
array([[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[1, 0, 0, 0, 0]])
Does anyone have a suggestion of a fast and easy way to accomplish the
above?
Carl  
Share this Question
P: n/a

Carl wrote: I have the following matrix that I want to transform:
import random import Numeric as N ru = [] for i in range(25): ru.append(int(random.uniform(0, 2))) ru = N.reshape(ru, (5, 5))
ru array([[1, 0, 1, 1, 1], [0, 1, 1, 1, 0], [1, 1, 0, 0, 1], [0, 1, 0, 0, 1], [1, 1, 0, 1, 1]])
Trailing numbers (ie, from left to right) after the first encounter of a "1" for all rows should equal "0".
Thus, I want this: ru array([[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [1, 0, 0, 0, 0]])
Does anyone have a suggestion of a fast and easy way to accomplish the above?
Carl
(Disclaimer: Numeric newbie code) import random import Numeric import itertools def oneone():
.... while 1:
.... r = int(random.uniform(0, 2))
.... yield r
.... if r: break
.... for r in itertools.repeat(0):
.... yield r
.... ru = Numeric.array([[x for x,y in itertools.izip(oneone(), range(5))]
for z in range(5)]) ru
array([[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[1, 0, 0, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 1, 0, 0]])
Or, more seriously, i. e. assuming that you have no influence on the initial
matrix:
r
array([[1, 1, 1],
[0, 1, 1],
[0, 0, 1]]) for i in r:
.... for k in Numeric.nonzero(i)[1:]:
.... i[k] = 0
.... r
array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
Peter  
P: n/a

Peter Otten wrote: Carl wrote:
I have the following matrix that I want to transform:
import random import Numeric as N ru = [] for i in range(25): ru.append(int(random.uniform(0, 2))) ru = N.reshape(ru, (5, 5))
> ru array([[1, 0, 1, 1, 1], [0, 1, 1, 1, 0], [1, 1, 0, 0, 1], [0, 1, 0, 0, 1], [1, 1, 0, 1, 1]])
Trailing numbers (ie, from left to right) after the first encounter of a "1" for all rows should equal "0".
Thus, I want this:
> ru array([[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [1, 0, 0, 0, 0]])
Does anyone have a suggestion of a fast and easy way to accomplish the above?
Carl
(Disclaimer: Numeric newbie code)
import random import Numeric import itertools def oneone(): ... while 1: ... r = int(random.uniform(0, 2)) ... yield r ... if r: break ... for r in itertools.repeat(0): ... yield r ... ru = Numeric.array([[x for x,y in itertools.izip(oneone(), range(5))] for z in range(5)]) ru array([[0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [1, 0, 0, 0, 0], [0, 0, 0, 1, 0], [0, 0, 1, 0, 0]]) Or, more seriously, i. e. assuming that you have no influence on the initial matrix: r array([[1, 1, 1], [0, 1, 1], [0, 0, 1]]) for i in r: ... for k in Numeric.nonzero(i)[1:]: ... i[k] = 0 ... r
array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
Peter
Thanks Peter,
This:
for i in ru:
for k in N.nonzero(i)[1:]:
i[k] = 0
works very nice, but I'm a little worried about performance problem, since
the matrix ru is typically of size 10,000 to 100,000 rows by 10 to 60
columns.
I have tried to figure out how to do it without loops, but have not managed
to do that yet.
Carl  
P: n/a

Well, my strategy is to get a new array with 1 in the spots where you
want a 1 in the output, and other values elsewhere. Then I can use
comparison to get a (boolean) array with 1s in the right place
I didn't find a satisfactory way to do that, but here's one that seemed
to work: ru
array([[0, 0, 1, 0, 1],
[1, 0, 0, 1, 1],
[0, 0, 0, 1, 1],
[1, 1, 1, 0, 0],
[1, 1, 0, 1, 0]]) N.add.accumulate(N.add.accumulate(ru, 1), 1)
array([[ 0, 0, 1, 2, 4],
[ 1, 2, 3, 5, 8],
[ 0, 0, 0, 1, 3],
[ 1, 3, 6, 9, 12],
[ 1, 3, 5, 8, 11]]) _ == 1
array([[0, 0, 1, 0, 0],
[1, 0, 0, 0, 0],
[0, 0, 0, 1, 0],
[1, 0, 0, 0, 0],
[1, 0, 0, 0, 0]], type=Bool)
The first accumulate makes everything to the left of a 1 >0, and the
second accumulate makes it >1.
Jeff  
P: n/a

Jeff Epler wrote: Well, my strategy is to get a new array with 1 in the spots where you want a 1 in the output, and other values elsewhere. Then I can use comparison to get a (boolean) array with 1s in the right place
I didn't find a satisfactory way to do that, but here's one that seemed to work: ru array([[0, 0, 1, 0, 1], [1, 0, 0, 1, 1], [0, 0, 0, 1, 1], [1, 1, 1, 0, 0], [1, 1, 0, 1, 0]]) N.add.accumulate(N.add.accumulate(ru, 1), 1) array([[ 0, 0, 1, 2, 4], [ 1, 2, 3, 5, 8], [ 0, 0, 0, 1, 3], [ 1, 3, 6, 9, 12], [ 1, 3, 5, 8, 11]]) _ == 1
array([[0, 0, 1, 0, 0], [1, 0, 0, 0, 0], [0, 0, 0, 1, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0]], type=Bool)
The first accumulate makes everything to the left of a 1 >0, and the second accumulate makes it >1.
Jeff
Jeff,
Your solution works very well. I tried to do something similar, but with
N.cumsum instead of N.add.accumuluate. However, I never did the second
step, so I ended up with two "1:s" in each row and was, therefore, never
able to do the booelan comparison.
Thanks for yopur help!
Carl   This discussion thread is closed Replies have been disabled for this discussion.   Question stats  viewed: 1076
 replies: 4
 date asked: Jul 18 '05
