2

I have a two-dimensional numpy array of data, holding symmetric information about pairs of elements I'm tracking, very much like a round-robin bracket in a tournament. Keeping with that analogy, each player occupies one row with the column data being their score against a given opponent. For "legacy" reasons, all scores will be positive numbers except for the score against oneself, which will be 0.

Let's say I want to find the worst score of a given player, returning both the score and the opponent they played for that score. How might I do this?

The mediocre version might look like:

minimum = float('inf')
min_opp = None
for opponent_id in player_ids:
    if opponent_id != player_id:
        score = match_matrix[player_id, opponent_id]
        if score < minimum:
            minimum = score
            min_opp = opponent_id
return minimum, min_opp

But that's not using the power of numpy at all. I feel like there should be an easy solution, but I cannot seem to find it.

score = np.min(match_matrix[player, :])

gives the self-score, and I can't quite make the code from this answer work correctly.

Thanks!

EDIT: This answer provides good ideas, but only gets the minimum of the entire array, not a single row.

3
  • Does this answer your question? Commented Feb 1, 2017 at 17:05
  • Possible duplicate of Minimum of Numpy Array Ignoring Diagonal Commented Feb 1, 2017 at 17:09
  • 1
    @jotasi. That answers the question for an entire matrix, not for a row-by-row case. I wouldn't consider it a dupe. Commented Feb 1, 2017 at 17:13

2 Answers 2

2

You can select the given row, mask out the self-score and return the minimum of the remainder. Basically what you did but with an extra masking step. I would also recommend using np.argmin instead of np.min because it returns the index of the minimum, which is much more informative in this case:

mask = np.ones(match_matrix.shape(1), dtype=np.bool)
mask[player] = False
opponent = np.argmin(match_matrix[player, mask])
if opponent >= player:
    opponent += 1
score = match_matrix[player, opponent]
Sign up to request clarification or add additional context in comments.

1 Comment

Okay! That's readable and does what I need it to. Thanks so much.
0

Here's one way to do it. np.min() will give you the minimum value in a row, and np.where can tell you where that value is.

grid = np.random.randint(0,10,[5,5]) #Random matchups of 5x5 players
player = 1
low_score = np.min(grid[player][grid[player]>0])    #Only look at positive scores
opponent = np.where(grid[player]==low_score)[0]

Here, opponents will be an array of opponents, in case player got the same low score against multiple opponents.

1 Comment

argmin + indexing is probably more efficient than min + where.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.