How to convert elements in a list of list according to label map dictionary?

Viewed 297

I am trying to convert the elements of a list of list according to label map dictionary. This original list of lists looks like:

original= [['0','1','2'],
           ['0', '0', '0', '0', '0', '0', '0', '1', '2', '0'],
           ['0', '0', '1', '2', '0', '0', '0', '0']]

The label map dictionary that I want to convert the elements in the original according to:

twitter_label_map = {'0':'O', '1':'B_A', '2':'I_A'}

The desired output should be like:

desired = [['O','B_A','I_A'],
           ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'B_A', 'I_A', 'O'],
           ['O', 'O', 'B_A', 'I_A', 'O', 'O', 'O', 'O']]

I have tried doing this:

desired = [[twitter_label_map[old_label] for labels_list in original] for old_label in labels_list]

However this gives me the following error:

NameError: name 'labels_list' is not defined

Thanks in advance!

4 Answers

Your comprehension nesting is inverted. You have to define labels_list in the outer brackets before you can use it in the inner brackets. Think in terms of nested loops.

You are on the right track, but have mixed up the variables in your list comprehension.

You have nested lists here. Therefore, you should loop through each sublist in original, and then apply the twitter_label_map to each element e in sublist:

original = [
    ['0', '1', '2'],
    ['0', '0', '0', '0', '0', '0', '0', '1', '2', '0'],
    ['0', '0', '1', '2', '0', '0', '0', '0']
]

twitter_label_map = {'0': 'O', '1': 'B_A', '2': 'I_A'}

result = [[twitter_label_map[e] for e in sublist] for sublist in original]

print(result)

Output:

[['O', 'B_A', 'I_A'], ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'B_A', 'I_A', 'O'], ['O', 'O', 'B_A', 'I_A', 'O', 'O', 'O', 'O']]

The above is equivalent to:

result = []
for sublist in original:
    sub = []  # transformed sublist
    for e in sublist:
        sub.append(twitter_label_map[e])
    result.append(sub)

In other words, nested loops, where we append each transformed sublist to an outer result list.

desired = [[twitter_label_map[ele] for ele in lst] for lst in original]

The output is:

[['O', 'B_A', 'I_A'],
['O', 'O', 'O', 'O', 'O', 'O', 'O', 'B_A', 'I_A', 'O'], 
['O', 'O', 'B_A', 'I_A', 'O', 'O', 'O', 'O']]

The list comprehension is the same as the following with for loops:

desired = []
for lst in original:
    new_lst = []
    for ele in lst:
        new_lst.append(twitter_label_map[ele])
    desired.append(new_lst)

All the other answers explicitly use loops. If you don't feel like using loops, here is another way to achieve what you want:

def parse_symbols(symbols_list):
    return list(map(lambda e: twitter_label_map[e], symbols_list))

results = list(map(parse_symbols, original))
print(results)

Output:

[['O', 'B_A', 'I_A'], ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'B_A', 'I_A', 'O'], ['O', 'O', 'B_A', 'I_A', 'O', 'O', 'O', 'O']]

Depending on your use case, using map might yield a better performance (source):

Since map() is written in C and is highly optimized, its internal implied loop can be more efficient than a regular Python for loop. This is one advantage of using map().

This method will also make it easier for you to implement parallel processing in your code, should you need it in the future (see multiprocessing.Pool.map).

Related