Schilcote
Schilcote

Reputation: 2394

Alter a 3D ndarray at the positions represented by a 2d ndarray

This is my first nontrivial use of numpy, and I'm having some trouble in one spot.

So, I have colors, a (xsize + 2, ysize + 2, 3) ndarray, and newlife, a (xsize + 2, ysize + 2) ndarray of booleans. I want to add a random value between -5 and 5 to all three values in colors at all positions where newlife is true. In other words newlife maps 2D vectors to whether or not I want to add a random value to the color in colors at that position.

I've tried a million variations on this:

colors[np.nonzero(newlife)] += (np.random.random_sample((xsize + 2,ysize + 2, 3)) * 10 - 5)

but I keep getting stuff like

ValueError: operands could not be broadcast together with shapes (589,3) (130,42,3) (589,3)

How do I do this?

Upvotes: 1

Views: 49

Answers (2)

Paul Panzer
Paul Panzer

Reputation: 53029

This changes the colors in-place assuming uint8 dtype. Both assumptions are not essential:

import numpy as np

n_x, n_y = 2, 2
colors = np.random.randint(5, 251, (n_x+2, n_y+2, 3), dtype=np.uint8)
mask = np.random.randint(0, 2, (n_x+2, n_y+2), dtype=bool)

n_change = np.count_nonzero(mask)
print(colors)
print(mask)
colors[mask] += np.random.randint(-5, 6, (n_change, 3), dtype=np.int8).view(np.uint8)
print(colors)

The easiest way of understanding this is to look at the shape of colors[mask].

Upvotes: 0

John Zwinck
John Zwinck

Reputation: 249293

I think this does what you want:

# example data
colors = np.random.randint(0, 100, (5,4,3))
newlife = np.random.randint(0, 2, (5,4), bool)

# create values to add, then mask with newlife
to_add = np.random.randint(-5,6, (5,4,3))
to_add[~newlife] = 0

# modify in place
colors += to_add

Upvotes: 1

Related Questions