Nickpick
Nickpick

Reputation: 6597

NumPy: sorting 3D array but keeping 2nd dimension assigned to first

I have an array that represents poker cards held by players. Each player holds 6 cards and the cards have a value of 1-12 and have a corresponding suit of 1-4.

The first player for example would hold the following 7 cards:

deck=np.array([[[  6.,   2.],
                [ 10.,   1.],
                [  5.,   1.],
                [  9.,   2.],
                [  4.,   1.],
                [  3.,   2.],
                [ 11.,   2.]]])

My problem now is that when I sort the cards to see which one has the highest value (in this case 11 with the corresponding suit 2)

sortedcards=-np.sort(-unsortedCards,axis=1)

It does not only sort the values in the first column, but also the ones in the second (which is the suit).

How can I sort only the first column and keep the second column assigned to the first one so that I don't lose the information which values has which suit?

Please bear in mind that the above example is only with one player but there will be several players. So the array has an additional dimension.

Important: The solution has to by pure NumPy matrix operation only.

Upvotes: 2

Views: 1977

Answers (2)

swenzel
swenzel

Reputation: 7173

First you need a single value which you can use to sort your cards. An easy one would be value*4 + suit:

sortval = deck[:,:,0]*4+deck[:,:,1]
sortval *= -1 # if you want largest first

Then you use np.argsort to find out which index belongs where and use it to sort your decks. It sorts along the last axis on default, which is what we want.

sortedIdx = np.argsort(sortval)

Now you can use it to sort your deck like this:

deck = deck[np.arange(len(deck))[:,np.newaxis],sortedIdx]

The np.arange... part makes sure that every second dimension index array from sortedIdx is paired with the right first dimension index.

The whole thing:

import numpy as np

deck = np.array([[[  6.,   2.],
                  [ 10.,   1.],
                  [  5.,   1.],
                  [  9.,   2.],
                  [  4.,   1.],
                  [  3.,   2.],
                  [ 11.,   2.]],

                 [[  6.,   2.],
                  [  2.,   2.],
                  [  2.,   3.],
                  [ 11.,   1.],
                  [ 11.,   3.],
                  [  5.,   3.],
                  [  4.,   4.]]])

sortval = deck[:,:,0]*4+deck[:,:,1]
sortval *= -1 # if you want largest first
sortedIdx = np.argsort(sortval)
deck = deck[np.arange(len(deck))[:,np.newaxis],sortedIdx]
print(deck)

Will print:

[[[ 11.   2.]
  [ 10.   1.]
  [  9.   2.]
  [  6.   2.]
  [  5.   1.]
  [  4.   1.]
  [  3.   2.]]

 [[ 11.   3.]
  [ 11.   1.]
  [  6.   2.]
  [  5.   3.]
  [  4.   4.]
  [  2.   3.]
  [  2.   2.]]]

Upvotes: 2

David de la Iglesia
David de la Iglesia

Reputation: 2534

Are you sorting the values only to see wich one has the highest value?? Because in this case why not use np.max()?:

deck=np.array([[[  6.,   2.],
                [ 10.,   1.],
                [  5.,   1.],
                [  9.,   2.],
                [  4.,   1.],
                [  3.,   2.],
                [ 11.,   2.]],
            [[  7.,   2.],
                [ 8.,   1.],
                [  1.,   1.],
                [  9.,   2.],
                [  4.,   1.],
                [  3.,   2.],
                [ 12.,   2.]]])

np.max(deck)
Out[4]: 12.0

np.max(deck[0])
Out[5]: 11.0

Upvotes: 0

Related Questions