1
votes

Itération plus rapide que pour la boucle

J'ai une boucle for pour un nouveau projet, mais cette forme de code est trop lente. J'essaie de trouver le moyen le plus rapide de le résoudre. Peut-être en tant que vecteur?

J'ai essayé l'approche def, mais elle ne s'est pas exécutée correctement.

%%time
for x in df2.index:   
    if x > 0: 
        if (
            (df2.loc[x,'DEF RANK'] == df2.loc[x,'OFF RANK']) 
            & (df2.loc[x,'W']=='nan')
            & (pd.isnull(df2.loc[(x-1),'Event2']) == False)
            & ((df2.loc[(x-1),'Event2'] == 'nan') == False)
        ):
            df2.loc[x,'W'] = df2.loc[(x-1),'W']
        else: # if the above isn't true - pass
            pass
    else: 
        pass

Temps de mur: 6,76 ms


4 commentaires

pourquoi utiliser la comparaison au niveau du bit?


Vos instructions else: pass sont obsolètes, sauf si vous prévoyez de les utiliser plus tard.


Vous voulez utiliser np.where et définir x> 0 comme condition pour la branche if que vous avez actuellement. Je ne serais pas surpris si cela scanne l'intégralité du DF mais, eh bien, nous n'avons aucun exemple avec lequel tester


votre df.index est-il continu? c'est-à-dire, est-ce qu'il se compose d'entiers consécutifs? Que voulez-vous faire avec df2.loc [x, 'W'] = df2.loc [x-1, 'W'] ?


3 Réponses :


-4
votes

Malheureusement, il n'y a pas de moyen plus rapide.

Voici une recommandation: remplacez tous les et s de votre code par et s.

Cela n'aide peut-être pas tant que ça.

Vous devez utiliser un autre langage de programmation, comme C, C ++ ou Java, car le code compilé peut s'exécuter plus rapidement que le code interprété. Si vous êtes prêt à être vraiment frustré, vous pouvez essayer le langage d'assemblage, mais je ne suis pas sûr que cela en vaille la peine pour une simple boucle for.


4 commentaires

Ils ont oublié d'ajouter la balise pandas. Ce code peut presque certainement être poussé dans le temps C mais ils n'ont pas donné d'exemple testable. J'ai ajouté la balise maintenant.


Cela pourrait également gagner un peu en utilisant Cython, mais quoi qu'il en soit, c'est une question trop large pour SO.


@ CME1Crewmember, veuillez ne pas faire de déclarations si vous n'en êtes pas certain. La solution vectorisée Pythons peut être très rapide, en particulier la gestion des données, l'utilisation de pandas et de numpy


@AndyL. Il existe peut-être des moyens un peu plus rapides, mais j'ai dit qu'il n'y avait pas de moyen bon plus rapide. L'utilisation d'un autre langage de programmation peut faire la différence. Au moment de répondre, il n'a pas affiché le code complet. Je n'ai vu qu'un fragment et je ne pouvais donc pas suggérer une meilleure façon.



0
votes

En Python, l'opérateur & bit à bit ne court-circuite pas. Cela signifie que toutes vos comparaisons se produisent à chaque fois, quelle que soit la valeur des déclarations devant elles. Essayez ceci pour une démonstration:

a

Sorties:

bool(print('a')) and bool(print('b')) and bool(print('c'))

Comparez cela aux opérateurs logiques et , qui court-circuite la chaîne de comparaisons:

a
b
c

Sorties:

bool(print('a')) & bool(print('b')) & bool(print('c'))

Essayez de soustraire vos & code> s avec et s pour limiter le nombre de comparaisons effectuées.

Une fois que vous avez fait cela, vous pouvez essayer de jouer avec les comparaisons qui devraient venir en premier. Vous voudrez les classer par l'un ou l'autre / les deux, lesquels sont les plus susceptibles d'être évalués à False et lesquels sont les plus performants.


0 commentaires

0
votes

La première chose que vous voulez apprendre lorsque vous traitez avec le dataframe pandas est de visualiser les données dans leur ensemble et d'essayer de les traiter dans leur ensemble. Alors, explorons votre code et voyons comment nous pouvons l'améliorer.

idx_gt0 = (df.index > 0)
rank_filters = df2['DEF RANK'].eq(df2['OFF RANK'])
w_isnan = df2['W'].eq('nan')

# the next two conditions are more challenging:
# we start with looking at the series  df.loc[df.index-1, 'Event2']
df2['event2_shifted'] = df2.loc[df2.index-1, 'Event2'].values

event2_notnull = df2['event2_shifted'].notnull()
event2_notnan = df2['event2_shifted'].ne('nan')

# now we can merge all filters:
filters = (idx_gt0 & rank_filters 
           & w_isnan & event2_notnull & event2_notnan
          ) 

 # last assign:
 df2.loc[filters, 'W'] = df2.loc[df2.index - 1, 'W']

Alors, avec tous les commentaires, comment pouvons-nous écrire des codes plus rapides. En clair à partir de votre code:

for x in df2.index:   
    # the next if means you essentially want to look at 
    # df.index > 0 only
    if x > 0: 
        # this if clause chains several 'and' conditions:
        if (
            # this is df2['DEF RANK'].eq(df2['OFF RANK'])
            (df2.loc[x,'DEF RANK'] == df2.loc[x,'OFF RANK']) 

            # this is df2['W'].eq('nan')
            & (df2.loc[x,'W']=='nan')

            # this is df2.loc[df.index - 1, 'Event2'].notnull()
            & (pd.isnull(df2.loc[(x-1),'Event2']) == False)

            # this is df2.loc[df.index - 1, 'Event2'].ne('nan')
            & ((df2.loc[(x-1),'Event2'] == 'nan') == False)
        ):
            # here you copy some position to other position
            df2.loc[x,'W'] = df2.loc[(x-1),'W']

        # if you don't do anything after else, why not delete it?
        else: # if the above isn't true - pass
            pass
    else: 
        pass

Bien sûr, cela est littéralement traduit de votre code. Mais comme vous l'avez dit, votre code ne fonctionne pas correctement. Il serait donc utile de donner un exemple de données d'entrée et sa sortie attendue.


0 commentaires