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 ?