3

Suppose I have the following array:

a = [[1, 4, 2, 3]
     [3, 1, 5, 4]
     [4, 3, 1, 2]]

What I'd like to do is impose a maximum value on the array, but have that maximum vary by row. For instance if I wanted to limit the 1st and 3rd row to a maximum value of 3, and the 2nd row to a value of 4, I could create something like:

[[1, 3, 2, 3]
 [3, 1, 4, 4]
 [3, 3, 1, 2]

Is there any better way than just looping over each row individually and setting it with 'nonzero'?

3 Answers 3

3

With numpy.clip (using the method version here):

a.clip(max=np.array([3, 4, 3])[:, None]) # np.clip(a, ...)
# array([[1, 3, 2, 3],
#        [3, 1, 4, 4],
#        [3, 3, 1, 2]])

Generalized:

def clip_2d_rows(a, maxs):
    maxs = np.asanyarray(maxs)
    if maxs.ndim == 1:
        maxs = maxs[:, np.newaxis]
    return np.clip(a, a_min=None, a_max=maxs)

You might be safer using the module-level function (np.clip) rather than the class method (np.ndarray.clip). The former uses a_max as a parameter, while the latter uses the builtin max as a parameter which is never a great idea.

Sign up to request clarification or add additional context in comments.

5 Comments

Well, don't I feel stupid now, thanks for such a quick reply!
Also, this seems faster!
"while the latter uses the builtin max as a parameter which is never a great idea." What do you mean uses the builtin max as a parameter?
strange that they use it then... Either way, I'll keep it in mind!
@juanpa.arrivillaga check the syntax. I guess it might be harmless, but usually see attempt to avoid using builtin names like that. i.e. def func(klass=None)..
3

With masking -

In [50]: row_lims = np.array([3,4,3])

In [51]: np.where(a > row_lims[:,None], row_lims[:,None], a)
Out[51]: 
array([[1, 3, 2, 3],
       [3, 1, 4, 4],
       [3, 3, 1, 2]])

1 Comment

This seems like a more flexible solution, but for the problem in specific Brad's answer seems more succinct and runs faster. Still, thanks! I'll have to look into masking more.
1

With

>>> a
array([[1, 4, 2, 3],
       [3, 1, 5, 4],
       [4, 3, 1, 2]])

Say you have

>>> maxs = np.array([[3],[4],[3]])
>>> maxs
array([[3],
       [4],
       [3]])

What about doing

>>> a.clip(max=maxs)
array([[1, 3, 2, 3],
       [3, 1, 4, 4],
       [3, 3, 1, 2]])

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.