Comment puis-je obtenir la deuxième valeur minimale de chaque colonne? J'ai ce tableau:
A = [54 53 59 36 40 44]
Je souhaite avoir une sortie comme:
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]]
6 Réponses :
Essayez ceci, en une seule ligne:
In [29]: [sorted(list(set(i)))[1] for i in zip(*A)] Out[29]: [54, 53, 50, 36, 40, 44]
en action:
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
zip(*A)transposera votre liste de liste afin que les colonnes deviennent des lignes.
et si vous avez une valeur en double, par exemple:
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]
Si vous devez sauter les deux 35 s, vous pouvez utiliser set() :
[sorted(i)[1] for i in zip(*A)]
>>> [sorted(set(items))[1] for items in A] [1, 7, 13, 19, 25]
N'est-ce pas obtenir le deuxième élément de chaque ligne plutôt que la colonne?
Les opérations sur les tableaux numpy doivent être effectuées avec des fonctions numpy , alors regardez celle-ci:
Out[61]: array([54, 53, 59, 36, 40, 44])
np.sort(A, axis=0)[1, :]
Cela doit être la meilleure solution pour autant que je sache, cela garde tout dans numpy , je pense que le lambda doit ralentir la solution heapq.nsmallest . Il semble préférable de tout garder rapide et numpy
J'espère avoir bien compris votre question, mais dans tous les cas, voici ma solution, je suis sûr qu'il existe une manière plus élégante de le faire, mais cela fonctionne
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)
En supposant que A est numpy.array (si cela est vrai, pensez à ajouter numpy balise numpy à votre question), vous pouvez utiliser apply_along_axis de la manière suivante:
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]
Notez que j'ai utilisé heapq.nsmallest car il effectue autant de tri que nécessaire pour obtenir les 2 plus petits éléments, contrairement à sorted qui effectue un tri complet.
vous pouvez utiliser heapq.nsmallest
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()
production:
[54, 53, 50, 36, 40, 44]
J'ai ajouté un simple benchmark pour comparer les performances des différentes solutions déjà postées:
from heapq import nsmallest [nsmallest(2, e)[-1] for e in zip(*A)]
L'utilisation de zip avec une fonction sorted est la solution la plus rapide pour les petites listes heapq.nsmallest tout en utilisant zip avec heapq.nsmallest montre qu'elle est la meilleure sur les grandes listes heapq.nsmallest
Juste une idée folle: ces résultats peuvent-ils être affectés par le fait que vous avez généré des nombres qui ne sont pas des dtypes numpy? De plus, le randint intégré ne retournera-t-il pas une liste au lieu d'un tableau?
est-ce la seule façon d'itérer sur les lignes de np.matrix? existe-t-il une alternative plus rapide?
deuxième minimum par colonne ?