2017-06-13 2 views
1

J'ai un data.frame que je voudrais sous-ensemble (par lignes) en "lots" (chevauchement), puis purrr:::map ces lots à une fonction. Dans l'exemple ci-dessous, d est le data.frame je voudrais sous-ensemble et lots:Sous-ensemble et reliure de ligne par les valeurs de colonne utilisant le schéma tidyverse

set.seed(19) 
n1 <- data.frame(c0= "N",c1 = rep("A",4),c2 = rep(c("i","j"),2), num = rnorm(4)) 
n2 <- data.frame(c0= "N", c1 = rep("B",6),c2 = rep(c("i","j"),3), num = rnorm(3)) 
y1 <- data.frame(c0 = "Y", c1 = rep("A",2),c2 = c("i","j"), num = rnorm(2)) 
y2 <- data.frame(c0 = "Y", c1 = rep("B",4),c2 = rep(c("i","j"),each = 2), num = rnorm(2)) 

d <- rbind(y1,y2,n1,n2) 

est ici d

# c0 c1 c2  num 
# 1 Y A i -0.7447795 
# 2 Y A j -0.2597870 
# 3 Y B i -0.1830838 
# 4 Y B i 0.5186300 
# 5 Y B j -0.1830838 
# 6 Y B j 0.5186300 
# 7 N A i -1.1894537 
# 8 N A j 0.3885812 
# 9 N A i -0.3443333 
# 10 N A j -0.5478961 
# 11 N B i 0.9806622 
# 12 N B j -0.2366460 
# 13 N B i 0.8097397 
# 14 N B j 0.9806622 
# 15 N B i -0.2366460 
# 16 N B j 0.8097397 

La recette subsetting est de

  1. sous-ensemble par c0 - > donner des groupes Y et N
  2. à l'intérieur c0=="N" sous-ensemble par c1 -> groupes donnant NA, NB
  3. sous-ensemble de chaque NA et NB par c2 -> donner des groupes NAi, NAj, NBi, NBj
  4. row_bind N?i-Y?i et N?j-Y?j (où ? est A ou B) -> donner les 4 derniers sous-ensembles de données

En R:

subset.Yi <- d %>% filter(c0=="Y"& c2=="i") 
subset.Yj <- d %>% filter(c0=="Y"& c2=="j") 

list(
    d1 = d %>% filter(c0=="N" & c1 == "A", c2 == "i") %>% rbind(subset.Yi), 
    d2 = d %>% filter(c0=="N" & c1 == "B", c2 == "i") %>% rbind(subset.Yi), 
    d3 = d %>% filter(c0=="N" & c1 == "A", c2 == "j") %>% rbind(subset.Yj), 
    d4 = d %>% filter(c0=="N" & c1 == "B", c2 == "j") %>% rbind(subset.Yj) 
) %>% 
tibble::tibble(batches = paste0("batch",1:length(.)),data = .) ->tmp 

Si correspondant par c2 était pas important que je pouvais faire quelque chose comme:

d %>% filter(.,c0 == "N") %>% 
    group_by(.,c1) %>% 
    do(batches = rbind(d[d$c0=="Y"],.)) -> tmp 

mais ce n'est pas tout à fait. Merci d'avance! BTW, je sais en dehors de tidyverse c'est faisable mais comme j'ai adopté tidyverse schéma pour le reste de mon code, j'espérais rester cohérent.

Répondre

0

Voici une solution qui fonctionne dans ce cas (bien que ce serait génial de voir une autre approche peut-être plus générale des autres).

tmp <- d %>% 
    group_by(c2) %>% 
    nest(.key = c2) %>% 
    mutate(c2 = map(c2,~ .x %>% 
        filter(.,c0 == "N") %>% 
        group_by (.,c1) %>% 
        do(batches = bind_rows(
         .x %>% filter(.,c0 == "Y") %>% select(-c1), 
         (.) %>% select(-c1) )) 
       )) 

tmp contient les quatre sous-ensembles. Je pouvais faire quelque chose comme

tmp %>% unnest(c2) %>% .$batches %>% map(.,~sum(.$num)) %>% unlist 

qui donne la colSum de la colonne num dans chacun des 4 sous-ensembles.

[1] -1.94302047 1.14452254 -0.08355576 1.62951506 

Side note: désélection c1 est techniquement pas nécessaire ici, mais depuis que je suis row_binding telle qu'une partie de dataframe ne tenait pas compte de la valeur c1 (voir recette ci-dessus de subsetting et notez ?), la valeur de c1 était confuse, donc je l'ai enlevé.