10
votes

Cycle itératif et hiérarchiquement à travers des rangées jusqu'à ce qu'une condition soit remplie

J'essaie de résoudre un problème de gestion des données dans R.

Supposons que mes données se ressemblent comme suit: P>

> df.end.result
       id  next.up is.cond.met origin
1  961980    20090        TRUE   <NA>
2   14788   655036       FALSE   <NA>
3  902460 40375164       FALSE   <NA>
4  900748 40031850       FALSE   <NA>
5  728912 40368996       FALSE   <NA>
6  141726   961980       FALSE 961980
7 1041190   141726       FALSE 961980
8  692268   760112       FALSE   <NA>


6 commentaires

Pouvez-vous ajouter quelques lignes de plus à l'exemple? Je ne suis pas sûr que je suive la logique


Essayez-vous de faire correspondre des entrées à partir de 2 données différentes? C'est le seul sens que je peux essayer de faire de cela. Si tel est le cas, il peut être utile de faire explicitement explicite.


@BryAngoggin Non. Les données sont comme dans df. DF.RESULT ne montre que ce que j'aimerais que le résultat final ressemble.


S'il y a une lacune dans les données que vous avez mentionnées dans l'exemple mis à jour, quel devrait être le résultat? L'algorithme devrait-elle rechercher le prochain sujet uniquement à la ligne suivante ou dans toutes les lignes suivantes? Et si la prochaine.UP est introuvable ce que l'algorithme devrait-il faire?


@ George91 Il devrait rechercher dans toutes les lignes suivantes (et / ou précédentes). Si aucune correspondance n'est trouvée, origine == na


Si vous voulez le faire efficacement, vous devez probablement stocker vos données dans une structure d'arborescence (prochaine-up étant le «parent» à un nœud donné) et utiliser une algo à traverser. Je ne suis pas informatique et je ne sais donc pas précisément le meilleur outil, mais cela semble prometteur: cran.r-project.org/web/packages/data.tree/vignettes/... Bien sûr, cela suppose que vos données ont un modicum de santé mentale (non Next.Up boucles, pas de lignes d'identification répétées).


3 Réponses :


5
votes

J'ai étendu votre exemple de données un peu pour montrer ce qui se passe avec plus de valeurs code> true code> dans is.cond.met code>. Utilisation du package DATA.TABLE. / CODE> Paquet, vous pouvez le faire:

id <- c("123", "414", "606", "119", "321", "507")
next.up <- c("414", "606", "119", "321", "507", "185")
is.cond.met <- c(FALSE, FALSE, TRUE, FALSE, TRUE, TRUE)

df <- data.frame(id, next.up, is.cond.met, stringsAsFactors = FALSE)


10 commentaires

Merci. Lors de l'adaptation du code sur les données réelles, j'obtiens l'erreur suivante: Type de RHS ('Caractère') doit correspondre à LHS ('INTEGER'). Pour vérifier et contraindre aurait trop d'impact sur la performance pour les cas les plus rapides. Soit modifier le type de la colonne cible ou coerce le RHS de: = vous-même (par exemple en utilisant 1L au lieu de 1)


@Thomasspeidel Avez-vous converti les colonnes comme je l'ai dit dans la note ?


@Thomasspeidel Quel est le résultat de sapply (df, classe) ?


J'ai fait. > SAPPLY (DF.TEST, CLASS) ID NOW.UP IS.COND.MET GRP Origine "caractère" "caractère" "logique" "INTEGER" "INTEGER"


@Thomasspeidel Pourriez-vous inclure un échantillon de vos données réelles dans la question? (de préférence la sortie de par exemple dput (tête (df.test, 10)) )


Pour certaines raisons, le code fonctionne si je filtre les données d'origine. Mais produit la mauvaise "origine" lorsque je ne le filtre pas. Est-ce que la commande de tri dans la mesure de données est-elle fournie?


@Thomasspeidel à la suite de la façon dont vous avez présenté les exemples de données, la commande aime dans l'approche que j'ai donnée ci-dessus. Si vous ne pouvez pas partager (une partie de) vos données réelles, pourriez-vous construire un exemple de jeu de données mieux imiter vos données et vos problèmes réels? Sans exemple qui reproduit le problème, il est assez difficile de dire comment résoudre ce problème.


Merci. Il est difficile de capturer les idiosyncrasies de données tout en préservant la confidentialité, maximisant la brièveté et la clarté ;-). Mes données ne sont pas triées. J'ai édité la question à inclure un meilleur exemple.


@Thomasspeidel J'ai inclus la sortie de mon code sur l'exemple mis à jour. Pourriez-vous indiquer si c'est la sortie que vous attendiez? Si ce n'est pas le cas, pourriez-vous indiquer dans lequel les rangées devraient donner un résultat différent (et de quelle manière)?


J'ai inclus une autre mise à jour avec ce que cela devrait ressembler



3
votes

Donc, IMHO, je pense que vous ne pouvez pas le résoudre sans une mise à jour interamène.

Semblable à @ procrastinatus-maximus Voici une solution itérative avec dplyr code> p>

> dfIterated
       id  next.up is.cond.met cond.origin.node cond.update
1  961980    20090        TRUE             <NA>        TRUE
2   14788   655036          NA             <NA>          NA
3  902460 40375164          NA             <NA>          NA
4  900748 40031850          NA             <NA>          NA
5  728912 40368996          NA             <NA>          NA
6  141726   961980        TRUE           961980        TRUE
7 1041190   141726        TRUE           961980        TRUE
8  692268   760112          NA             <NA>          NA


6 commentaires

C'est presque ce que je veux, à l'exception de la ligne 1 devrait être évalué à manquer car dès que la condition est remplie, Origine ne doit pas évaluer à Next.Up . Voir ma mise à jour. Cela devrait être trivial à réparer. Mes données sont énormes, alors j'espère que cette approche est rapide! Je vais tester sur les données réelles et rapportera.


Fait intéressant, ce n'est pas que trivial corriger :-) puisqu'il briserait les hypothèses de l'algorithme - mais nous pouvons heureusement que nous puissions le stocker au début et remplacer l'origine à la fin en conséquence. (Edits fabriqués dans le code). La complexité de stockage supplémentaire est en O (2n) puisque nous n'avons pas besoin de 3 + 3 colonnes supplémentaires - cela signifie que si vous chargez que vous vous chargez dplyr :: if_else pour un traitement plus rapide au lieu de ifelse . L'algorithme doit s'arrêter après que le nœud le plus profond ait été atteint.


BTW Si vos données sont supérieures à 10 Go, vous pouvez passer à Data.Table. Ce sera définitivement plus rapide - le principe restera le même mais la syntaxe sera différente.


Mise à jour: J'ai toujours des problèmes avec le code proposé. Cela fonctionne bien dans l'exemple. Cependant, cela ne fonctionne pas comme prévu sur les données réelles. J'ai du mal à comprendre pourquoi.


Étant donné que la prime est sur le point d'expirer, je l'attribuerai à @Drey, car sa solution me reçoit le plus proche de ce que j'essaie de réaliser.


Merci! Pouvez-vous décrire plus en détail ce qui vous trouble avec les données réelles?



3
votes

J'espère que j'ai compris votre problème correctement et voici mon point de vue. Il semble que vous essayiez de résoudre un problème de réseau en termes de tables de données. Je suggère la formulation suivante.

Nous avons un réseau, défini comme un ensemble d'arêtes (colonnes ID code> et suivant.up code> correspond à vertex_from code > et vertex_to code>). Le réseau est un ensemble d'arbres. Colonne is.cond.met code> Les sommets des cartes qui sont des points finaux ou des racines des arbres. Les arbres avec une racine non accomplie ne sont pas pris en compte. P>

J'ai légèrement modifié votre MRE pour le rendre plus démonstratif. P>

df0 <- data.frame(id = c("961980", "14788", "902460", "900748", "728912", "141726", "1041190", "692268"),
                  next.up = c("20090", "655036", "40375164", "40031850", "40368996", "961980", "141726", "760112"),
                  is.cond.met = c(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE), stringsAsFactors = FALSE)

df0 %>% add_origin

#         id  next.up is.cond.met origin
# 1:  961980    20090        TRUE     NA
# 2:   14788   655036       FALSE     NA
# 3:  902460 40375164       FALSE     NA
# 4:  900748 40031850       FALSE     NA
# 5:  728912 40368996       FALSE     NA
# 6:  141726   961980       FALSE 961980
# 7: 1041190   141726       FALSE 961980
# 8:  692268   760112       FALSE     NA


0 commentaires