The built-in max takes a key function, you can pass that as abs:
>>> max([3, 7, -10], key=abs)
-10
You can call abs again on the result to normalise the result:
>>> abs(max([3, 7, -10], key=abs))
10
Answer from Moses Koledoye on Stack OverflowThe built-in max takes a key function, you can pass that as abs:
>>> max([3, 7, -10], key=abs)
-10
You can call abs again on the result to normalise the result:
>>> abs(max([3, 7, -10], key=abs))
10
max(max(a),-min(a))
It's the fastest for now, since no intermediate list is created (for 100 000 values):
In [200]: %timeit max(max(a),-min(a))
100 loops, best of 3: 8.82 ms per loop
In [201]: %timeit abs(max(a,key=abs))
100 loops, best of 3: 13.8 ms per loop
In [202]: %timeit max(map(abs,a))
100 loops, best of 3: 13.2 ms per loop
In [203]: %timeit max(abs(n) for n in a)
10 loops, best of 3: 19.9 ms per loop
In [204]: %timeit np.abs(a).max()
100 loops, best of 3: 11.4 ms per loop
Let, df the dataframe with two columns, apply conditional absolute minimum over rows using axis=1
Here, x[np.argmin(x.abs())] checks the row index with absolute minimum and return the the original value with sign.
Also, we would need pd.isnull(x.min()) check for 'All-NaN slice encountered i.e when both the columns have NaN values.
In [3]: df.apply(lambda x: x.min() if pd.isnull(x.min()) else
x[np.argmin(x.abs())], axis=1)
Out[3]:
0 NaN
1 2
2 1
3 0
4 -1
5 -2
6 -3
7 -4
8 4
9 3
10 2
dtype: float64
OK, after reading and understanding your question and not being able to find a vectorised approach, we can define a custom function and call apply and pass each row.
So this will check if either column is null if so return the min value, it then compares the abs value of either column and then returns the column that has smallest abs value but the original value including sign:
In [269]:
def func(x):
if pd.isnull(x.a) or pd.isnull(x.b):
return x.min()
elif np.abs(x.a) < np.abs(x.b):
return x.a
else:
return x.b
df.apply(lambda row: func(row), axis = 1)
Out[269]:
0 NaN
1 2
2 1
3 0
4 -1
5 -2
6 -3
7 -4
8 4
9 3
10 2
dtype: float64
A more idiomatic and readable solution would be to use itertools.combinations(list, 2) to take all pairs.
max(abs(a) - abs(b) for a, b in itertools.combinations(int_list, 2))
However, that is O(n2). A smarter O(n) solution would be to subtract the minimum absolute value from the maximum absolute value.
absolutes = [abs(elem) for elem in int_list]
print max(absolutes) - min(absolutes)
An alternative, purely functional style approach that builds on itertools.combinations too is this:
max(itertools.starmap(operator.sub, itertools.combinations(map(abs, int_list), 2)))
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
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)