Erhalten Sie zweite Mindestwerte pro Spalte im 2D-Array

15

Wie kann ich den zweiten Mindestwert aus jeder Spalte erhalten? Ich habe dieses Array:

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]]

Ich möchte eine Ausgabe haben wie:

A = [54 53 59 36 40 44]
Herr Dan
quelle
Hast du etwas versucht? ?
Meha Parekh
zweites Minimum pro Spalte ?
Nicolas Gervais
@NicolasGervais ja
Herr Dan

Antworten:

12

Versuchen Sie dies in nur einer Zeile:

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

in Aktion:

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) transponiert Ihre Liste der Liste, so dass die Spalten Zeilen werden.

und wenn Sie einen doppelten Wert haben, zum Beispiel:

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

Wenn Sie beide 35s überspringen müssen , können Sie Folgendes verwenden set():

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

Operationen an numpyArrays sollten mit numpyFunktionen ausgeführt werden. Sehen Sie sich also Folgendes an:

np.sort(A, axis=0)[1, :]
Out[61]: array([54, 53, 59, 36, 40, 44])
Nicolas Gervais
quelle
Dies muss die beste Lösung sein, soweit ich weiß, es hält alles in numpy, ich denke, die Lösung lambdamuss verlangsamt werden heapq.nsmallest. Scheint am besten, alles schnell zu haltennumpy
Jamylak
3

Sie können heapq.nsmallest verwenden

from heapq import nsmallest

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

Ausgabe:

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

Ich habe einen einfachen Benchmark hinzugefügt, um die Leistung der verschiedenen bereits veröffentlichten Lösungen zu vergleichen:

Geben Sie hier die Bildbeschreibung ein

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

Die Verwendung zipmit sortedFunktion ist die schnellste Lösung für kleine 2D-Listen, während die Verwendung zipmit heapq.nsmallestShows die beste Lösung für große 2D-Listen ist

Kederrac
quelle
1
Nur ein wilder Gedanke: Können diese Ergebnisse durch die Tatsache beeinflusst werden, dass Sie Zahlen generiert haben, die keine numpy dtypes sind? Gibt der eingebaute Randint nicht auch eine Liste anstelle eines Arrays zurück?
Nicolas Gervais
1

Ich hoffe, ich habe Ihre Frage richtig verstanden, aber so oder so ist hier meine Lösung. Ich bin mir sicher, dass es einen eleganteren Weg gibt, dies zu tun, aber es funktioniert

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,50,76,57,44]]

#rotate the array 90deg
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])
print(result)

Geben Sie hier die Bildbeschreibung ein

imcrazeegamer
quelle
0

Unter der Annahme , dass Aist numpy.array(falls dies zutrifft beachten Sie bitte das Hinzufügen numpyTag zu Ihrer Frage) dann könnten Sie verwenden apply_along_axisfür die folgende Art und Weise:

import heap
import numpy as np
A = np.array([[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]])
second_mins = np.apply_along_axis(lambda x:heapq.nsmallest(2,x)[-1], 0, A)
print(second_mins)  # [54 53 59 36 40 44]

Beachten Sie, dass ich heapq.nsmallest verwendet habe, da es so viel sortiert wie erforderlich, um 2 kleinste Elemente zu erhalten, im Gegensatz zu sorteddenen, die die Sortierung vollständig durchführen.

Daweo
quelle
0
>>> A = np.arange(30).reshape(5,6).tolist()
>>> A
[[0, 1, 2, 3, 4, 5], 
 [6, 7, 8, 9, 10, 11], 
 [12, 13, 14, 15, 16, 17], 
 [18, 19, 20, 21, 22, 23],
 [24, 25, 26, 27, 28, 29]]

Aktualisiert : Verwenden Sie setdiese Option , um zu verhindern, dass Listen mit dupliziert und transponiert werdenzip(*A)

>>> [sorted(set(items))[1] for items in zip(*A)]
[6, 7, 8, 9, 10, 11]

alt: zweites Mindestelement in jeder Zeile

>>> [sorted(set(items))[1] for items in A]
[1, 7, 13, 19, 25]
Dishin H Goyani
quelle
Bekommt das nicht das zweite Element in jeder Zeile und nicht in der Spalte?
paxdiablo
@paxdiablo Ja danke für inform. aktualisierte Antwort.
Dishin H Goyani