1
votes

Trouvez «x» les plus grandes différences dans la liste Python

Disons que j'ai une liste de données ... disons le cours des actions par exemple, et je veux en savoir plus sur les différences entre chaque élément de la liste - en particulier la plus grande différence. Dans ce cas, il s'agirait de trouver les 2 prix qui présentent le plus grand changement (c'est-à-dire le plus grand gain ou perte).

Maintenant, je ne veux pas simplement trouver la plus grande différence singulière . Je veux trouver peut-être les 5 plus grandes différences - où les 5 paires de nombres utilisées pour calculer la différence sont uniques et ne convergent pas vers la même solution.

Une façon de procéder consiste à imbriquer pour boucles comme ça:

from itertools import combinations
from heapq import nlargest

nums = [98,34,513,352,3523,308,13]

def findTrades(list_, amount):
    Trades_ = []

    while len(list_) >= 2:
        res = nlargest(1, combinations(list_, 2), key = lambda x: abs(x[0]-x[1]))
        Trades_.append(res)
        for i in res[0]:
            list_ = [x for x in list_ if x != i]

    return sorted(Trades_)[-amount:]

print (findTrades(nums, 3))

Mais je pense que cette méthode est vraiment maladroite et ne résout pas la question à portée de main. Y a-t-il une meilleure manière de faire cela? Merci!

Modifier:

Solution pour les personnes intéressées

J'ai utilisé une version modifiée de @ Chris_Rands répond pour résoudre le problème. Fondamentalement, cette fonction trouve simplement la plus grande différence, puis supprime chaque élément de la liste d'origine et effectue ce processus jusqu'à ce qu'il ne reste qu'un seul élément (lorsque vous ne pouvez pas trouver un autre diff). Le résultat est un tableau de tuples contenant 100% des paires uniques des plus grandes différences par rapport à l'ensemble de données:

nums = [1,2,3,4,5]

for i in nums:
    for x in nums:
        return x-i


0 commentaires

7 Réponses :


0
votes

Je voudrais parcourir la liste une fois et trouver les 3 plus grands nombres de la liste et les 3 plus petits nombres de la liste. Trouvez les différences entre tous ces nombres et prenez les 3 plus grands. Ce sera performant et garantira que vous avez trouvé les 5 plus grandes différences.


2 commentaires

Je l'ajouterai demain, je suis sur le point de jouer au basket.


je dois mettre ces cerceaux



1
votes

Voici une fonction qui prend une liste / tuple et retourne les 5 plus grandes différenciées. Notez que cela n'utilise aucune autre dépendance que les dépendances intégrées.

Utilisation:
différences (liste_, longueur)
list_ est la liste d'entrée que vous souhaitez vérifier.
length est le nombre de différences que vous souhaitez enregistrer.

def differences(list_, length):
    diffs = list(0 for _ in range(length))
    for i, j in enumerate(list_):
        for k in list_[i + 1:]:
            if max(j, k) - min(j, k) > min(diffs):
                diffs[0] = max(j, k) - min(j, k)
                diffs = sorted(diffs)
    return diffs

Les 5 plus grands seront ce qui sera renvoyé. S'il n'y a que 3 éléments dans une liste, ce qui fait 3 différences, les deux derniers seront 0 car vous ne pouvez pas obtenir de différence négative avec ce code.


0 commentaires

1
votes

Si je comprends bien:

from operator import sub
from itertools import combinations

gen = sorted(set(abs(sub(*tup)) for tup in combinations(nums, 2)), reverse=True)

gen

[4, 3, 2, 1]


1 commentaires

Oui, vous avez raison, cela produit toutes les différences possibles. Mais il ne semble pas transmettre les valeurs originales explicites qui ont été soustraites. Je n'ai pas précisé cela dans l'OP, mon erreur, mais c'est ce que je recherche.



2
votes

Prenez le produit cartisean et utilisez max :

sorted(combinations(nums,2), key=lambda t: abs(t[0]-t[1]), reverse=True)
[(1, 5), (1, 4), (2, 5), (1, 3), (2, 4), (3, 5), (1, 2), (2, 3), (3, 4), (4, 5)]

Si vous voulez qu'ils soient triés par différence:

from itertools import combinations 
nums = [1,2,3,4,5]
max(combinations(nums,2), key=lambda t: abs(t[0]-t[1]))
# (1,5)


1 commentaires

Cela fonctionne parfaitement! Mais comment pourrais-je aussi faire en sorte qu'il n'utilise qu'une seule fois le max et le min? Dans votre deuxième exemple, 5 et 1 sont utilisés à plusieurs reprises, est-il possible de n'utiliser ces valeurs qu'une seule fois pour que chaque paire soit composée de valeurs complètement uniques de nums? Le tableau de résultats serait nettement plus court.



3
votes

Ici x = 3 . Utiliser heapq.nlargest est préférable au tri des petites valeurs de x.

>>> from itertools import combinations
>>> from heapq import nlargest
>>> nlargest(3, combinations(nums, 2), key = lambda x: abs(x[0]-x[1]))
[(1, 5), (1, 4), (2, 5)]


2 commentaires

J'ai utilisé ceci et cela a très bien fonctionné! Une question cependant ... puisqu'il y a un maximum dans pratiquement tous les ensembles de données, comment pourrais-je obtenir les plus grandes différences qui n'utilisent le maximum qu'une seule fois? Chaque paire de nombres devrait être unique, le maximum ne pourrait pas être répété sur la ligne comme 5 est ici dans cet exemple.


@jblew On dirait que vous voulez simplement obtenir les 5 nombres les plus grands et les 5 plus petits, les trier, puis obtenir leurs différences de cette façon.



0
votes

Vous pouvez essayer d'utiliser les matrices:

l = np.array([1,2,3,4])
a = np.tile(l,(len(l),1))
a - a.T

entrez la description de l'image ici

Cela vous donnera la différence entre deux paires de éléments. Vous pouvez maintenant choisir les n paires les plus grandes.

b.ravel () [np.argsort (b.ravel ())] [- 4:] vous donnera la plus grande 4 valeurs

tableau ([1, 2, 2, 3])


0 commentaires

0
votes

sol contient les cinq plus grandes différences. Je remplace la différence minimale à chaque fois lors de l'itération. Devrait être simple à comprendre. (Je n'ai pas vérifié les cas extrêmes et autres problèmes)

lis=[1,2,6,3,76,44,98,23,56,87,23,65,19,73]
sol=[0,0,0,0,0]
for i in range(len(lis)):
  for j in range(len(lis)):
    if abs(lis[i]-lis[j])>min(sol):
      sol[sol.index(min(sol))]=lis[i]-lis[j]

print(sol)

#returned this [86, 97, 92, 96, 95]


0 commentaires