1

I have a 2D array (image) in which I want to replace array values greater than some threshold with a random number in some range. My attempt was to use numpy.random.uniform, as so

Z[Z > some_value] = uniform(lower_limit,upper_limit)

However I've found that this replaces all values above the threshold with the same random value. I would like to replace all array values above the threshold with a different random value each.

I think this would require some interation over the entire array for which I would need to generate a random value if the condition is met. How would I do this?

2 Answers 2

1

You are correct that iteration would be the correct way to go. Let's do a list comprehension.

[uniform(lower_limit, upper_limit) if i > some_value else i
 for i in Z]

Let's step through it. Take an individual value. If it is greater than the threshold, use a randomly generated one, otherwise the original value.

uniform(lower_limit, upper_limit) if i > some_value else i

Repeat this for every element in Z

for i in Z

For a 2D array, nest multiple comprehensions. Imagine that the above solution was to hit everything in one row and then repeat it for every row.

[[uniform(lower_limit, upper_limit) if i > some_value else i
  for i in row]
  for row in Z]
Sign up to request clarification or add additional context in comments.

5 Comments

After implementing this I am getting the error ValueError: The truth value of an array with more than one element is ambiguous. I'm guessing this is because it is a 2d array? Is there a way to iterate using the above list comprehension and preserve the shape of the array (2d) without having to convert it to a 1d array?
@maelstromscientist My apologies, updated with new example. Iterating (using a list comprehension of course) over each 1D array in your 2D array should work for you.
Nevermind, I had a silly mistake with variable names and once that was fixed it worked great. Thanks!
Huh. No idea. It may be time to split the offending piece of code out. def small_or_random(num): ... then simplify the comprehension to [[small_or_random(i) for i in row] for row in Z]. That should be much easier to debug / reason about.
@maelstromscientist You should start to get used to the mechanisms provided by numpy to work with whole arrays at once instead of doing operations element-wise by looping or using list-comprehensions. It is advantageous both in terms of speed and readability. See my answer.
0

Check the third argument to uniform. Using size=N will yield an array of random values with length N. Thus

z[z>some_value] = np.random.uniform(lower, upper, len(z>some_value))

will do what you want.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.