Reputation: 413
I have a list of lists as follows:
original_list = [['B_S', 'O', 'O', 'O'],
['B_S', 'O', 'O', 'O'],
['O', 'O', 'B_S', 'O'],
['O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'B_S', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O']]
I want to aggregate each three list to be one list based on the majority of elements. That is, if two positions have the same element, the new list will take the same element in the same position. The desired output should be like:
desired_output = [['B_S', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O']]
I have tried with this complex function:
def collect_labels(lab_user):
def aggregate_labels(a,b,c):
aggregated_list = []
# iterate over 3 lists
for x,y,z in zip(a, b, c):
if x != 'O':
aggregated_list.append(x)
elif y != 'O':
aggregated_list.append(y)
#elif z != 'O':
#aggregated_list.append(z) # you can improve the code
else:
aggregated_list.append(z)
return aggregated_list
result = [aggregate_labels(lab_user[i], lab_user[i+1], lab_user[i+2]) for i in range(0,len(lab_user)-2, 3)]
return result
But it return the wrong result:
wrong_result= [['B_S', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'B_S', 'O', 'O']]
I will be very grateful if you could help me to correct my code!
Upvotes: 1
Views: 209
Reputation: 71464
The hardest part of the problem is just grouping your lists into the three chunks:
>>> [original_list[i*3:i*3+3] for i in range(len(original_list)//3)]
[[['B_S', 'O', 'O', 'O'], ['B_S', 'O', 'O', 'O'], ['O', 'O', 'B_S', 'O']],
[['O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O']],
[['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'B_S', 'O', 'O'], ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O']]]
Once you have that, though, you can use zip
to group the items you want to compare:
>>> chunks = [original_list[i*3:i*3+3] for i in range(len(original_list)//3)]
>>> [list(zip(*j)) for j in chunks]
[[('B_S', 'B_S', 'O'), ('O', 'O', 'O'), ('O', 'O', 'B_S'), ('O', 'O', 'O')],
[('O', 'O', 'O'), ('O', 'O', 'O'), ('O', 'O', 'O'), ('O', 'O', 'O'), ('B_S', 'O', 'O'), ('O', 'B_S', 'O'), ('O', 'O', 'B_S'), ('O', 'O', 'O'), ('O', 'O', 'O'), ('O', 'O', 'O')],
[('O', 'O', 'O'), ('O', 'O', 'O'), ('O', 'O', 'O'), ('O', 'O', 'O'), ('O', 'O', 'O'), ('B_S', 'B_S', 'B_S'), ('O', 'O', 'O'), ('O', 'O', 'O'), ('B_S', 'B_S', 'B_S'), ('B_S', 'O', 'O'), ('O', 'O', 'O'), ('O', 'O', 'O')]]
And then you just want to pick the item in each of those zipped tuples that appears the most frequently -- aka statistics.mode
:
>>> import statistics
>>> [[statistics.mode(i) for i in zip(*j)] for j in chunks]
[['B_S', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O']]
or all together:
from statistics import mode
original_list = [['B_S', 'O', 'O', 'O'],
['B_S', 'O', 'O', 'O'],
['O', 'O', 'B_S', 'O'],
['O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'B_S', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O']]
CHUNK_LEN = 3
desired_output = [
[mode(i) for i in zip(*j)]
for j in (
original_list[i*CHUNK_LEN:(i+1)*CHUNK_LEN]
for i in range(len(original_list)//CHUNK_LEN)
)
]
Obviously if you can make original_list
just be correctly grouped up front it's a lot easier:
from statistics import mode
original_list = [[['B_S', 'O', 'O', 'O'],
['B_S', 'O', 'O', 'O'],
['O', 'O', 'B_S', 'O']],
[['O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O']],
[['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'B_S', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O']]]
desired_output = [
[mode(i) for i in zip(*j)]
for j in original_list
]
Upvotes: 3
Reputation: 13651
A broader solution using loop:
def merge_result(data):
ar = []
for i in range(0, len(data)-2, 3):
temp = []
for j in range(len(data[i])):
if data[i][j] == data[i+1][j]:
temp.append(data[i][j])
elif data[i+2][j] == data[i+1][j]:
temp.append(data[i+1][j])
elif data[i][j] == data[i+2][j]:
temp.append(data[i][j])
else:
temp.append('O')
ar.append(temp)
return ar
if __name__ == "__main__":
original_list = [['B_S', 'O', 'O', 'O'],
['B_S', 'O', 'O', 'O'],
['O', 'O', 'B_S', 'O'],
['O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'B_S', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O']]
print(merge_result(original_list))
Output:
[['B_S', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O', 'B_S', 'O', 'O', 'B_S', 'O', 'O', 'O']]
Upvotes: 2