2017-06-06 2 views
0

J'ai une trame de données contenant deux colonnes: une variable de regroupement et une période d'intervalle sur laquelle la variable de regroupement est conservée. J'ai une autre trame de données avec une colonne de date et une colonne de valeur. Comment puis-je joindre ces deux tables un peu efficacement avec les fonctions dplyr + tidyverse?Comment effectuer une jointure en fonction des intervalles avec dplyr?

library(dplyr) 
library(lubridate) 
ty <- data_frame(date = mdy(paste(1, 1 + seq(20), 2017, sep = "/")), 
       y = c(rnorm(7), rnorm(7, mean = 2), rnorm(6, mean = -1))) 
gy <- data_frame(period = interval(mdy(c("01/01/2017", "01/08/2017", "01/15/2017")), 
            mdy(c("01/07/2017", "01/14/2017", "01/20/2017"))), 
          batch = c(1, 2, 3)) 

Je veux construire la table qui équivaut à:

ty %>% mutate(batch = c(rep(1, 7), rep(2, 7), rep(3, 6))) 

Idéalement, cela devrait fonctionner assez rapidement sur des ensembles de données jusqu'à 1.000.000 lignes. Mieux encore si cela fonctionne sur 100 000 000 :).

+3

cela ne répond pas à votre question ('dplyr'), mais comme un commentaire - vous devriez vérifier [roulement rejoint dans 'data.table'] (https://stackoverflow.com/questions/12030932/rolling-joins-data-table-in-r) – C8H10N4O2

Répondre

1

Que diriez-vous:

ty %>% 
    mutate(batch = case_when(
    ty$date %within% gy$period[1] ~gy$batch[1], 
    ty$date %within% gy$period[2] ~gy$batch[2], 
    ty$date %within% gy$period[3] ~gy$batch[3])) 

Vous serait évidemment nécessaire de définir les intervalles de case_when. Combien avez-vous? J'ai utilisé cat et paste0 avec un bon effet pour cela dans le passé.

Édité pour refléter les commentaires d'OP. Cela devrait prendre soin de l'ESN et permettrait à la génération des intervalles de case_when programatically:

ty %>% 
    mutate(batch = eval(parse(text = paste0("case_when(", 
             paste(
             paste0(
              "ty$date %within% gy$period[", 
              seq_along(gy$period), 
              "] ~gy$batch[", 
              seq_along(gy$period), 
              "]" 
             ), 
             collapse = ", " 
            ), ")")))) 
+0

C'est une bonne idée pour un nombre relativement petit de lots. J'ai ~ 10 000, cependant. Avec tout le NSE, je m'inquiète que cela ne fonctionnerait pas avec coller et eval, mais peut-être que je me trompe :) – wdkrnls

+1

Devrait fonctionner pour n'importe quelle longueur de lot maintenant. – biomiha

0

C'est le meilleur que je pouvais venir avec à ce jour:

ty$batch <- unlist(lapply(ty$date, function(d) gy$batch[which(d %within% gy$period)]), recursive = FALSE, use.names = FALSE) 

Mais il ne semble pas très rapide.