By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,714 Members | 750 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,714 IT Pros & Developers. It's quick & easy.

A matrix problem. Please help!

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

Jul 18 '05 #1
Share this Question
Share on Google+
4 Replies


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

Jul 18 '05 #2

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

Jul 18 '05 #3

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

Jul 18 '05 #4

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
Jul 18 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.