Find absolute maximum or minimum at specific position in list by Python

Viewed 1008

I have a list of arrays, like this:

data = [([-1.01201792,  2.5,  0.68665077]), ([-2.5,  0.5,  2.68189991]), ([-2.5,  3.5, 5.92202221]), ([-2.5, 5.5, 10.19026759]), ([-2.5, 6.5, 15.30091085])]

I am trying to get the absolute maximum value of each array without considering the second value in the array. For example, in the first array: ([-1.01201792, 2.5, 0.68665077]), without considering 2.5, the absolute maximum is 1.01201792.

I hope the outcome looks like this:

result = [1.01201792, 2.68189991, 5.92202221, 10.19026759, 15.30091085]

How can I achieve this?

5 Answers

You should just code as you would write the steps:

outlist = []                          # create an empty output list
for x in data:                        # for each sublist in data
    val = max(abs(x[0]), abs(x[2]))   # find max of absolute of 1st and 3rd
    outlist.append(val)               # add above value to output list

print(outlist)                        # print the output list

Output:

[1.01201792, 2.68189991, 5.92202221, 10.19026759, 15.30091085]

If there may be more than 3 elements in sublists, you can use following:

outlist = []                        # create an empty output list
for x in data:                      # for each sublist in data
    x = [x[0]]+x[2:]                # create a new list without 2nd element
    val = max(x)                    # find max of new list
    outlist.append(val)             # add above value to output list

print(outlist)                      # print the output list

You could use a list comprehension to iterate over each 'sub list', using map to get the abs. value and list slicing to drop the second value:

data = [([-1.01201792,  2.5,  0.68665077]), ([-2.5,  0.5,  2.68189991]), ([-2.5,  3.5, 5.92202221]), ([-2.5, 5.5, 10.19026759]), ([-2.5, 6.5, 15.30091085])]
x =[max(map(math.fabs, [lst[0]]+lst[2:])) for lst in data]
print(list(x))

Output:

[1.01201792, 2.68189991, 5.92202221, 10.19026759, 15.30091085]

A numpy oneliner. Probably faster than the other approaches depending on the actual size of your data. Convert data to numpy array, slice so you only have the first and last item, convert into absolute values and finally take the max over axis 1.

maxs = np.abs(np.array(data)[:, [0,2]]).max(axis=1)

Broken down:

import numpy as np

data = [([-1.01201792,  2.5,  0.68665077]), ([-2.5,  0.5,  2.68189991]), ([-2.5,  3.5, 5.92202221]), ([-2.5, 5.5, 10.19026759]), ([-2.5, 6.5, 15.30091085])]

arr = np.array(data)  # convert into array
first_last = arr[:, [0,2]]  # only keep the first and last item of each sublist
absol = np.abs(first_last)  # convert to absolute values
maxs = absol.max(axis=1)  # get the max value on the first axis

print(maxs)

You can try nested list comprehension that the inner list comprehension will change all items to absolute and will check the max value without the item in index 1.

data = [([-1.01201792,  2.5,  0.68665077]), ([-2.5,  0.5,  2.68189991]), ([-2.5,  3.5, 5.92202221]), ([-2.5, 5.5, 10.19026759]), ([-2.5, 6.5, 15.30091085])]
result = [max([abs(y) for inx, y in enumerate(i) if inx != 1]) for i in data]
print(result)

Output

[1.01201792, 2.68189991, 5.92202221, 10.19026759, 15.30091085]

Unless you are trying to golf, I'd go with something readable:

>>> [max(abs(a), abs(c)) for a, _, c in data]
[1.01201792, 2.68189991, 5.92202221, 10.19026759, 15.30091085]

If there is some more backstory to this you can do all sorts of things to make the data match your mental model and the meaning of the data, e.g.:

>>> north, _, west = zip(*data)
>>> [max(map(abs, v)) for v in zip(north, west)]
[1.01201792, 2.68189991, 5.92202221, 10.19026759, 15.30091085]
Related