0

Given:

  • list of strings:
colors = ['red', 'blue', 'green', 'grey', 'black', 'yellow', 'brown', 'orange', 'magenta', 'cyan', 'teal', 'turquise']
  • a, a numpy.array with a.shape[0] <= len(colors) that contains some numeric (repeating) values.

Requirement:

Producing a list l, of str objects that will match the elements in a. I.e. for each element in a, there will be the same str object in l, as in shown in Example 1.

Example 1:

Given:

import numpy as np


colors = ['red', 'blue', 'green', 'grey', 'black', 'yellow', 'brown', 'orange', 'magenta', 'cyan', 'teal', 'turquise']

a = np.array([0, 1, 5, 7, 1, 5, 7, 7, 0, 0])

the desired output should be:

Out: ['red', 'blue', 'green', 'grey', 'blue', 'green', 'grey', 'grey', 'red', 'red']

My solution:

I can think of two ways to do it as shown in Code 1 and Code 2.

Code 1:

import numpy as np

colors = ['red', 'blue', 'green', 'grey', 'black', 'yellow', 'brown', 'orange', 'magenta', 'cyan', 'teal', 'turquise']
a = np.array([0, 1, 5, 7, 1, 5, 7, 7, 0, 0])

num_2_color_dict = {}
for num in np.unique(a):
    num_2_color_dict[num] = colors[np.min(np.where(a==num))]
    
color_by_num = []
for num in a:
    color_by_num.append(num_2_color_dict[num])
color_by_num
Out: ['red', 'blue', 'green', 'grey', 'blue', 'green', 'grey', 'grey', 'red', 'red']

Code 2:

import numpy as np

colors = ['red', 'blue', 'green', 'grey', 'black', 'yellow', 'brown', 'orange', 'magenta', 'cyan', 'teal', 'turquise']
a = np.array([0, 1, 5, 7, 1, 5, 7, 7, 0, 0])

colors_by_num = [colors[np.min(np.where(np.unique(a)==num))] for num in a]
colors_by_num

Question:

I'd like to be able to achieve the same result without using loops, and preferably with some numpy array manipulation technique, that will shorten the code.

Thanks in advance.

2 Answers 2

4

As Josef states in his answer, numpy.unique has the option to return integer encodings, which is what you want. So the following piece of code should help you out:

np.take(colors, np.unique(a,return_inverse=True)[1])

With setting return_inverse=True, you get the integer encodings, as second return parameter. Numpy.take() gives you the items for the indices.

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

Comments

1
colors = np.array(['red', 'blue', 'green', 'grey', 'black', 'yellow', 'brown', 'orange', 'magenta', 'cyan', 'teal', 'turquise'])
a      = np.array([0, 1, 5, 7, 1, 5, 7, 7, 0, 0])

_, i = np.where(a[:, None] == np.unique(a))

colors[i]


>>> array(['red', 'blue', 'green', 'grey', 'blue', 'green', 'grey', 'grey', 'red', 'red'])

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.