-1

I have a list of lists that I want to re-order:

qvalues = [[0.1, 0.3, 0.6],[0.7, 0.1, 0.2],[0.3, 0.4, 0.3],[0.1, 0.3, 0.6],[0.1, 0.3, 0.6],[0.1, 0.3, 0.6]]

I know how to reorder this list if I have a list with the order I want (example here). The tricky part is getting this order.

What I have is this:

locations = [(['Loc1','Loc1'], 3), (['Loc2'], 1), (['Loc3', 'Loc3', 'Loc3'], 2)]

This is a list of tuples, where the first element of each tuple is a list with the location name, repeated for each individual in that location, and the second element is the order these individuals are in on the qvalues list (qvalues[0] is 'Loc2', qvalues[1:4] are 'Loc3' and qvalues[4:6] are 'Loc1'.

What I want is to change the order of the lists in qvalues to the order they show up in locations: First 'Loc1', then 'Loc2' and finally 'Loc3'.

This is just a small example, my real dataset has hundreds of individuals and 17 locations.

Thanks in advance for any help you may provide.

Community
  • 1
  • 1
Stunts
  • 430
  • 6
  • 11

1 Answers1

1

You will need to build a list of offsets and length instead of length and positions as provided in your locations list. Then, you’ll be able to reorder based on the answer you linked to:

qvalues = [[0.1, 0.3, 0.6],[0.7, 0.1, 0.2],[0.3, 0.4, 0.3],[0.1, 0.3, 0.6],[0.1, 0.3, 0.6],[0.1, 0.3, 0.6]]
locations = [(['Loc1','Loc1'], 3), (['Loc2'], 1), (['Loc3', 'Loc3', 'Loc3'], 2)]

locations_dict = {pos:(index,len(loc)) for index,(loc,pos) in enumerate(locations)}
# if python2: locations_dict = dict([(pos,(index,len(loc))) for index,(loc,pos) in enumerate(locations)])

offsets = [None]*len(locations)

def compute_offset(pos):
    # compute new offset from offset and length of previous position. End of recursion at position 1: we’re at the beginning of the list
    offset = sum(compute_offset(pos-1)) if pos > 1 else 0
    # get index at where to store current offset + length of current location
    index, length = locations_dict[pos]
    offsets[index] = (offset, length)

    return offsets[index]

compute_offset(len(locations))

qvalues = [qvalues[offset:offset+length] for offset,length in offsets]

You’ll end up with qvalues being a list of lists of lists instead of a "simple" list of lists. If you want to flatten it to keep your initial layout use this list comprehension instead:

qvalues = [value for offset,length in offsets for value in qvalues[offset:offset+length]]

Output with first version

[[[0.1, 0.3, 0.6], [0.1, 0.3, 0.6]], [[0.1, 0.3, 0.6]], [[0.7, 0.1, 0.2], [0.3, 0.4, 0.3], [0.1, 0.3, 0.6]]]

Output with second version

[[0.1, 0.3, 0.6], [0.1, 0.3, 0.6], [0.1, 0.3, 0.6], [0.7, 0.1, 0.2], [0.3, 0.4, 0.3], [0.1, 0.3, 0.6]]
Stunts
  • 430
  • 6
  • 11
301_Moved_Permanently
  • 4,007
  • 14
  • 28