2016-05-03 1 views
1

Mon cadre de données comporte des colonnes que je souhaite diviser par des tirets, des lignes en double avec des caractères à gauche et à droite des tirets. Je sais comment scinder et dupliquer, mais je n'arrive pas à comprendre comment conserver certaines parties des cordes. Description assez terrible - je pense qu'il est juste plus facile de montrer la trame de données et la sortie désirée.R: fractionner et dupliquer une ligne

tmp = structure(list(Unit.Types = c("10 - 12 Pack 11.2 - 14.9 oz Bottle or Can", 
"8 - 12 Pack 11.5 - 16 oz Bottle or Can"), Row.Count = c("899", 
"305"), Test = c("B", "A")), .Names = c("Unit.Types", "Row.Count", 
"Test"), row.names = c(104L, 196L), class = "data.frame") 

library(tidyr) 
library(dplyr) 

tmp2 = tmp %>% mutate(Unit.Types = strsplit(as.character(Unit.Types), "-")) %>% unnest(Unit.Types) 
tmp2 

    Row.Count Test    Unit.Types 
1  899 B     10 
2  899 B   12 Pack 11.2 
3  899 B 14.9 oz Bottle or Can 
4  305 A      8 
5  305 A   12 Pack 11.5 
6  305 A 16 oz Bottle or Can 

Ma sortie désirée devrait ressembler à ceci:

        Unit.Types Row.Count Test 
1 10 Pack 11.2 oz Bottle or Can  899 B 
2 10 Pack 14.9 oz Bottle or Can  899 B 
3 12 Pack 11.2 oz Bottle or Can  899 B 
4 12 Pack 14.9 oz Bottle or Can  899 B 
5 8 Pack 11.5 oz Bottle or Can  305 A 
6 8 Pack 16 oz Bottle or Can  305 A 
7 12 Pack 11.5 oz Bottle or Can  305 A 
8 12 Pack 16 oz Bottle or Can  305 A 

Ou au moins comme ça, divisé par tableau de bord avec "oz"

        Unit.Types Row.Count Test 
1 10 - 12 Pack 11.2 oz Bottle or Can  899 B 
2 10 - 12 Pack 14.9 oz Bottle or Can  899 B 
3 8 - 12 Pack 11.5 oz Bottle or Can  305 A 
4 8 - 12 Pack 16 oz Bottle or Can  305 A 

Toute aide est grandement appréciée !!

+0

sont toutes les lignes de la forme « 10 - 12 Paquet 11,2 à 14,9 oz bouteille ou la canette »? – Stibu

+0

Peut également être "10 Pack 14 - 16 oz Can" –

Répondre

1

Jetez un oeil à cette fonction

f <- function(x){ 
    strsplit(x, " Pack | oz Bottle or Can")[[1]] %>% 
    strsplit(" - ") %>% 
    expand.grid() %>% 
    mutate(V = paste(Var1, "Pack", Var2, "oz Bottle or Can")) %>% 
    `[[`("V") 
} 

Il doit être appliqué à des chaînes qui sont dans la colonne Unit.Types. Exemple:

> f(tmp$Unit.Types[[1]]) 
[1] "10 Pack 11.2 oz Bottle or Can" "12 Pack 11.2 oz Bottle or Can" 
[3] "10 Pack 14.9 oz Bottle or Can" "12 Pack 14.9 oz Bottle or Can" 

Puis, avec cette fonction, nous pouvons faire ce qui suit:

ans <- tmp %>% split(1:nrow(tmp)) %>% 
lapply(function(x) data.frame(Unit.Types = f(x$Unit.Types), 
           Row.Count = x$Row.Count, 
           Test = x$Test 
          ) 
     ) %>% 
do.call(rbind, .) 
row.names(ans) <- NULL 

ans est notre data.frame souhaitée.

UPD Concernant votre commentaire: nous pouvons utiliser regex qui correspond à des paires de nombres séparés par ' - ', ou tout simplement des chiffres et réécrire f avec elle.

regex <- "[0-9]+(.[0-9]+)?(- [0-9]+(.[0-9]+)?)?" 

f <- function(x){ 
    m <- gregexpr(regex, x) 
    matches <- regmatches(x, m)[[1]] 
    nonmatches <- regmatches(x, m, invert = T)[[1]][-1] 
    strsplit(matches, " - ") %>% 
    expand.grid(stringsAsFactors = F) %>% 
    apply(MARGIN = 1, function(y) rbind(y, nonmatches) %>% 
            c %>% 
            paste(collapse = "")) 
} 

Cette fonction peut gérer même les chaînes avec trois ou plus de spécifications numéro:

> x <- "2 - 3 big packs of 10 - 12 Pack 11.2 - 14.9 oz Can" 
> f(x) 
[1] "2 big packs of 10 Pack 11.2 oz Can" "3 big packs of 10 Pack 11.2 oz Can" 
[3] "2 big packs of 12 Pack 11.2 oz Can" "3 big packs of 12 Pack 11.2 oz Can" 
[5] "2 big packs of 10 Pack 14.9 oz Can" "3 big packs of 10 Pack 14.9 oz Can" 
[7] "2 big packs of 12 Pack 14.9 oz Can" "3 big packs of 12 Pack 14.9 oz Can" 
+0

Merci! Cela fonctionne très bien avec "oz Bottle or Can" fin de chaîne. Dans des cas plus généraux, la fin est répétée deux fois (par exemple, la fin d'une chaîne peut être "blah .. 10 - 12 oz Can" ou autre forme - bouteille, fût, etc.). –