-1
votes

Algorithme de chevauchement d'une étincelle à l'aide de DataFrames

donné une source de données avec champs: produit_id - produit - start_time - end_time

i J'essaie de construire la logique pour attraper des enregistrements se chevauchant pour le même produit (basé sur start_time et end_time ) en utilisant les fonctions deataframe. xxx

je voudrais recevoir en sortie xxx

car bouteille_1 a des temps de chevauchement avec bouteille_2 et bottle_3 , où 2 enregistrements se chevauchent si les conditions suivantes sont remplies:

  • max (a.start_time, b.start_time)
  • ! (A.Start_time == b.start_time && A.end_time == b.end_time)
  • a.start_time! = b.start_time || a.end_time! = B.end_time

    Lorsque les 2 dernières conditions précisent simplement que je ne suis pas intéressé par des cas dans lesquels start_time et end_time sont égaux (par exemple, CAN_1 et can_3 ne sont pas dans le résultat attendu même s'ils ont le même start_time et end_time ).

    pour comment Le problème est structuré est facile à penser à une solution avec MapReduce à l'aide de RDD, mais je suis intéressé par une solution avec DataFrames .

    indice : Il y a une chance que avec groupeby (). AGG () est possible de spécifier une condition intéressante qui atteint la logique décrite?

    Pour toute explication plus poussée N'hésitez pas à demander

    ne pas dupliquer de Comment agréger sur la fenêtre de temps de roulement avec des groupes dans une étincelle

    malheureusement dans la réponse déclarée a été utilisée f.lag , lequel Dans mon cas n'est pas assez bon état: F.Lag utilise une comparaison avec l'enregistrement précédent uniquement, mais dans l'exemple signalé ne fonctionnerait pas si désiré depuis que bouteille_1 ne serait pas signalé comme superposé avec < code> bouteille_3 car ils ne sont pas des enregistrements consécutifs


0 commentaires

3 Réponses :


2
votes

Chacune des conditions peut être traduite directement dans SQL

(df.alias("a").join(df.alias("b"), ["product"]).filter(cond1 & cond2 & cond3))


0 commentaires

0
votes

Essayez ceci:

+-----+---+---+------+----+----+
|label|min|max|label1|min1|max1|
+-----+---+---+------+----+----+
|    1|  2|  5|     2|   4|   7|
|    2|  4|  7|     3|   6|   9|
+-----+---+---+------+----+----+


4 commentaires

Merci beaucoup! Les deux solutions (votre et @ user11013893) m'ont aidé à résoudre mon problème! Votre solution a où ($ "étiquette" <$ "étiquette1") qui m'a aidé à éviter les résultats dupliqués, tandis que les autres ont fourni des fonctions plus intéressantes. Probablement le crossjoin n'était pas nécessaire: une jointure interne normale en fonction du produit (voir l'exemple) était suffisant. Je ne comprends pas pourquoi ma question a été votée (identique pour votre réponse que j'ai votée). Mais je pense que votre réponse était plus utile avec l'utilisation du dans où ($ "étiquette" <$ "label1") . Je vais accepter le vôtre


Pour aider la lisibilité de la réponse, pourriez-vous modifier votre message et vous rapprocher de l'exemple que j'ai signalé? Donc changer où ($ "étiquette" <$ "étiquette1") à sur où ($ "product_id" <$ "product_id1") , la jointe basée sur ... et ainsi de suite


Je suggère de mettre le code Python dans une réponse séparée car elle modifie complètement le style de programmation.


J'ai commencé à travailler avec ML avec Python, mais c'était trop dynamique pour moi. Scala est parfait (professionnellement, je me développe en Java);>



1
votes

basé sur @Andiconicus Solution J'ai créé cette approche dans Pure Python.

Il était nécessaire de rejoindre Le Dataframe avec lui-même pour vérifier si des rangées se chevauchent. Bien sûr, vous devez omettre auto-auto avec la condition df.product_id (deux lettres rangée et le chevauchement de produit S) .

tout le code: xxx


0 commentaires