A matrix problem. Please help!

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Carl

    A matrix problem. Please help!

    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(r andom.uniform(0 , 2)))
    ru = N.reshape(ru, (5, 5))
    [color=blue][color=green][color=darkred]
    >>> ru[/color][/color][/color]
    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:
    [color=blue][color=green][color=darkred]
    >>> ru[/color][/color][/color]
    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

  • Peter Otten

    #2
    Re: A matrix problem. Please help!

    Carl wrote:
    [color=blue]
    > 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(r andom.uniform(0 , 2)))
    > ru = N.reshape(ru, (5, 5))
    >[color=green][color=darkred]
    >>>> ru[/color][/color]
    > 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:
    >[color=green][color=darkred]
    >>>> ru[/color][/color]
    > 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[/color]

    (Disclaimer: Numeric newbie code)
    [color=blue][color=green][color=darkred]
    >>> import random
    >>> import Numeric
    >>> import itertools
    >>> def oneone():[/color][/color][/color]
    .... while 1:
    .... r = int(random.unif orm(0, 2))
    .... yield r
    .... if r: break
    .... for r in itertools.repea t(0):
    .... yield r
    ....[color=blue][color=green][color=darkred]
    >>> ru = Numeric.array([[x for x,y in itertools.izip( oneone(), range(5))][/color][/color][/color]
    for z in range(5)])[color=blue][color=green][color=darkred]
    >>> ru[/color][/color][/color]
    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]])[color=blue][color=green][color=darkred]
    >>>[/color][/color][/color]

    Or, more seriously, i. e. assuming that you have no influence on the initial
    matrix:
    [color=blue][color=green][color=darkred]
    >>> r[/color][/color][/color]
    array([[1, 1, 1],
    [0, 1, 1],
    [0, 0, 1]])[color=blue][color=green][color=darkred]
    >>> for i in r:[/color][/color][/color]
    .... for k in Numeric.nonzero (i)[1:]:
    .... i[k] = 0
    ....[color=blue][color=green][color=darkred]
    >>> r[/color][/color][/color]
    array([[1, 0, 0],
    [0, 1, 0],
    [0, 0, 1]])

    Peter

    Comment

    • Carl

      #3
      Re: A matrix problem. Please help!

      Peter Otten wrote:
      [color=blue]
      > Carl wrote:
      >[color=green]
      >> 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(r andom.uniform(0 , 2)))
      >> ru = N.reshape(ru, (5, 5))
      >>[color=darkred]
      >>>>> ru[/color]
      >> 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:
      >>[color=darkred]
      >>>>> ru[/color]
      >> 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[/color]
      >
      > (Disclaimer: Numeric newbie code)
      >[color=green][color=darkred]
      >>>> import random
      >>>> import Numeric
      >>>> import itertools
      >>>> def oneone():[/color][/color]
      > ... while 1:
      > ... r = int(random.unif orm(0, 2))
      > ... yield r
      > ... if r: break
      > ... for r in itertools.repea t(0):
      > ... yield r
      > ...[color=green][color=darkred]
      >>>> ru = Numeric.array([[x for x,y in itertools.izip( oneone(), range(5))][/color][/color]
      > for z in range(5)])[color=green][color=darkred]
      >>>> ru[/color][/color]
      > 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]])[color=green][color=darkred]
      >>>>[/color][/color]
      >
      > Or, more seriously, i. e. assuming that you have no influence on the
      > initial matrix:
      >[color=green][color=darkred]
      >>>> r[/color][/color]
      > array([[1, 1, 1],
      > [0, 1, 1],
      > [0, 0, 1]])[color=green][color=darkred]
      >>>> for i in r:[/color][/color]
      > ... for k in Numeric.nonzero (i)[1:]:
      > ... i[k] = 0
      > ...[color=green][color=darkred]
      >>>> r[/color][/color]
      > array([[1, 0, 0],
      > [0, 1, 0],
      > [0, 0, 1]])
      >
      > Peter[/color]


      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

      Comment

      • Jeff Epler

        #4
        Re: A matrix problem. Please help!

        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:[color=blue][color=green][color=darkred]
        >>> ru[/color][/color][/color]
        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]])[color=blue][color=green][color=darkred]
        >>> N.add.accumulat e(N.add.accumul ate(ru, 1), 1)[/color][/color][/color]
        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]])[color=blue][color=green][color=darkred]
        >>> _ == 1[/color][/color][/color]
        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

        Comment

        • Carl

          #5
          Re: A matrix problem. Please help!

          Jeff Epler wrote:
          [color=blue]
          > 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:[color=green][color=darkred]
          >>>> ru[/color][/color]
          > 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]])[color=green][color=darkred]
          >>>> N.add.accumulat e(N.add.accumul ate(ru, 1), 1)[/color][/color]
          > 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]])[color=green][color=darkred]
          >>>> _ == 1[/color][/color]
          > 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[/color]

          Jeff,

          Your solution works very well. I tried to do something similar, but with
          N.cumsum instead of N.add.accumulua te. 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

          Comment

          Working...