Python >> Tutoriel Python >  >> Python Tag >> Array

Obtenir les deuxièmes valeurs minimales par colonne dans un tableau 2D

Essayez ceci, en une seule ligne :

[sorted(i)[1] for i in zip(*A)]

en 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) va transposer votre liste de liste pour que les colonnes deviennent des lignes.

et si vous avez une valeur en double, par exemple :

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

Si vous devez ignorer les deux numpy s, vous pouvez utiliser set() :

In [29]: [sorted(list(set(i)))[1] for i in zip(*A)]                                                                                                                                                                
Out[29]: [54, 53, 50, 36, 40, 44]

Opérations sur numpy les tableaux doivent être faits avec numpy fonctions, alors regardez celle-ci :

np.sort(A, axis=0)[1, :]
Out[61]: array([54, 53, 59, 36, 40, 44])

vous pouvez utiliser heapq.nsmallest

from heapq import nsmallest

[nsmallest(2, e)[-1] for e in zip(*A)]

sortie :

[54, 53, 50, 36, 40, 44]

J'ai ajouté un benchmark simple pour comparer les performances des différentes solutions déjà postées :

from simple_benchmark import BenchmarkBuilder
from heapq import nsmallest


b = 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()

Utilisation de zip avec sorted la fonction est la solution la plus rapide pour les petites listes 2d tout en utilisant zip avec heapq.nsmallest montre qu'il est le meilleur sur les grandes listes 2d