Get second minimum values per column in 2D array
Try this, in just one line:
[sorted(i)[1] for i in zip(*A)]
in action:
In [12]: A = [[72, 76, 44, 62, 81, 31], ...: [54 ,36 ,82 ,71 ,40, 45], ...: [63 ,59, 84, 36, 34 ,51], ...: [58, 53, 59, 22, 77 ,64], ...: [35 ,77, 60, 76, 57, 44]] In [18]: [sorted(i)[1] for i in zip(*A)] Out[18]: [54, 53, 59, 36, 40, 44]
zip(*A)
will transpose your list of list so the columns become rows.
and if you have duplicate value, for example:
In [19]: A = [[72, 76, 44, 62, 81, 31], ...: [54 ,36 ,82 ,71 ,40, 45], ...: [63 ,59, 84, 36, 34 ,51], ...: [35, 53, 59, 22, 77 ,64], # 35 ...: [35 ,77, 50, 76, 57, 44],] # 35
If you need to skip both 35
s, you can use set()
:
In [29]: [sorted(list(set(i)))[1] for i in zip(*A)] Out[29]: [54, 53, 50, 36, 40, 44]
Operations on numpy
arrays should be done with numpy
functions, so look at this one:
np.sort(A, axis=0)[1, :]
Out[61]: array([54, 53, 59, 36, 40, 44])
you can use heapq.nsmallest
from heapq import nsmallest[nsmallest(2, e)[-1] for e in zip(*A)]
output:
[54, 53, 50, 36, 40, 44]
I added a simple benchmark to compare the performance of the different solutions already posted:
from simple_benchmark import BenchmarkBuilderfrom heapq import nsmallestb = BenchmarkBuilder()@b.add_function()def MehrdadPedramfar(A): return [sorted(i)[1] for i in zip(*A)]@b.add_function()def NicolasGervais(A): return np.sort(A, axis=0)[1, :]@b.add_function()def imcrazeegamerr(A): rotated = zip(*A[::-1]) result = [] for arr in rotated: # sort each 1d array from min to max arr = sorted(list(arr)) # add the second minimum value to result array result.append(arr[1]) return result@b.add_function()def Daweo(A): return np.apply_along_axis(lambda x:heapq.nsmallest(2,x)[-1], 0, A)@b.add_function() def kederrac(A): return [nsmallest(2, e)[-1] for e in zip(*A)]@b.add_arguments('Number of row/cols (A is square matrix)')def argument_provider(): for exp in range(2, 18): size = 2**exp yield size, [[randint(0, 1000) for _ in range(size)] for _ in range(size)]r = b.run()r.plot()
Using zip
with sorted
function is the fastest solution for small 2d lists while using zip
with heapq.nsmallest
shows to be the best on big 2d lists