Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

More Elegant way to number a list according to values

I would like to map a list into numbers according to the values.

For example:

['aa', 'b', 'b', 'c', 'aa', 'b', 'a'] -> [0, 1, 1, 2, 0, 1, 3]

I'm trying to achieve this by using numpy and a mapping dict.

def number(lst):
    x = np.array(lst)
    unique_names = list(np.unique(x))
    mapping = dict(zip(unique_names, range(len(unique_names)))) # Translating dict
    map_func = np.vectorize(lambda name: d[name])
    return map_func(x)

Is there a more elegant / faster way to do this?

Update: Bonus question -- do it with the order maintained.

like image 886
blancmange Avatar asked Apr 14 '17 09:04

blancmange


People also ask

How do you represent a list?

A list can often be constructed by writing the items in sequence, separated by commas, semicolons, and/or spaces, within a pair of delimiters such as parentheses '()', brackets '[]', braces '{}', or angle brackets '<>'.

How do you count a value in a list?

1) Using count() method count() is the in-built function by which python count occurrences in list. It is the easiest among all other methods used to count the occurrence. Count() methods take one argument, i.e., the element for which the number of occurrences is to be counted.

Which is more efficient list or set?

Sets use hashing to perform look ups which makes them way faster than lists in this regard. (In the practical example the code using lists took about 45 seconds to run, whereas the code with sets took less than a tenth of a second!)

How do I make a list of sequential numbers in Python?

How do you create a sequence of numbers in Python? Use range() to generate a sequence of numbers Call range(start, stop) to generate a sequence of numbers from start up to stop . Use a for-loop to iterate over each number in this sequence and use list.


1 Answers

You can use the return_inverse keyword:

x = np.array(['aa', 'b', 'b', 'c', 'aa', 'b', 'a'])
uniq, map_ = np.unique(x, return_inverse=True)
map_
# array([1, 2, 2, 3, 1, 2, 0])

Edit: Order preserving version:

x = np.array(['aa', 'b', 'b', 'c', 'aa', 'b', 'a'])
uniq, idx, map_ = np.unique(x, return_index=True, return_inverse=True)
mxi = idx.max()+1
mask = np.zeros((mxi,), bool)
mask[idx] = True
oidx = np.where(mask)[0]
iidx = np.empty_like(oidx)
iidx[map_[oidx]] = np.arange(oidx.size)
iidx[map_]
# array([0, 1, 1, 2, 0, 1, 3])
like image 174
Paul Panzer Avatar answered Nov 05 '22 18:11

Paul Panzer